Compare commits
182 Commits
Author | SHA1 | Date | |
---|---|---|---|
7b4d13b73e | |||
2909aa1656 | |||
64131b6764 | |||
0b78d75a21 | |||
b35c342960 | |||
24c858d379 | |||
b8a31a8be9 | |||
02c30d6454 | |||
985f003e6d | |||
98045e1e2e | |||
5762ce58a4 | |||
2787ee71fc | |||
e61a6df4d7 | |||
0a5c2ecbf5 | |||
6bfab696ad | |||
928f2dd496 | |||
bcf75892f7 | |||
594761385f | |||
d05fba06ec | |||
25155b1b38 | |||
ded6c9c199 | |||
c62e6c0045 | |||
b3feda9fd1 | |||
7ef8e2c8b8 | |||
d5ff211871 | |||
51c23e3842 | |||
557b30815e | |||
145459bfc3 | |||
f97a6a2bee | |||
1134422891 | |||
6012275c7b | |||
2f07063375 | |||
310d1ed485 | |||
a48edbb16e | |||
d6258409fc | |||
1b94b1247b | |||
9ef63ae60e | |||
f99de4be48 | |||
80fd1820c2 | |||
0a4a983d20 | |||
c2cc830691 | |||
4d0490d1c6 | |||
02d1838547 | |||
5c6edff778 | |||
7cbca32ddd | |||
8950e315f8 | |||
a703df40c0 | |||
225fce8810 | |||
bdc0f0fcdd | |||
5bbb8c4858 | |||
35b9551bfb | |||
c8c5a05b39 | |||
2771f0301a | |||
c4f04edc59 | |||
5530422846 | |||
ce77c81fb5 | |||
bc488d4ac2 | |||
fe72a10346 | |||
0da88398b4 | |||
c42de3da20 | |||
4bf9f36baa | |||
380cb192c7 | |||
8882e19ec5 | |||
7f52059b98 | |||
1ce3cc4d7c | |||
657c71e94d | |||
c8cfb3c7b7 | |||
6e7e90acf4 | |||
6d3a556d34 | |||
7d9188b659 | |||
4f0a805c79 | |||
53f3320492 | |||
f9ce51b4a5 | |||
f8bf432c0d | |||
a822482172 | |||
b22f8a0b02 | |||
227331bf24 | |||
744688cbe1 | |||
79c8126c4a | |||
0b7c8e4ef7 | |||
35e00f61d8 | |||
aba3d58df8 | |||
45984a8166 | |||
ea5655ae42 | |||
f06cb0dfbb | |||
1abae55976 | |||
a83ed40ec4 | |||
75ecae4672 | |||
16a6f942c5 | |||
aa98508e57 | |||
583383aee1 | |||
13f69f81d7 | |||
43c34fcd64 | |||
c272238539 | |||
6e0d2706a8 | |||
25a7289ce8 | |||
1ba7d045e4 | |||
a4d75befe7 | |||
88377529bc | |||
91b9a0280f | |||
25173ae85c | |||
ad3350705e | |||
a16bc5db28 | |||
51657338f5 | |||
0fe3ea25af | |||
806daaf7c9 | |||
21ff4a83b5 | |||
ecc9aa40d7 | |||
c34ca2a59b | |||
dde7094fe3 | |||
105afdfefc | |||
4c254a8686 | |||
33ca203e57 | |||
2ff4133cd4 | |||
49ad85713e | |||
1978bf151f | |||
506378de82 | |||
53ead7a03f | |||
ab979fd63c | |||
1e84a2238b | |||
5618adf86c | |||
345b0bc95f | |||
b1d6c35e99 | |||
d767f1a101 | |||
c15f2b9a12 | |||
a21a53662b | |||
ebb5340019 | |||
6108bd214e | |||
eed27e101a | |||
2767680bed | |||
4080e30b6f | |||
e89257be62 | |||
d3c40a7e8b | |||
60657d5d25 | |||
71d5ae0e68 | |||
46b8d202c7 | |||
bc193a6470 | |||
577528fa0a | |||
35e78ea633 | |||
d5d4f85003 | |||
c6a49a6f5d | |||
a3ff9373a2 | |||
e6d2e74b17 | |||
e8464206e7 | |||
b6c4934123 | |||
8ee83f738b | |||
c359300375 | |||
eb3361fa07 | |||
1b53da6749 | |||
c701895e29 | |||
e81222821e | |||
cbca8c9e93 | |||
92c4edacf2 | |||
e4c648ee92 | |||
69f6586aa9 | |||
391713b84d | |||
8c6a25e4b4 | |||
250701aff0 | |||
2dfd1bd5a2 | |||
1c7380d4cf | |||
68d9ac88b3 | |||
f6b3874668 | |||
c616878a64 | |||
ad485a68ce | |||
2ebba3b8e7 | |||
4117e6e1c5 | |||
423ee04879 | |||
1625e3ba6c | |||
5a71ab3c20 | |||
b5833bf556 | |||
6c31765965 | |||
6dc1d42d90 | |||
e273a954e6 | |||
a602a942c4 | |||
dd32b33621 | |||
355d0405f4 | |||
c1e1595d58 | |||
ef476ac9b3 | |||
a7aaa7b18b | |||
3abfbab5d1 | |||
b158474e21 | |||
cfbcc41543 |
11
.gitignore
vendored
11
.gitignore
vendored
@ -12,9 +12,7 @@ msbuild.binlog
|
|||||||
*.idea
|
*.idea
|
||||||
|
|
||||||
Oqtane.Server/appsettings.json
|
Oqtane.Server/appsettings.json
|
||||||
Oqtane.Server/Data/*.mdf
|
Oqtane.Server/Data
|
||||||
Oqtane.Server/Data/*.ldf
|
|
||||||
Oqtane.Server/Data/*.db
|
|
||||||
|
|
||||||
/Oqtane.Server/Properties/PublishProfiles/FolderProfile.pubxml
|
/Oqtane.Server/Properties/PublishProfiles/FolderProfile.pubxml
|
||||||
Oqtane.Server/Content
|
Oqtane.Server/Content
|
||||||
@ -22,3 +20,10 @@ Oqtane.Server/Packages
|
|||||||
Oqtane.Server/wwwroot/Content
|
Oqtane.Server/wwwroot/Content
|
||||||
Oqtane.Server/wwwroot/Packages/*.log
|
Oqtane.Server/wwwroot/Packages/*.log
|
||||||
|
|
||||||
|
Oqtane.Server/wwwroot/Modules
|
||||||
|
!Oqtane.Server/wwwroot/Modules/Oqtane.Modules.*
|
||||||
|
!Oqtane.Server/wwwroot/Modules/Templates
|
||||||
|
|
||||||
|
Oqtane.Server/wwwroot/Themes
|
||||||
|
!Oqtane.Server/wwwroot/Themes/Oqtane.Themes.*
|
||||||
|
!Oqtane.Server/wwwroot/Themes/Templates
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.Extensions.Localization
|
namespace Microsoft.Extensions.Localization
|
||||||
{
|
{
|
||||||
public static class OqtaneLocalizationExtensions
|
public static class OqtaneLocalizationExtensions
|
||||||
@ -18,5 +20,42 @@ namespace Microsoft.Extensions.Localization
|
|||||||
}
|
}
|
||||||
return localizedValue;
|
return localizedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an IStringLocalizer based on a type name. This extension method is useful in scenarios where the default IStringLocalizer is unable to locate the resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localizerFactory"></param>
|
||||||
|
/// <param name="fullTypeName">the full type name ie. GetType().FullName</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IStringLocalizer Create(this IStringLocalizerFactory localizerFactory, string fullTypeName)
|
||||||
|
{
|
||||||
|
var typename = fullTypeName;
|
||||||
|
|
||||||
|
// handle generic types
|
||||||
|
var type = Type.GetType(fullTypeName);
|
||||||
|
if (type.IsGenericType)
|
||||||
|
{
|
||||||
|
typename = type.GetGenericTypeDefinition().FullName;
|
||||||
|
typename = typename.Substring(0, typename.IndexOf("`")); // remove generic type info
|
||||||
|
}
|
||||||
|
|
||||||
|
// format typename
|
||||||
|
if (typename.Contains(","))
|
||||||
|
{
|
||||||
|
typename = typename.Substring(0, typename.IndexOf(",")); // remove assembly info
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove rootnamespace
|
||||||
|
var rootnamespace = "";
|
||||||
|
var attributes = type.Assembly.GetCustomAttributes(typeof(RootNamespaceAttribute), false);
|
||||||
|
if (attributes.Length > 0)
|
||||||
|
{
|
||||||
|
rootnamespace = ((RootNamespaceAttribute)attributes[0]).RootNamespace;
|
||||||
|
}
|
||||||
|
typename = typename.Replace(rootnamespace + ".", "");
|
||||||
|
|
||||||
|
// create IStringLocalizer using factory
|
||||||
|
return localizerFactory.Create(typename, type.Assembly.GetName().Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
|
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="pwd" type="password" class="form-control" @bind="@_pwd" />
|
<input id="pwd" type="password" class="form-control" @bind="@_pwd" autocomplete="new-password" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
|
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="pwd" type="password" class="form-control" @bind="@_pwd" />
|
<input id="pwd" type="password" class="form-control" @bind="@_pwd" autocomplete="new-password" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="server" HelpText="Enter the database server" ResourceKey="Server">Server:</Label>
|
<Label Class="col-sm-3" For="server" HelpText="Enter the database server name. This might include a port number as well if you are using a cloud service (ie. servername.database.windows.net,1433) " ResourceKey="Server">Server:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="server" type="text" class="form-control" @bind="@_server" />
|
<input id="server" type="text" class="form-control" @bind="@_server" />
|
||||||
</div>
|
</div>
|
||||||
@ -35,7 +35,7 @@
|
|||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
|
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="pwd" type="password" class="form-control" @bind="@_pwd" />
|
<input id="pwd" type="password" class="form-control" @bind="@_pwd" autocomplete="new-password" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@
|
|||||||
@if (_encryption == "true")
|
@if (_encryption == "true")
|
||||||
{
|
{
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="trustservercertificate" HelpText="Specify the type of certificate you are using for encryption" ResourceKey="TrustServerCertificate">Certificate:</Label>
|
<Label Class="col-sm-3" For="trustservercertificate" HelpText="Specify the type of certificate you are using for encryption. Verifiable is equivalent to False. Self Signed is equivalent to True." ResourceKey="TrustServerCertificate">Certificate:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="encryption" class="form-select custom-select" @bind="@_trustservercertificate">
|
<select id="encryption" class="form-select custom-select" @bind="@_trustservercertificate">
|
||||||
<option value="true">@Localizer["Self Signed"]</option>
|
<option value="true">@Localizer["Self Signed"]</option>
|
||||||
|
@ -26,29 +26,42 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@if (_databases != null)
|
@if (_databases != null)
|
||||||
{
|
{
|
||||||
<select id="databasetype" class="form-select custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
<div class="input-group">
|
||||||
@foreach (var database in _databases)
|
<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">@Localizer[@database.Name]</option>
|
||||||
<option value="@database.Name" selected>@Localizer[@database.Name]</option>
|
}
|
||||||
}
|
</select>
|
||||||
else
|
@if (!_showConnectionString)
|
||||||
{
|
{
|
||||||
<option value="@database.Name">@Localizer[@database.Name]</option>
|
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionString"]</button>
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
</select>
|
{
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionParameters"]</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@{
|
@if (!_showConnectionString)
|
||||||
if (_databaseConfigType != null)
|
{
|
||||||
{
|
if (_databaseConfigType != null)
|
||||||
@DatabaseConfigComponent;
|
{
|
||||||
}
|
@DatabaseConfigComponent
|
||||||
}
|
}
|
||||||
</div>
|
}
|
||||||
|
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">String:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="connectionstring" class="form-control" @bind="@_connectionString" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<h2>@Localizer["ApplicationAdmin"]</h2><br />
|
<h2>@Localizer["ApplicationAdmin"]</h2><br />
|
||||||
@ -62,13 +75,19 @@
|
|||||||
<div class="row mb-1 align-items-center">
|
<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>
|
<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="col-sm-9">
|
||||||
<input id="password" type="password" class="form-control" @bind="@_hostPassword" />
|
<div class="input-group">
|
||||||
|
<input id="password" type="@_passwordType" class="form-control" @bind="@_hostPassword" autocomplete="new-password" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglePassword</button>
|
||||||
|
</div>
|
||||||
</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="confirm" HelpText="Please confirm the password entered above by entering it again" ResourceKey="Confirm">Confirm:</Label>
|
<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="col-sm-9">
|
||||||
<input id="confirm" type="password" class="form-control" @bind="@_confirmPassword" />
|
<div class="input-group">
|
||||||
|
<input id="confirm" type="@_confirmPasswordType" class="form-control" @bind="@_confirmPassword" autocomplete="new-password" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@ToggleConfirmPassword">@_toggleConfirmPassword</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@ -101,9 +120,15 @@
|
|||||||
private Type _databaseConfigType;
|
private Type _databaseConfigType;
|
||||||
private object _databaseConfig;
|
private object _databaseConfig;
|
||||||
private RenderFragment DatabaseConfigComponent { get; set; }
|
private RenderFragment DatabaseConfigComponent { get; set; }
|
||||||
|
private bool _showConnectionString = false;
|
||||||
|
private string _connectionString = string.Empty;
|
||||||
|
|
||||||
private string _hostUsername = string.Empty;
|
private string _hostUsername = string.Empty;
|
||||||
private string _hostPassword = 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 _confirmPassword = string.Empty;
|
||||||
private string _hostEmail = string.Empty;
|
private string _hostEmail = string.Empty;
|
||||||
private bool _register = true;
|
private bool _register = true;
|
||||||
@ -112,6 +137,9 @@
|
|||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
_togglePassword = SharedLocalizer["ShowPassword"];
|
||||||
|
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
||||||
|
|
||||||
_databases = await DatabaseService.GetDatabasesAsync();
|
_databases = await DatabaseService.GetDatabasesAsync();
|
||||||
if (_databases.Exists(item => item.IsDefault))
|
if (_databases.Exists(item => item.IsDefault))
|
||||||
{
|
{
|
||||||
@ -129,7 +157,7 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_databaseName = (string)eventArgs.Value;
|
_databaseName = (string)eventArgs.Value;
|
||||||
|
_showConnectionString = false;
|
||||||
LoadDatabaseConfigComponent();
|
LoadDatabaseConfigComponent();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -166,9 +194,16 @@
|
|||||||
private async Task Install()
|
private async Task Install()
|
||||||
{
|
{
|
||||||
var connectionString = String.Empty;
|
var connectionString = String.Empty;
|
||||||
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
if (_showConnectionString)
|
||||||
{
|
{
|
||||||
connectionString = databaseConfigControl.GetConnectionString();
|
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("@"))
|
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
||||||
@ -212,10 +247,48 @@
|
|||||||
{
|
{
|
||||||
_message = Localizer["Message.Password.Invalid"];
|
_message = Localizer["Message.Password.Invalid"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = Localizer["Message.Require.DbInfo"];
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
Module module = await ModuleService.GetModuleAsync(ModuleState.ModuleId);
|
Module module = await ModuleService.GetModuleAsync(ModuleState.ModuleId);
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
string message = string.Format(Localizer["Error.Module.Load"], module.ModuleDefinitionName);
|
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], module.ModuleDefinitionName), MessageType.Error);
|
||||||
AddModuleMessage(message, MessageType.Error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await logger.LogCritical("Error Loading Module {Module}", module);
|
await logger.LogCritical("Error Loading Module {Module}", module);
|
||||||
|
@ -56,6 +56,10 @@ else
|
|||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
_jobs = await JobService.GetJobsAsync();
|
_jobs = await JobService.GetJobsAsync();
|
||||||
|
if (_jobs.Count == 0)
|
||||||
|
{
|
||||||
|
AddModuleMessage(string.Format(Localizer["Message.NoJobs"], NavigateUrl("admin/system")), MessageType.Warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string DisplayStatus(bool isEnabled, bool isExecuting)
|
private string DisplayStatus(bool isEnabled, bool isExecuting)
|
||||||
|
@ -20,6 +20,7 @@ else
|
|||||||
@if (_availableCultures.Count() == 0)
|
@if (_availableCultures.Count() == 0)
|
||||||
{
|
{
|
||||||
<ModuleMessage Type="MessageType.Info" Message="@_message"></ModuleMessage>
|
<ModuleMessage Type="MessageType.Info" Message="@_message"></ModuleMessage>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -31,7 +32,7 @@ else
|
|||||||
<select id="_code" class="form-select" @bind="@_code" required>
|
<select id="_code" class="form-select" @bind="@_code" required>
|
||||||
@foreach (var culture in _availableCultures)
|
@foreach (var culture in _availableCultures)
|
||||||
{
|
{
|
||||||
<option value="@culture.Name">@culture.DisplayName</option>
|
<option value="@culture.Name">@(culture.DisplayName + " (" + culture.Name + ")")</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -47,11 +48,11 @@ else
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveLanguage">@SharedLocalizer["Save"]</button>
|
<button type="button" class="btn btn-success" @onclick="SaveLanguage">@SharedLocalizer["Save"]</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Download" ResourceKey="Download" Security="SecurityAccessLevel.Host">
|
<TabPanel Name="Translations" Heading="Translations" ResourceKey="Download" Security="SecurityAccessLevel.Host">
|
||||||
<div class="row justify-content-center mb-3">
|
<div class="row justify-content-center mb-3">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
@ -78,6 +79,7 @@ else
|
|||||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||||
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||||
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||||
|
@((MarkupString)(!string.IsNullOrEmpty(context.PackageUrl) ? " | " + SharedLocalizer["Search.Source"] + ": <strong>" + new Uri(context.PackageUrl).Host + "</strong>" : ""))
|
||||||
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 1px; vertical-align: middle;">
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
@ -113,7 +115,7 @@ else
|
|||||||
<TabPanel Name="Upload" ResourceKey="Upload" Security="SecurityAccessLevel.Host">
|
<TabPanel Name="Upload" ResourceKey="Upload" Security="SecurityAccessLevel.Host">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" HelpText="Upload one or more translations. Once they are uploaded click Install to complete the installation." ResourceKey="LanguageUpload">Language: </Label>
|
<Label Class="col-sm-3" HelpText="Upload one or more translations. Once they are uploaded click Install to complete the installation." ResourceKey="LanguageUpload">Translation: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" />
|
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" />
|
||||||
</div>
|
</div>
|
||||||
@ -159,33 +161,32 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
|
|
||||||
private string _code = string.Empty;
|
private string _code = string.Empty;
|
||||||
private string _isDefault = "False";
|
private string _isDefault = "False";
|
||||||
private string _message;
|
private string _message;
|
||||||
private IEnumerable<Culture> _supportedCultures;
|
private IEnumerable<Culture> _supportedCultures;
|
||||||
private IEnumerable<Culture> _availableCultures;
|
private IEnumerable<Culture> _availableCultures;
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
private string _price = "free";
|
private string _price = "free";
|
||||||
private string _search = "";
|
private string _search = "";
|
||||||
private string _productname = "";
|
private string _productname = "";
|
||||||
private string _license = "";
|
private string _license = "";
|
||||||
private string _packageid = "";
|
private string _packageid = "";
|
||||||
private string _version = "";
|
private string _version = "";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
||||||
var languagesCodes = languages.Select(l => l.Code).ToList();
|
var languagesCodes = languages.Select(l => l.Code).ToList();
|
||||||
|
|
||||||
_supportedCultures = await LocalizationService.GetCulturesAsync();
|
_supportedCultures = await LocalizationService.GetCulturesAsync();
|
||||||
_availableCultures = _supportedCultures
|
_availableCultures = _supportedCultures.Where(c => !c.Name.Equals(Constants.DefaultCulture) && !languagesCodes.Contains(c.Name));
|
||||||
.Where(c => !c.Name.Equals(Constants.DefaultCulture) && !languagesCodes.Contains(c.Name));
|
await LoadTranslations();
|
||||||
await LoadTranslations();
|
|
||||||
|
|
||||||
if (_supportedCultures.Count() == 1)
|
if (_supportedCultures.Count() == 1)
|
||||||
{
|
{
|
||||||
|
@ -19,15 +19,17 @@ else
|
|||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>@SharedLocalizer["Name"]</th>
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
<th>@Localizer["Code"]</th>
|
<th>@Localizer["Code"]</th>
|
||||||
|
<th>@Localizer["Translation"]</th>
|
||||||
<th>@Localizer["Default"]</th>
|
<th>@Localizer["Default"]</th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionDialog Header="Delete Language" Message="@string.Format(Localizer["Confirm.Language.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteLanguage(context))" Disabled="@((context.IsDefault && _languages.Count > 2) || context.Code == Constants.DefaultCulture)" ResourceKey="DeleteLanguage" /></td>
|
<td><ActionDialog Header="Delete Language" Message="@string.Format(Localizer["Confirm.Language.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteLanguage(context))" Disabled="@((context.IsDefault && _languages.Count > 2) || context.Code == Constants.DefaultCulture)" ResourceKey="DeleteLanguage" /></td>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Code</td>
|
<td>@context.Code</td>
|
||||||
<td><TriStateCheckBox Value="@(context.IsDefault)" Disabled="true"></TriStateCheckBox></td>
|
<td>@context.Version</td>
|
||||||
<td>
|
<td><TriStateCheckBox Value="@(context.IsDefault)" Disabled="true"></TriStateCheckBox></td>
|
||||||
|
<td>
|
||||||
@if (UpgradeAvailable(context.Code))
|
@if (UpgradeAvailable(context.Code))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadLanguage(context.Code))>@SharedLocalizer["Upgrade"]</button>
|
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadLanguage(context.Code))>@SharedLocalizer["Upgrade"]</button>
|
||||||
@ -50,9 +52,6 @@ else
|
|||||||
var cultures = await LocalizationService.GetCulturesAsync();
|
var cultures = await LocalizationService.GetCulturesAsync();
|
||||||
var culture = cultures.First(c => c.Name.Equals(Constants.DefaultCulture));
|
var culture = cultures.First(c => c.Name.Equals(Constants.DefaultCulture));
|
||||||
|
|
||||||
// Adds English as default language
|
|
||||||
_languages.Insert(0, new Language { Name = culture.DisplayName, Code = culture.Name, IsDefault = !_languages.Any(l => l.IsDefault) });
|
|
||||||
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
_packages = await PackageService.GetPackagesAsync("translation");
|
_packages = await PackageService.GetPackagesAsync("translation");
|
||||||
@ -81,10 +80,10 @@ else
|
|||||||
var upgradeavailable = false;
|
var upgradeavailable = false;
|
||||||
if (_packages != null)
|
if (_packages != null)
|
||||||
{
|
{
|
||||||
var package = _packages.Where(item => item.PackageId == (Constants.PackageId + ".Client." + code)).FirstOrDefault();
|
var package = _packages.Where(item => item.PackageId == ("Oqtane.Client." + code)).FirstOrDefault();
|
||||||
if (package != null)
|
if (package != null)
|
||||||
{
|
{
|
||||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) > 0);
|
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_togglepassword = Localizer["ShowPassword"];
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
|
||||||
if (PageState.Site.Settings.ContainsKey("LoginOptions:AllowSiteLogin") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:AllowSiteLogin"]))
|
if (PageState.Site.Settings.ContainsKey("LoginOptions:AllowSiteLogin") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:AllowSiteLogin"]))
|
||||||
{
|
{
|
||||||
@ -117,22 +117,47 @@
|
|||||||
_username = PageState.QueryString["name"];
|
_username = PageState.QueryString["name"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PageState.QueryString.ContainsKey("token"))
|
if (PageState.QueryString.ContainsKey("token") && !string.IsNullOrEmpty(_username))
|
||||||
{
|
{
|
||||||
var user = new User();
|
var user = new User();
|
||||||
user.SiteId = PageState.Site.SiteId;
|
user.SiteId = PageState.Site.SiteId;
|
||||||
user.Username = _username;
|
user.Username = _username;
|
||||||
user = await UserService.VerifyEmailAsync(user, PageState.QueryString["token"]);
|
|
||||||
|
|
||||||
if (user != null)
|
if (PageState.QueryString.ContainsKey("key"))
|
||||||
{
|
{
|
||||||
await logger.LogInformation(LogFunction.Security, "Email Verified For For Username {Username}", _username);
|
user = await UserService.LinkUserAsync(user, PageState.QueryString["token"], PageState.Site.Settings["ExternalLogin:ProviderType"], PageState.QueryString["key"], PageState.Site.Settings["ExternalLogin:ProviderName"]);
|
||||||
AddModuleMessage(Localizer["Success.Account.Verified"], MessageType.Info);
|
if (user != null)
|
||||||
|
{
|
||||||
|
await logger.LogInformation(LogFunction.Security, "External Login Linkage Successful For Username {Username}", _username);
|
||||||
|
AddModuleMessage(Localizer["Success.Account.Linked"], MessageType.Info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await logger.LogError(LogFunction.Security, "External Login Linkage Failed For Username {Username}", _username);
|
||||||
|
AddModuleMessage(Localizer["Message.Account.NotLinked"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
_username = "";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await logger.LogError(LogFunction.Security, "Email Verification Failed For Username {Username}", _username);
|
user = await UserService.VerifyEmailAsync(user, PageState.QueryString["token"]);
|
||||||
AddModuleMessage(Localizer["Message.Account.NotVerfied"], MessageType.Warning);
|
if (user != null)
|
||||||
|
{
|
||||||
|
await logger.LogInformation(LogFunction.Security, "Email Verified For For Username {Username}", _username);
|
||||||
|
AddModuleMessage(Localizer["Success.Account.Verified"], MessageType.Info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await logger.LogError(LogFunction.Security, "Email Verification Failed For Username {Username}", _username);
|
||||||
|
AddModuleMessage(Localizer["Message.Account.NotVerified"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (PageState.QueryString.ContainsKey("status"))
|
||||||
|
{
|
||||||
|
AddModuleMessage(Localizer["ExternalLoginStatus." + PageState.QueryString["status"]], MessageType.Info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,11 +184,11 @@
|
|||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
if (await interop.FormValid(login))
|
if (await interop.FormValid(login))
|
||||||
{
|
{
|
||||||
var user = new User { SiteId = PageState.Site.SiteId, Username = _username, Password = _password};
|
var user = new User { SiteId = PageState.Site.SiteId, Username = _username, Password = _password, LastIPAddress = SiteState.RemoteIPAddress};
|
||||||
|
|
||||||
if (!twofactor)
|
if (!twofactor)
|
||||||
{
|
{
|
||||||
user = await UserService.LoginUserAsync(user, false, false);
|
user = await UserService.LoginUserAsync(user);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -174,23 +199,14 @@
|
|||||||
{
|
{
|
||||||
await logger.LogInformation(LogFunction.Security, "Login Successful For Username {Username}", _username);
|
await logger.LogInformation(LogFunction.Security, "Login Successful For Username {Username}", _username);
|
||||||
|
|
||||||
if (PageState.Runtime == Oqtane.Shared.Runtime.Server)
|
// post back to the Login page so that the cookies are set correctly
|
||||||
{
|
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
|
||||||
// server-side Blazor needs to post to the Login page so that the cookies are set correctly
|
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
|
||||||
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
|
await interop.SubmitForm(url, fields);
|
||||||
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
|
|
||||||
await interop.SubmitForm(url, fields);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
|
|
||||||
authstateprovider.NotifyAuthenticationChanged();
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl(_returnUrl, true));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (user.TwoFactorRequired)
|
if ((PageState.Site.Settings.ContainsKey("LoginOptions:TwoFactor") && PageState.Site.Settings["LoginOptions:TwoFactor"] == "required") || user.TwoFactorRequired)
|
||||||
{
|
{
|
||||||
twofactor = true;
|
twofactor = true;
|
||||||
validated = false;
|
validated = false;
|
||||||
@ -282,12 +298,12 @@
|
|||||||
if (_passwordtype == "password")
|
if (_passwordtype == "password")
|
||||||
{
|
{
|
||||||
_passwordtype = "text";
|
_passwordtype = "text";
|
||||||
_togglepassword = Localizer["HidePassword"];
|
_togglepassword = SharedLocalizer["HidePassword"];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_passwordtype = "password";
|
_passwordtype = "password";
|
||||||
_togglepassword = Localizer["ShowPassword"];
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Logs
|
@namespace Oqtane.Modules.Admin.Logs
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
@inject ILogService LogService
|
@inject ILogService LogService
|
||||||
@inject ISettingService SettingService
|
@inject ISettingService SettingService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@ -91,19 +92,23 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _level = "-";
|
private string _level = "-";
|
||||||
private string _function = "-";
|
private string _function = "-";
|
||||||
private string _rows = "10";
|
private string _rows = "10";
|
||||||
private int _page = 1;
|
private int _page = 1;
|
||||||
private List<Log> _logs;
|
private List<Log> _logs;
|
||||||
private string _retention = "";
|
private string _retention = "";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (PageState.QueryString.ContainsKey("id") && int.TryParse(PageState.QueryString["id"], out int id))
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, ModuleState.ModuleId, "Detail", $"id={id}"));
|
||||||
|
}
|
||||||
if (PageState.QueryString.ContainsKey("level"))
|
if (PageState.QueryString.ContainsKey("level"))
|
||||||
{
|
{
|
||||||
_level = PageState.QueryString["level"];
|
_level = PageState.QueryString["level"];
|
||||||
|
@ -76,64 +76,71 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private string _moduledefinitionname = string.Empty;
|
private string _moduledefinitionname = string.Empty;
|
||||||
private string _owner = string.Empty;
|
private string _owner = string.Empty;
|
||||||
private string _module = string.Empty;
|
private string _module = string.Empty;
|
||||||
private string _description = string.Empty;
|
private string _description = string.Empty;
|
||||||
private List<Template> _templates;
|
private List<Template> _templates;
|
||||||
private string _template = "-";
|
private string _template = "-";
|
||||||
private string[] _versions;
|
private string[] _versions;
|
||||||
private string _reference = Constants.Version;
|
private string _reference = "local";
|
||||||
private string _minversion = "2.0.0";
|
private string _minversion = "2.0.0";
|
||||||
private string _location = string.Empty;
|
private string _location = string.Empty;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
_moduledefinitionname = SettingService.GetSetting(ModuleState.Settings, "ModuleDefinitionName", "");
|
_moduledefinitionname = SettingService.GetSetting(ModuleState.Settings, "ModuleDefinitionName", "");
|
||||||
if (string.IsNullOrEmpty(_moduledefinitionname))
|
if (string.IsNullOrEmpty(_moduledefinitionname))
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Info.Module.Creator"], MessageType.Info);
|
AddModuleMessage(Localizer["Info.Module.Creator"], MessageType.Info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Info.Module.Activate"], MessageType.Info);
|
AddModuleMessage(Localizer["Info.Module.Activate"], MessageType.Info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_templates = await ModuleDefinitionService.GetModuleDefinitionTemplatesAsync();
|
_templates = await ModuleDefinitionService.GetModuleDefinitionTemplatesAsync();
|
||||||
_versions = Constants.ReleaseVersions.Split(',').Where(item => Version.Parse(item).CompareTo(Version.Parse("2.0.0")) >= 0).ToArray();
|
_versions = Constants.ReleaseVersions.Split(',').Where(item => Version.Parse(item).CompareTo(Version.Parse("2.0.0")) >= 0).ToArray();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading Module Creator");
|
await logger.LogError(ex, "Error Loading Module Creator");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CreateModule()
|
private async Task CreateModule()
|
||||||
{
|
{
|
||||||
validated = true;
|
validated = true;
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
if (await interop.FormValid(form))
|
if (await interop.FormValid(form))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var moduleDefinition = new ModuleDefinition { Owner = _owner, Name = _module, Description = _description, Template = _template, Version = _reference };
|
if (IsValid(_owner) && IsValid(_module) && _owner != _module && _template != "-")
|
||||||
moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition);
|
{
|
||||||
|
var moduleDefinition = new ModuleDefinition { Owner = _owner, Name = _module, Description = _description, Template = _template, Version = _reference };
|
||||||
|
moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition);
|
||||||
|
|
||||||
var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
|
var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
|
||||||
SettingService.SetSetting(settings, "ModuleDefinitionName", moduleDefinition.ModuleDefinitionName);
|
SettingService.SetSetting(settings, "ModuleDefinitionName", moduleDefinition.ModuleDefinitionName);
|
||||||
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
|
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
|
||||||
|
|
||||||
GetLocation();
|
GetLocation();
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Module.Create"], NavigateUrl("admin/system")), MessageType.Success);
|
AddModuleMessage(string.Format(Localizer["Success.Module.Create"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage(Localizer["Message.Require.ValidName"], MessageType.Warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||||
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||||
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||||
|
@((MarkupString)(!string.IsNullOrEmpty(context.PackageUrl) ? " | " + SharedLocalizer["Search.Source"] + ": <strong>" + new Uri(context.PackageUrl).Host + "</strong>" : ""))
|
||||||
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 1px; vertical-align: middle;">
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
@ -90,9 +91,9 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p style="height: 200px; overflow-y: scroll;">
|
<p style="height: 200px; overflow-y: scroll;">
|
||||||
<h3>@_productname</h3>
|
<h3>@_productname</h3>
|
||||||
@if (!string.IsNullOrEmpty(_license))
|
@if (!string.IsNullOrEmpty(_packagelicense))
|
||||||
{
|
{
|
||||||
@((MarkupString)_license)
|
@((MarkupString)_packagelicense)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -114,145 +115,145 @@
|
|||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
private string _price = "free";
|
private string _price = "free";
|
||||||
private string _search = "";
|
private string _search = "";
|
||||||
private string _productname = "";
|
private string _productname = "";
|
||||||
private string _license = "";
|
private string _packageid = "";
|
||||||
private string _packageid = "";
|
private string _packagelicense = "";
|
||||||
private string _version = "";
|
private string _packageversion = "";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await LoadModuleDefinitions();
|
await LoadModuleDefinitions();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading Packages {Error}", ex.Message);
|
await logger.LogError(ex, "Error Loading Packages {Error}", ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.Package.Load"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Package.Load"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadModuleDefinitions()
|
private async Task LoadModuleDefinitions()
|
||||||
{
|
{
|
||||||
var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||||
_packages = await PackageService.GetPackagesAsync("module", _search, _price, "");
|
_packages = await PackageService.GetPackagesAsync("module", _search, _price, "");
|
||||||
|
|
||||||
if (_packages != null)
|
if (_packages != null)
|
||||||
{
|
{
|
||||||
foreach (Package package in _packages.ToArray())
|
foreach (Package package in _packages.ToArray())
|
||||||
{
|
{
|
||||||
if (moduledefinitions.Exists(item => item.PackageName == package.PackageId))
|
if (moduledefinitions.Exists(item => item.PackageName == package.PackageId))
|
||||||
{
|
{
|
||||||
_packages.Remove(package);
|
_packages.Remove(package);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void PriceChanged(ChangeEventArgs e)
|
private async void PriceChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_price = (string)e.Value;
|
_price = (string)e.Value;
|
||||||
_search = "";
|
_search = "";
|
||||||
await LoadModuleDefinitions();
|
await LoadModuleDefinitions();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error On PriceChanged");
|
await logger.LogError(ex, "Error On PriceChanged");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Search()
|
private async Task Search()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await LoadModuleDefinitions();
|
await LoadModuleDefinitions();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error On Search");
|
await logger.LogError(ex, "Error On Search");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Reset()
|
private async Task Reset()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_search = "";
|
_search = "";
|
||||||
await LoadModuleDefinitions();
|
await LoadModuleDefinitions();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error On Reset");
|
await logger.LogError(ex, "Error On Reset");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HideModal()
|
private void HideModal()
|
||||||
{
|
{
|
||||||
_productname = "";
|
_productname = "";
|
||||||
_license = "";
|
_packagelicense = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetPackage(string packageid, string version)
|
private async Task GetPackage(string packageid, string version)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var package = await PackageService.GetPackageAsync(packageid, version);
|
var package = await PackageService.GetPackageAsync(packageid, version);
|
||||||
if (package != null)
|
if (package != null)
|
||||||
{
|
{
|
||||||
_productname = package.Name;
|
_productname = package.Name;
|
||||||
if (!string.IsNullOrEmpty(package.License))
|
_packageid = package.PackageId;
|
||||||
{
|
if (!string.IsNullOrEmpty(package.License))
|
||||||
_license = package.License.Replace("\n", "<br />");
|
{
|
||||||
}
|
_packagelicense = package.License.Replace("\n", "<br />");
|
||||||
_packageid = package.PackageId;
|
}
|
||||||
_version = package.Version;
|
_packageversion = package.Version;
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
|
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
|
||||||
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadPackage()
|
private async Task DownloadPackage()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(_packageid, _version, Constants.PackagesFolder);
|
await PackageService.DownloadPackageAsync(_packageid, _packageversion, Constants.PackagesFolder);
|
||||||
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _version);
|
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _packageversion);
|
||||||
AddModuleMessage(Localizer["Success.Module.Download"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.Module.Download"], MessageType.Success);
|
||||||
_productname = "";
|
_productname = "";
|
||||||
_license = "";
|
_packagelicense = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _version);
|
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _packageversion);
|
||||||
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InstallModules()
|
private async Task InstallModules()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Installing Module");
|
await logger.LogError(ex, "Error Installing Modules");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@
|
|||||||
private List<Template> _templates;
|
private List<Template> _templates;
|
||||||
private string _template = "-";
|
private string _template = "-";
|
||||||
private string[] _versions;
|
private string[] _versions;
|
||||||
private string _reference = Constants.Version;
|
private string _reference = "local";
|
||||||
private string _minversion = "2.0.0";
|
private string _minversion = "2.0.0";
|
||||||
private string _location = string.Empty;
|
private string _location = string.Empty;
|
||||||
|
|
||||||
@ -151,7 +151,7 @@
|
|||||||
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
_minversion = template.Version;
|
_minversion = template.Version;
|
||||||
}
|
}
|
||||||
GetLocation();
|
GetLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetLocation()
|
private void GetLocation()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject IModuleDefinitionService ModuleDefinitionService
|
@inject IModuleDefinitionService ModuleDefinitionService
|
||||||
|
@inject IPackageService PackageService
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IStringLocalizer<Edit> Localizer
|
@inject IStringLocalizer<Edit> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
@ -43,7 +44,13 @@
|
|||||||
<input id="version" class="form-control" @bind="@_version" disabled />
|
<input id="version" class="form-control" @bind="@_version" disabled />
|
||||||
</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="packagename" HelpText="The unique name of the package from which this module was installed" ResourceKey="PackageName">Package Name: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the module" ResourceKey="Owner">Owner: </Label>
|
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the module" ResourceKey="Owner">Owner: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
||||||
@ -74,7 +81,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
|
<br />
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@SharedLocalizer["Save"]</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -82,24 +95,100 @@
|
|||||||
<PermissionGrid EntityName="@EntityNames.ModuleDefinition" PermissionNames="@PermissionNames.Utilize" Permissions="@_permissions" @ref="_permissionGrid" />
|
<PermissionGrid EntityName="@EntityNames.ModuleDefinition" PermissionNames="@PermissionNames.Utilize" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@SharedLocalizer["Save"]</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
<TabPanel Name="Translations" ResourceKey="Translations">
|
||||||
|
@if (_packages != null)
|
||||||
|
{
|
||||||
|
if (_packages.Count > 0)
|
||||||
|
{
|
||||||
|
<Pager Items="@_packages">
|
||||||
|
<Row>
|
||||||
|
<td>
|
||||||
|
<h3 style="display: inline;"><a href="@context.ProductUrl" target="_new">@context.Name</a></h3> by: <strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
|
||||||
|
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
|
||||||
|
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||||
|
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||||
|
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||||
|
@((MarkupString)(!string.IsNullOrEmpty(context.PackageUrl) ? " | " + SharedLocalizer["Search.Source"] + ": <strong>" + new Uri(context.PackageUrl).Host + "</strong>" : ""))
|
||||||
|
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||||
|
</td>
|
||||||
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
|
@if (context.Price != null && !string.IsNullOrEmpty(context.PackageUrl))
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
|
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
|
||||||
|
{
|
||||||
|
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.Value.ToString("$#,##0.00")</a>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</Row>
|
||||||
|
</Pager>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="InstallTranslations">@SharedLocalizer["Install"]</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<br />
|
||||||
|
<div class="mx-auto text-center">
|
||||||
|
@Localizer["Search.NoResults"]
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</TabPanel>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@SharedLocalizer["Save"]</button>
|
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
@if (_productname != "")
|
||||||
<br />
|
{
|
||||||
<br />
|
<div class="app-actiondialog">
|
||||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
<div class="modal" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">@SharedLocalizer["Review License Terms"]</h5>
|
||||||
|
<button type="button" class="btn-close" aria-label="Close" @onclick="HideModal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p style="height: 200px; overflow-y: scroll;">
|
||||||
|
<h3>@_productname</h3>
|
||||||
|
@if (!string.IsNullOrEmpty(_packagelicense))
|
||||||
|
{
|
||||||
|
@((MarkupString)_packagelicense)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@SharedLocalizer["License Not Specified"]
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-success" @onclick="DownloadTranslation">@SharedLocalizer["Accept"]</button>
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="HideModal">@SharedLocalizer["Cancel"]</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private int _moduleDefinitionId;
|
private int _moduleDefinitionId;
|
||||||
private string _name;
|
private string _name;
|
||||||
private string _version;
|
private string _description = "";
|
||||||
private string _categories;
|
private string _categories;
|
||||||
private string _moduledefinitionname = "";
|
private string _moduledefinitionname = "";
|
||||||
private string _description = "";
|
private string _version;
|
||||||
private string _owner = "";
|
private string _packagename = "";
|
||||||
|
private string _owner = "";
|
||||||
private string _url = "";
|
private string _url = "";
|
||||||
private string _contact = "";
|
private string _contact = "";
|
||||||
private string _license = "";
|
private string _license = "";
|
||||||
@ -114,6 +203,12 @@
|
|||||||
private PermissionGrid _permissionGrid;
|
private PermissionGrid _permissionGrid;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
private List<Package> _packages;
|
||||||
|
private string _productname = "";
|
||||||
|
private string _packageid = "";
|
||||||
|
private string _packagelicense = "";
|
||||||
|
private string _packageversion = "";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
@ -125,11 +220,12 @@
|
|||||||
if (moduleDefinition != null)
|
if (moduleDefinition != null)
|
||||||
{
|
{
|
||||||
_name = moduleDefinition.Name;
|
_name = moduleDefinition.Name;
|
||||||
_version = moduleDefinition.Version;
|
_description = moduleDefinition.Description;
|
||||||
_categories = moduleDefinition.Categories;
|
_categories = moduleDefinition.Categories;
|
||||||
_moduledefinitionname = moduleDefinition.ModuleDefinitionName;
|
_moduledefinitionname = moduleDefinition.ModuleDefinitionName;
|
||||||
_description = moduleDefinition.Description;
|
_version = moduleDefinition.Version;
|
||||||
_owner = moduleDefinition.Owner;
|
_packagename = moduleDefinition.PackageName;
|
||||||
|
_owner = moduleDefinition.Owner;
|
||||||
_url = moduleDefinition.Url;
|
_url = moduleDefinition.Url;
|
||||||
_contact = moduleDefinition.Contact;
|
_contact = moduleDefinition.Contact;
|
||||||
_license = moduleDefinition.License;
|
_license = moduleDefinition.License;
|
||||||
@ -139,7 +235,9 @@
|
|||||||
_createdon = moduleDefinition.CreatedOn;
|
_createdon = moduleDefinition.CreatedOn;
|
||||||
_modifiedby = moduleDefinition.ModifiedBy;
|
_modifiedby = moduleDefinition.ModifiedBy;
|
||||||
_modifiedon = moduleDefinition.ModifiedOn;
|
_modifiedon = moduleDefinition.ModifiedOn;
|
||||||
}
|
|
||||||
|
_packages = await PackageService.GetPackagesAsync("translation", "", "", moduleDefinition.PackageName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -185,4 +283,66 @@
|
|||||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HideModal()
|
||||||
|
{
|
||||||
|
_productname = "";
|
||||||
|
_packagelicense = "";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task GetPackage(string packageid, string version)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var package = await PackageService.GetPackageAsync(packageid, version);
|
||||||
|
if (package != null)
|
||||||
|
{
|
||||||
|
_productname = package.Name;
|
||||||
|
_packageid = package.PackageId;
|
||||||
|
if (!string.IsNullOrEmpty(package.License))
|
||||||
|
{
|
||||||
|
_packagelicense = package.License.Replace("\n", "<br />");
|
||||||
|
}
|
||||||
|
_packageversion = package.Version;
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
|
||||||
|
AddModuleMessage(Localizer["Error.Translation.Download"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DownloadTranslation()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await PackageService.DownloadPackageAsync(_packageid, _version, Constants.PackagesFolder);
|
||||||
|
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _version);
|
||||||
|
AddModuleMessage(Localizer["Success.Translation.Download"], MessageType.Success);
|
||||||
|
_productname = "";
|
||||||
|
_packagelicense = "";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _version);
|
||||||
|
AddModuleMessage(Localizer["Error.Translation.Download"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InstallTranslations()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await PackageService.InstallPackagesAsync();
|
||||||
|
AddModuleMessage(string.Format(Localizer["Success.Translation.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Installing Translations");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,32 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<ActionLink Action="Add" Text="Install Module" ResourceKey="InstallModule" />
|
<div class="container">
|
||||||
@((MarkupString)" ")
|
<div class="row mb-3 align-items-center">
|
||||||
<ActionLink Action="Create" Text="Create Module" ResourceKey="CreateModule" Class="btn btn-secondary" />
|
<div class="col-sm-6">
|
||||||
|
<ActionLink Action="Add" Text="Install Module" ResourceKey="InstallModule" />
|
||||||
|
@((MarkupString)" ")
|
||||||
|
<ActionLink Action="Create" Text="Create Module" ResourceKey="CreateModule" Class="btn btn-secondary" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<select class="form-select" @onchange="(e => CategoryChanged(e))">
|
||||||
|
@foreach (var category in _categories)
|
||||||
|
{
|
||||||
|
if (category == _category)
|
||||||
|
{
|
||||||
|
<option value="@category" selected>@category @Localizer["Modules"]</option>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<option value="@category">@category @Localizer["Modules"]</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Pager Items="@_moduleDefinitions">
|
<Pager Items="@_moduleDefinitions.Where(item => item.Categories.Contains(_category))">
|
||||||
<Header>
|
<Header>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
@ -30,9 +51,9 @@ else
|
|||||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" ResourceKey="EditModule" /></td>
|
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" ResourceKey="EditModule" /></td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.AssemblyName != "Oqtane.Client")
|
@if (context.AssemblyName != "Oqtane.Client")
|
||||||
{
|
{
|
||||||
<ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete", context.Name])" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" />
|
<ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete", context.Name])" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" />
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Version</td>
|
<td>@context.Version</td>
|
||||||
@ -50,9 +71,12 @@ else
|
|||||||
@((MarkupString)PurchaseLink(context.PackageName))
|
@((MarkupString)PurchaseLink(context.PackageName))
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@if (UpgradeAvailable(context.PackageName, context.Version))
|
@{
|
||||||
|
var version = UpgradeAvailable(context.PackageName, context.Version);
|
||||||
|
}
|
||||||
|
@if (version != context.Version)
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadModule(context.PackageName, context.Version))>@SharedLocalizer["Upgrade"]</button>
|
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadModule(context.PackageName, version))>@SharedLocalizer["Upgrade"]</button>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
</Row>
|
</Row>
|
||||||
@ -60,92 +84,99 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<ModuleDefinition> _moduleDefinitions;
|
private List<ModuleDefinition> _moduleDefinitions;
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
|
private List<string> _categories = new List<string>();
|
||||||
|
private string _category = "Common";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_moduleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
_moduleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||||
_packages = await PackageService.GetPackagesAsync("module");
|
_packages = await PackageService.GetPackagesAsync("module");
|
||||||
}
|
_categories = _moduleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList();
|
||||||
catch (Exception ex)
|
}
|
||||||
{
|
catch (Exception ex)
|
||||||
if (_moduleDefinitions == null)
|
{
|
||||||
{
|
if (_moduleDefinitions == null)
|
||||||
await logger.LogError(ex, "Error Loading Modules {Error}", ex.Message);
|
{
|
||||||
AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error);
|
await logger.LogError(ex, "Error Loading Modules {Error}", ex.Message);
|
||||||
}
|
AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string PurchaseLink(string packagename)
|
private string PurchaseLink(string packagename)
|
||||||
{
|
{
|
||||||
string link = "";
|
string link = "";
|
||||||
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
||||||
{
|
{
|
||||||
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||||
if (package != null)
|
if (package != null)
|
||||||
{
|
{
|
||||||
if (package.ExpiryDate != null && package.ExpiryDate.Value.Date != DateTime.MaxValue.Date)
|
if (package.ExpiryDate != null && package.ExpiryDate.Value.Date != DateTime.MaxValue.Date)
|
||||||
{
|
{
|
||||||
link += "<span>" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + "</span>";
|
link += "<span>" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + "</span>";
|
||||||
if (!string.IsNullOrEmpty(package.PaymentUrl))
|
if (!string.IsNullOrEmpty(package.PaymentUrl))
|
||||||
{
|
{
|
||||||
link += " <a class=\"btn btn-primary\" style=\"text-decoration: none !important\" href=\"" + package.PaymentUrl + "\" target=\"_new\">" + SharedLocalizer["Extend"] + "</a>";
|
link += " <a class=\"btn btn-primary\" style=\"text-decoration: none !important\" href=\"" + package.PaymentUrl + "\" target=\"_new\">" + SharedLocalizer["Extend"] + "</a>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpgradeAvailable(string packagename, string version)
|
private string UpgradeAvailable(string packagename, string version)
|
||||||
{
|
{
|
||||||
var upgradeavailable = false;
|
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
||||||
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
{
|
||||||
{
|
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||||
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
if (package != null && Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0)
|
||||||
if (package != null)
|
{
|
||||||
{
|
return package.Version;
|
||||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
}
|
||||||
}
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
private async Task DownloadModule(string packagename, string version)
|
||||||
return upgradeavailable;
|
{
|
||||||
}
|
try
|
||||||
|
{
|
||||||
|
await PackageService.DownloadPackageAsync(packagename, version, Constants.PackagesFolder);
|
||||||
|
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", packagename, version);
|
||||||
|
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
||||||
|
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version} {Error}", packagename, version, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task DownloadModule(string packagename, string version)
|
private async Task DeleteModule(ModuleDefinition moduleDefinition)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(packagename, version, Constants.PackagesFolder);
|
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
|
||||||
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", packagename, version);
|
AddModuleMessage(Localizer["Success.Module.Delete"], MessageType.Success);
|
||||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, true));
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
}
|
||||||
}
|
catch (Exception ex)
|
||||||
catch (Exception ex)
|
{
|
||||||
{
|
await logger.LogError(ex, "Error Deleting Module {ModuleDefinition} {Error}", moduleDefinition, ex.Message);
|
||||||
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version} {Error}", packagename, version, ex.Message);
|
AddModuleMessage(Localizer["Error.Module.Delete"], MessageType.Error);
|
||||||
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async Task DeleteModule(ModuleDefinition moduleDefinition)
|
private void CategoryChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
_category = (string)e.Value;
|
||||||
{
|
StateHasChanged();
|
||||||
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
|
}
|
||||||
AddModuleMessage(Localizer["Success.Module.Delete"], MessageType.Success);
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, true));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Deleting Module {ModuleDefinition} {Error}", moduleDefinition, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Module.Delete"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -90,116 +90,125 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
public override string Title => "Module Settings";
|
public override string Title => "Module Settings";
|
||||||
|
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private List<Theme> _themes;
|
private List<Theme> _themes;
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private string _title;
|
private string _title;
|
||||||
private string _containerType;
|
private string _containerType;
|
||||||
private string _allPages = "false";
|
private string _allPages = "false";
|
||||||
private string _permissionNames = "";
|
private string _permissionNames = "";
|
||||||
private string _permissions = null;
|
private string _permissions = null;
|
||||||
private string _pageId;
|
private string _pageId;
|
||||||
private PermissionGrid _permissionGrid;
|
private PermissionGrid _permissionGrid;
|
||||||
private Type _moduleSettingsType;
|
private Type _moduleSettingsType;
|
||||||
private object _moduleSettings;
|
private object _moduleSettings;
|
||||||
private string _moduleSettingsTitle = "Module Settings";
|
private string _moduleSettingsTitle = "Module Settings";
|
||||||
private RenderFragment ModuleSettingsComponent { get; set; }
|
private RenderFragment ModuleSettingsComponent { get; set; }
|
||||||
private Type _containerSettingsType;
|
private Type _containerSettingsType;
|
||||||
private object _containerSettings;
|
private object _containerSettings;
|
||||||
private RenderFragment ContainerSettingsComponent { get; set; }
|
private RenderFragment ContainerSettingsComponent { get; set; }
|
||||||
private string createdby;
|
private string createdby;
|
||||||
private DateTime createdon;
|
private DateTime createdon;
|
||||||
private string modifiedby;
|
private string modifiedby;
|
||||||
private DateTime modifiedon;
|
private DateTime modifiedon;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
_title = ModuleState.Title;
|
_title = ModuleState.Title;
|
||||||
_themes = await ThemeService.GetThemesAsync();
|
_themes = await ThemeService.GetThemesAsync();
|
||||||
_containers = ThemeService.GetContainerControls(_themes, PageState.Page.ThemeType);
|
_containers = ThemeService.GetContainerControls(_themes, PageState.Page.ThemeType);
|
||||||
_containerType = ModuleState.ContainerType;
|
_containerType = ModuleState.ContainerType;
|
||||||
_allPages = ModuleState.AllPages.ToString();
|
_allPages = ModuleState.AllPages.ToString();
|
||||||
_permissions = ModuleState.Permissions;
|
_permissions = ModuleState.Permissions;
|
||||||
_permissionNames = ModuleState.ModuleDefinition.PermissionNames;
|
_pageId = ModuleState.PageId.ToString();
|
||||||
_pageId = ModuleState.PageId.ToString();
|
createdby = ModuleState.CreatedBy;
|
||||||
createdby = ModuleState.CreatedBy;
|
createdon = ModuleState.CreatedOn;
|
||||||
createdon = ModuleState.CreatedOn;
|
modifiedby = ModuleState.ModifiedBy;
|
||||||
modifiedby = ModuleState.ModifiedBy;
|
modifiedon = ModuleState.ModifiedOn;
|
||||||
modifiedon = ModuleState.ModifiedOn;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(ModuleState.ModuleDefinition.SettingsType))
|
if (ModuleState.ModuleDefinition != null)
|
||||||
{
|
{
|
||||||
// module settings type explicitly declared in IModule interface
|
_permissionNames = ModuleState.ModuleDefinition?.PermissionNames;
|
||||||
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.SettingsType);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// legacy support - module settings type determined by convention ( ie. existence of a "Settings.razor" component in module )
|
|
||||||
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
|
|
||||||
}
|
|
||||||
if (_moduleSettingsType != null)
|
|
||||||
{
|
|
||||||
var moduleobject = Activator.CreateInstance(_moduleSettingsType) as IModuleControl;
|
|
||||||
if (!string.IsNullOrEmpty(moduleobject.Title))
|
|
||||||
{
|
|
||||||
_moduleSettingsTitle = moduleobject.Title;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModuleSettingsComponent = builder =>
|
if (!string.IsNullOrEmpty(ModuleState.ModuleDefinition.SettingsType))
|
||||||
{
|
{
|
||||||
builder.OpenComponent(0, _moduleSettingsType);
|
// module settings type explicitly declared in IModule interface
|
||||||
builder.AddComponentReferenceCapture(1, inst => { _moduleSettings = Convert.ChangeType(inst, _moduleSettingsType); });
|
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.SettingsType);
|
||||||
builder.CloseComponent();
|
}
|
||||||
};
|
else
|
||||||
}
|
{
|
||||||
|
// legacy support - module settings type determined by convention ( ie. existence of a "Settings.razor" component in module )
|
||||||
|
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
|
||||||
|
}
|
||||||
|
if (_moduleSettingsType != null)
|
||||||
|
{
|
||||||
|
var moduleobject = Activator.CreateInstance(_moduleSettingsType) as IModuleControl;
|
||||||
|
if (!string.IsNullOrEmpty(moduleobject.Title))
|
||||||
|
{
|
||||||
|
_moduleSettingsTitle = moduleobject.Title;
|
||||||
|
}
|
||||||
|
|
||||||
var theme = _themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
|
ModuleSettingsComponent = builder =>
|
||||||
if (theme != null && !string.IsNullOrEmpty(theme.ContainerSettingsType))
|
{
|
||||||
{
|
builder.OpenComponent(0, _moduleSettingsType);
|
||||||
_containerSettingsType = Type.GetType(theme.ContainerSettingsType);
|
builder.AddComponentReferenceCapture(1, inst => { _moduleSettings = Convert.ChangeType(inst, _moduleSettingsType); });
|
||||||
if (_containerSettingsType != null)
|
builder.CloseComponent();
|
||||||
{
|
};
|
||||||
ContainerSettingsComponent = builder =>
|
}
|
||||||
{
|
}
|
||||||
builder.OpenComponent(0, _containerSettingsType);
|
else
|
||||||
builder.AddComponentReferenceCapture(1, inst => { _containerSettings = Convert.ChangeType(inst, _containerSettingsType); });
|
{
|
||||||
builder.CloseComponent();
|
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], ModuleState.ModuleDefinitionName), MessageType.Error);
|
||||||
};
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveModule()
|
var theme = _themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
|
||||||
{
|
if (theme != null && !string.IsNullOrEmpty(theme.ContainerSettingsType))
|
||||||
validated = true;
|
{
|
||||||
var interop = new Interop(JSRuntime);
|
_containerSettingsType = Type.GetType(theme.ContainerSettingsType);
|
||||||
if (await interop.FormValid(form))
|
if (_containerSettingsType != null)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_title))
|
ContainerSettingsComponent = builder =>
|
||||||
{
|
{
|
||||||
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
builder.OpenComponent(0, _containerSettingsType);
|
||||||
pagemodule.PageId = int.Parse(_pageId);
|
builder.AddComponentReferenceCapture(1, inst => { _containerSettings = Convert.ChangeType(inst, _containerSettingsType); });
|
||||||
pagemodule.Title = _title;
|
builder.CloseComponent();
|
||||||
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
|
};
|
||||||
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
|
}
|
||||||
{
|
}
|
||||||
pagemodule.ContainerType = string.Empty;
|
}
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
|
|
||||||
{
|
|
||||||
pagemodule.ContainerType = string.Empty;
|
|
||||||
}
|
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
|
||||||
|
|
||||||
var module = ModuleState;
|
private async Task SaveModule()
|
||||||
module.AllPages = bool.Parse(_allPages);
|
{
|
||||||
module.Permissions = _permissionGrid.GetPermissions();
|
validated = true;
|
||||||
await ModuleService.UpdateModuleAsync(module);
|
var interop = new Interop(JSRuntime);
|
||||||
|
if (await interop.FormValid(form))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(_title))
|
||||||
|
{
|
||||||
|
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||||
|
pagemodule.PageId = int.Parse(_pageId);
|
||||||
|
pagemodule.Title = _title;
|
||||||
|
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
|
||||||
|
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
|
||||||
|
{
|
||||||
|
pagemodule.ContainerType = string.Empty;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
|
||||||
|
{
|
||||||
|
pagemodule.ContainerType = string.Empty;
|
||||||
|
}
|
||||||
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
|
|
||||||
|
var module = ModuleState;
|
||||||
|
module.AllPages = bool.Parse(_allPages);
|
||||||
|
module.PageModuleId = ModuleState.PageModuleId;
|
||||||
|
module.Permissions = _permissionGrid.GetPermissions();
|
||||||
|
await ModuleService.UpdateModuleAsync(module);
|
||||||
|
|
||||||
if (_moduleSettingsType != null)
|
if (_moduleSettingsType != null)
|
||||||
{
|
{
|
||||||
|
@ -27,19 +27,25 @@
|
|||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="password" HelpText="Please choose a sufficiently secure password and enter it here" ResourceKey="Password"></Label>
|
<Label Class="col-sm-3" For="password" HelpText="Please choose a sufficiently secure password and enter it here" ResourceKey="Password"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="password" type="password" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
<div class="input-group">
|
||||||
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</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="confirm" HelpText="Enter your password again to confirm it matches the value entered above" ResourceKey="Confirm"></Label>
|
<Label Class="col-sm-3" For="confirm" HelpText="Enter your password again to confirm it matches the value entered above" ResourceKey="Confirm"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="confirm" type="password" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
|
<div class="input-group">
|
||||||
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</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="email" HelpText="Your email address where you wish to receive notifications" ResourceKey="Email"></Label>
|
<Label Class="col-sm-3" For="email" HelpText="Your email address where you wish to receive notifications" ResourceKey="Email"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="email" class="form-control" @bind="@_email" maxlength="256" required />
|
<input id="email" class="form-control" @bind="@_email" maxlength="256" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@ -62,15 +68,22 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _username = string.Empty;
|
private string _username = string.Empty;
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private string _password = string.Empty;
|
private string _password = string.Empty;
|
||||||
private string _confirm = string.Empty;
|
private string _passwordtype = "password";
|
||||||
private string _email = string.Empty;
|
private string _togglepassword = string.Empty;
|
||||||
private string _displayname = string.Empty;
|
private string _confirm = string.Empty;
|
||||||
|
private string _email = string.Empty;
|
||||||
|
private string _displayname = string.Empty;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
||||||
|
|
||||||
|
protected override void OnParametersSet()
|
||||||
|
{
|
||||||
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
}
|
||||||
|
|
||||||
private async Task Register()
|
private async Task Register()
|
||||||
{
|
{
|
||||||
@ -134,4 +147,18 @@ else
|
|||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(string.Empty));
|
NavigationManager.NavigateTo(NavigateUrl(string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TogglePassword()
|
||||||
|
{
|
||||||
|
if (_passwordtype == "password")
|
||||||
|
{
|
||||||
|
_passwordtype = "text";
|
||||||
|
_togglepassword = SharedLocalizer["HidePassword"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_passwordtype = "password";
|
||||||
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,19 @@
|
|||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="password" HelpText="The new password. It must satisfy complexity rules for the site." ResourceKey="Password">Password: </Label>
|
<Label Class="col-sm-3" For="password" HelpText="The new password. It must satisfy complexity rules for the site." ResourceKey="Password">Password: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="password" type="password" class="form-control" @bind="@_password" required />
|
<div class="input-group">
|
||||||
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</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="confirm" HelpText="Enter the password again. It must exactly match the password entered above." ResourceKey="Confirm">Confirm: </Label>
|
<Label Class="col-sm-3" For="confirm" HelpText="Enter the password again. It must exactly match the password entered above." ResourceKey="Confirm">Confirm: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="confirm" type="password" class="form-control" @bind="@_confirm" required />
|
<div class="input-group">
|
||||||
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -36,12 +42,16 @@
|
|||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private string _username = string.Empty;
|
private string _username = string.Empty;
|
||||||
private string _password = string.Empty;
|
private string _password = string.Empty;
|
||||||
|
private string _passwordtype = "password";
|
||||||
|
private string _togglepassword = string.Empty;
|
||||||
private string _confirm = string.Empty;
|
private string _confirm = string.Empty;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
|
||||||
if (PageState.QueryString.ContainsKey("name") && PageState.QueryString.ContainsKey("token"))
|
if (PageState.QueryString.ContainsKey("name") && PageState.QueryString.ContainsKey("token"))
|
||||||
{
|
{
|
||||||
_username = PageState.QueryString["name"];
|
_username = PageState.QueryString["name"];
|
||||||
@ -110,4 +120,18 @@
|
|||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(string.Empty));
|
NavigationManager.NavigateTo(NavigateUrl(string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TogglePassword()
|
||||||
|
{
|
||||||
|
if (_passwordtype == "password")
|
||||||
|
{
|
||||||
|
_passwordtype = "text";
|
||||||
|
_togglepassword = SharedLocalizer["HidePassword"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_passwordtype = "password";
|
||||||
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ else
|
|||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
_roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
|
_roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
|
||||||
_roles = _roles.Where(item => item.Name != RoleNames.Everyone).ToList();
|
_roles.RemoveAll(item => item.Name == RoleNames.Everyone || item.Name == RoleNames.Unauthenticated);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -95,11 +95,7 @@ else
|
|||||||
roleid = Int32.Parse(PageState.QueryString["id"]);
|
roleid = Int32.Parse(PageState.QueryString["id"]);
|
||||||
Role role = await RoleService.GetRoleAsync(roleid);
|
Role role = await RoleService.GetRoleAsync(roleid);
|
||||||
name = role.Name;
|
name = role.Name;
|
||||||
users = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
users = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered);
|
||||||
users = users
|
|
||||||
.Where(u => u.Role.Name == RoleNames.Registered)
|
|
||||||
.OrderBy(u => u.User.DisplayName)
|
|
||||||
.ToList();
|
|
||||||
await GetUserRoles();
|
await GetUserRoles();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -113,8 +109,7 @@ else
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, name);
|
||||||
userroles = userroles.Where(item => item.RoleId == roleid).ToList();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -170,24 +170,54 @@
|
|||||||
@if (_aliases != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
@if (_aliases != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
<Section Name="Aliases" Heading="Aliases" ResourceKey="Aliases">
|
<Section Name="Aliases" Heading="Aliases" ResourceKey="Aliases">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="alias" HelpText="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 should be separated by commas." ResourceKey="Aliases">Aliases: </Label>
|
<Label Class="col-sm-3" For="aliases" HelpText="The list of aliases for this site" ResourceKey="Aliases">Aliases: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
|
<button type="button" class="btn btn-primary" @onclick="AddAlias">@SharedLocalizer["Add"]</button>
|
||||||
|
<Pager Items="@_aliases">
|
||||||
|
<Header>
|
||||||
|
<th style="width: 1px;"> </th>
|
||||||
|
<th style="width: 1px;"> </th>
|
||||||
|
<th>@Localizer["AliasName"]</th>
|
||||||
|
<th>@Localizer["AliasDefault"]</th>
|
||||||
|
</Header>
|
||||||
|
<Row>
|
||||||
|
@if (context.AliasId != _aliasid)
|
||||||
|
{
|
||||||
|
<td>
|
||||||
|
@if (_aliasid == -1)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-primary" @onclick="@(() => EditAlias(context))">@SharedLocalizer["Edit"]</button>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if (_aliasid == -1)
|
||||||
|
{
|
||||||
|
<ActionDialog Action="Delete" OnClick="@(async () => await DeleteAlias(context))" ResourceKey="DeleteModule" Class="btn btn-danger" Header="Delete Alias" Message="@string.Format(Localizer["Confirm.Alias.Delete", context.Name])" />
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
<td>@context.Name</td>
|
||||||
|
<td>@context.IsDefault</td>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<td><button type="button" class="btn btn-success" @onclick="@(async () => await SaveAlias())">@SharedLocalizer["Save"]</button></td>
|
||||||
|
<td><button type="button" class="btn btn-secondary" @onclick="@(async () => await CancelAlias())">@SharedLocalizer["Cancel"]</button></td>
|
||||||
|
<td>
|
||||||
|
<input id="aliasname" class="form-control" @bind="@_aliasname" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="defaultaias" class="form-select" @bind="@_defaultalias" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
}
|
||||||
|
</Row>
|
||||||
|
</Pager>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="defaultalias" HelpText="The default alias for the site. Requests for non-default aliases will be redirected to the default alias." ResourceKey="DefaultAlias">Default Alias: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="defaultalias" class="form-select" @bind="@_defaultalias" required>
|
|
||||||
@foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray())
|
|
||||||
{
|
|
||||||
<option value="@name">@name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
<Section Name="Hosting" Heading="Hosting Model" ResourceKey="Hosting">
|
<Section Name="Hosting" Heading="Hosting Model" ResourceKey="Hosting">
|
||||||
@ -253,8 +283,9 @@
|
|||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private string _name = string.Empty;
|
private string _name = string.Empty;
|
||||||
private List<Alias> _aliases;
|
private List<Alias> _aliases;
|
||||||
private string _defaultalias = string.Empty;
|
private int _aliasid = -1;
|
||||||
private string _urls = string.Empty;
|
private string _aliasname;
|
||||||
|
private string _defaultalias;
|
||||||
private string _runtime = "";
|
private string _runtime = "";
|
||||||
private string _prerender = "";
|
private string _prerender = "";
|
||||||
private int _logofileid = -1;
|
private int _logofileid = -1;
|
||||||
@ -304,10 +335,7 @@
|
|||||||
_prerender = site.RenderMode.Replace(_runtime, "");
|
_prerender = site.RenderMode.Replace(_runtime, "");
|
||||||
_isdeleted = site.IsDeleted.ToString();
|
_isdeleted = site.IsDeleted.ToString();
|
||||||
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
await GetAliases();
|
||||||
{
|
|
||||||
await GetAliases();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (site.LogoFileId != null)
|
if (site.LogoFileId != null)
|
||||||
{
|
{
|
||||||
@ -341,7 +369,7 @@
|
|||||||
_smtpssl = SettingService.GetSetting(settings, "SMTPSSL", "False");
|
_smtpssl = SettingService.GetSetting(settings, "SMTPSSL", "False");
|
||||||
_smtpusername = SettingService.GetSetting(settings, "SMTPUsername", string.Empty);
|
_smtpusername = SettingService.GetSetting(settings, "SMTPUsername", string.Empty);
|
||||||
_smtppassword = SettingService.GetSetting(settings, "SMTPPassword", string.Empty);
|
_smtppassword = SettingService.GetSetting(settings, "SMTPPassword", string.Empty);
|
||||||
_togglesmtppassword = Localizer["Show"];
|
_togglesmtppassword = SharedLocalizer["ShowPassword"];
|
||||||
_smtpsender = SettingService.GetSetting(settings, "SMTPSender", string.Empty);
|
_smtpsender = SettingService.GetSetting(settings, "SMTPSender", string.Empty);
|
||||||
_retention = SettingService.GetSetting(settings, "NotificationRetention", "30");
|
_retention = SettingService.GetSetting(settings, "NotificationRetention", "30");
|
||||||
|
|
||||||
@ -407,154 +435,94 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-")
|
if (_name != string.Empty && _themetype != "-" && _containertype != "-")
|
||||||
{
|
{
|
||||||
var unique = true;
|
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (site != null)
|
||||||
{
|
{
|
||||||
_urls = Regex.Replace(_urls, @"\r\n?|\n", ","); // convert line breaks to commas
|
bool refresh = false;
|
||||||
var aliases = await AliasService.GetAliasesAsync();
|
bool reload = false;
|
||||||
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray())
|
|
||||||
|
site.Name = _name;
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
var alias = aliases.Where(item => item.Name == name).FirstOrDefault();
|
if (site.Runtime != _runtime || site.RenderMode != _runtime + _prerender)
|
||||||
if (alias != null && unique)
|
|
||||||
{
|
{
|
||||||
unique = (alias.TenantId == PageState.Site.TenantId && alias.SiteId == PageState.Site.SiteId);
|
site.Runtime = _runtime;
|
||||||
|
site.RenderMode = _runtime + _prerender;
|
||||||
|
reload = true; // needs to be reloaded on server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unique && string.IsNullOrEmpty(_defaultalias)) unique = false;
|
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
||||||
}
|
|
||||||
|
|
||||||
if (unique)
|
site.LogoFileId = null;
|
||||||
{
|
var logofileid = _logofilemanager.GetFileId();
|
||||||
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
if (logofileid != -1)
|
||||||
if (site != null)
|
|
||||||
{
|
{
|
||||||
bool refresh = false;
|
site.LogoFileId = logofileid;
|
||||||
bool reload = false;
|
}
|
||||||
|
int? faviconFieldId = _faviconfilemanager.GetFileId();
|
||||||
site.Name = _name;
|
if (faviconFieldId == -1) faviconFieldId = null;
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (site.FaviconFileId != faviconFieldId)
|
||||||
{
|
{
|
||||||
if (site.Runtime != _runtime || site.RenderMode != _runtime + _prerender)
|
site.FaviconFileId = faviconFieldId;
|
||||||
{
|
reload = true; // needs to be reloaded on server
|
||||||
site.Runtime = _runtime;
|
}
|
||||||
site.RenderMode = _runtime + _prerender;
|
if (site.DefaultThemeType != _themetype)
|
||||||
reload = true; // needs to be reloaded on server
|
{
|
||||||
}
|
site.DefaultThemeType = _themetype;
|
||||||
}
|
refresh = true; // needs to be refreshed on client
|
||||||
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
}
|
||||||
|
if (site.DefaultContainerType != _containertype)
|
||||||
site.LogoFileId = null;
|
{
|
||||||
var logofileid = _logofilemanager.GetFileId();
|
site.DefaultContainerType = _containertype;
|
||||||
if (logofileid != -1)
|
refresh = true; // needs to be refreshed on client
|
||||||
{
|
}
|
||||||
site.LogoFileId = logofileid;
|
site.AdminContainerType = _admincontainertype;
|
||||||
}
|
|
||||||
int? faviconFieldId = _faviconfilemanager.GetFileId();
|
if (site.PwaIsEnabled.ToString() != _pwaisenabled)
|
||||||
if (faviconFieldId == -1) faviconFieldId = null;
|
{
|
||||||
if (site.FaviconFileId != faviconFieldId)
|
site.PwaIsEnabled = Boolean.Parse(_pwaisenabled);
|
||||||
{
|
reload = true; // needs to be reloaded on server
|
||||||
site.FaviconFileId = faviconFieldId;
|
}
|
||||||
reload = true; // needs to be reloaded on server
|
int? pwaappiconfileid = _pwaappiconfilemanager.GetFileId();
|
||||||
}
|
if (pwaappiconfileid == -1) pwaappiconfileid = null;
|
||||||
if (site.DefaultThemeType != _themetype)
|
if (site.PwaAppIconFileId != pwaappiconfileid)
|
||||||
{
|
{
|
||||||
site.DefaultThemeType = _themetype;
|
site.PwaAppIconFileId = pwaappiconfileid;
|
||||||
refresh = true; // needs to be refreshed on client
|
reload = true; // needs to be reloaded on server
|
||||||
}
|
}
|
||||||
if (site.DefaultContainerType != _containertype)
|
int? pwasplashiconfileid = _pwasplashiconfilemanager.GetFileId();
|
||||||
{
|
if (pwasplashiconfileid == -1) pwasplashiconfileid = null;
|
||||||
site.DefaultContainerType = _containertype;
|
if (site.PwaSplashIconFileId != pwasplashiconfileid)
|
||||||
refresh = true; // needs to be refreshed on client
|
{
|
||||||
}
|
site.PwaSplashIconFileId = pwasplashiconfileid;
|
||||||
site.AdminContainerType = _admincontainertype;
|
reload = true; // needs to be reloaded on server
|
||||||
|
}
|
||||||
if (site.PwaIsEnabled.ToString() != _pwaisenabled)
|
|
||||||
{
|
site = await SiteService.UpdateSiteAsync(site);
|
||||||
site.PwaIsEnabled = Boolean.Parse(_pwaisenabled);
|
|
||||||
reload = true; // needs to be reloaded on server
|
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
||||||
}
|
settings = SettingService.SetSetting(settings, "SMTPHost", _smtphost, true);
|
||||||
int? pwaappiconfileid = _pwaappiconfilemanager.GetFileId();
|
settings = SettingService.SetSetting(settings, "SMTPPort", _smtpport, true);
|
||||||
if (pwaappiconfileid == -1) pwaappiconfileid = null;
|
settings = SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, true);
|
||||||
if (site.PwaAppIconFileId != pwaappiconfileid)
|
settings = SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true);
|
||||||
{
|
settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true);
|
||||||
site.PwaAppIconFileId = pwaappiconfileid;
|
settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true);
|
||||||
reload = true; // needs to be reloaded on server
|
settings = SettingService.SetSetting(settings, "NotificationRetention", _retention, true);
|
||||||
}
|
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
||||||
int? pwasplashiconfileid = _pwasplashiconfilemanager.GetFileId();
|
|
||||||
if (pwasplashiconfileid == -1) pwasplashiconfileid = null;
|
await logger.LogInformation("Site Settings Saved {Site}", site);
|
||||||
if (site.PwaSplashIconFileId != pwasplashiconfileid)
|
|
||||||
{
|
if (refresh || reload)
|
||||||
site.PwaSplashIconFileId = pwasplashiconfileid;
|
{
|
||||||
reload = true; // needs to be reloaded on server
|
NavigationManager.NavigateTo(NavigateUrl(true), reload); // refresh/reload
|
||||||
}
|
}
|
||||||
|
else
|
||||||
site = await SiteService.UpdateSiteAsync(site);
|
{
|
||||||
|
AddModuleMessage(Localizer["Success.Settings.SaveSite"], MessageType.Success);
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
await interop.ScrollTo(0, 0, "smooth");
|
||||||
settings = SettingService.SetSetting(settings, "SMTPHost", _smtphost, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "SMTPPort", _smtpport, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "NotificationRetention", _retention, true);
|
|
||||||
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
|
||||||
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
|
||||||
{
|
|
||||||
var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
|
||||||
.Select(sValue => sValue.Trim()).ToArray();
|
|
||||||
foreach (Alias alias in _aliases)
|
|
||||||
{
|
|
||||||
if (!names.Contains(alias.Name.Trim()))
|
|
||||||
{
|
|
||||||
await AliasService.DeleteAliasAsync(alias.AliasId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string name in names)
|
|
||||||
{
|
|
||||||
var alias = _aliases.Find(item => item.Name.Trim() == name);
|
|
||||||
if (alias == null)
|
|
||||||
{
|
|
||||||
alias = new Alias();
|
|
||||||
alias.Name = name;
|
|
||||||
alias.TenantId = site.TenantId;
|
|
||||||
alias.SiteId = site.SiteId;
|
|
||||||
alias.IsDefault = (name == _defaultalias);
|
|
||||||
await AliasService.AddAliasAsync(alias);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (alias.Name != name || alias.IsDefault != (alias.Name.Trim() == _defaultalias))
|
|
||||||
{
|
|
||||||
alias.Name = name;
|
|
||||||
alias.IsDefault = (name == _defaultalias);
|
|
||||||
await AliasService.UpdateAliasAsync(alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await GetAliases();
|
|
||||||
}
|
|
||||||
|
|
||||||
await logger.LogInformation("Site Settings Saved {Site}", site);
|
|
||||||
|
|
||||||
if (refresh || reload)
|
|
||||||
{
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl(true), reload); // refresh/reload
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddModuleMessage(Localizer["Success.Settings.SaveSite"], MessageType.Success);
|
|
||||||
await interop.ScrollTo(0, 0, "smooth");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else // deuplicate alias or default alias not specified
|
|
||||||
{
|
|
||||||
AddModuleMessage(Localizer["Message.Aliases.Taken"], MessageType.Warning);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -578,19 +546,19 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sites = await SiteService.GetSitesAsync();
|
var aliases = await AliasService.GetAliasesAsync();
|
||||||
if (sites.Count > 1)
|
if (aliases.Any(item => item.SiteId != PageState.Site.SiteId || item.TenantId != PageState.Site.TenantId))
|
||||||
{
|
{
|
||||||
await SiteService.DeleteSiteAsync(PageState.Site.SiteId);
|
await SiteService.DeleteSiteAsync(PageState.Site.SiteId);
|
||||||
await logger.LogInformation("Site Deleted {SiteId}", PageState.Site.SiteId);
|
await logger.LogInformation("Site Deleted {SiteId}", PageState.Site.SiteId);
|
||||||
|
|
||||||
var aliases = await AliasService.GetAliasesAsync();
|
foreach (Alias alias in aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId))
|
||||||
foreach (Alias a in aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId))
|
|
||||||
{
|
{
|
||||||
await AliasService.DeleteAliasAsync(a.AliasId);
|
await AliasService.DeleteAliasAsync(alias.AliasId);
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl("admin/sites"));
|
var redirect = aliases.First(item => item.SiteId != PageState.Site.SiteId || item.TenantId != PageState.Site.TenantId);
|
||||||
|
NavigationManager.NavigateTo(PageState.Uri.Scheme + "://" + redirect.Name, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -637,31 +605,97 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetAliases()
|
|
||||||
{
|
|
||||||
_urls = string.Empty;
|
|
||||||
_defaultalias = string.Empty;
|
|
||||||
_aliases = await AliasService.GetAliasesAsync();
|
|
||||||
_aliases = _aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId).OrderBy(item => item.AliasId).ToList();
|
|
||||||
foreach (Alias alias in _aliases)
|
|
||||||
{
|
|
||||||
_urls += (_urls == string.Empty) ? alias.Name.Trim() : ", " + alias.Name.Trim();
|
|
||||||
if (alias.IsDefault && string.IsNullOrEmpty(_defaultalias)) _defaultalias = alias.Name.Trim();
|
|
||||||
}
|
|
||||||
if (string.IsNullOrEmpty(_defaultalias)) _defaultalias = _aliases.First().Name.Trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ToggleSMTPPassword()
|
private void ToggleSMTPPassword()
|
||||||
{
|
{
|
||||||
if (_smtppasswordtype == "password")
|
if (_smtppasswordtype == "password")
|
||||||
{
|
{
|
||||||
_smtppasswordtype = "text";
|
_smtppasswordtype = "text";
|
||||||
_togglesmtppassword = Localizer["Hide"];
|
_togglesmtppassword = SharedLocalizer["HidePassword"];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_smtppasswordtype = "password";
|
_smtppasswordtype = "password";
|
||||||
_togglesmtppassword = Localizer["Show"];
|
_togglesmtppassword = SharedLocalizer["ShowPassword"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task GetAliases()
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
_aliases = await AliasService.GetAliasesAsync();
|
||||||
|
_aliases = _aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId).OrderBy(item => item.AliasId).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddAlias()
|
||||||
|
{
|
||||||
|
_aliases.Add(new Alias { AliasId = 0, Name = "", IsDefault = false });
|
||||||
|
_aliasid = 0;
|
||||||
|
_aliasname = "";
|
||||||
|
_defaultalias = "False";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EditAlias(Alias alias)
|
||||||
|
{
|
||||||
|
_aliasid = alias.AliasId;
|
||||||
|
_aliasname = alias.Name;
|
||||||
|
_defaultalias = alias.IsDefault.ToString();
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteAlias(Alias alias)
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
await AliasService.DeleteAliasAsync(alias.AliasId);
|
||||||
|
await GetAliases();
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveAlias()
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(_aliasname))
|
||||||
|
{
|
||||||
|
var aliases = await AliasService.GetAliasesAsync();
|
||||||
|
var alias = aliases.Where(item => item.Name == _aliasname).FirstOrDefault();
|
||||||
|
bool unique = (alias == null || alias.AliasId == _aliasid);
|
||||||
|
if (unique)
|
||||||
|
{
|
||||||
|
if (_aliasid == 0)
|
||||||
|
{
|
||||||
|
alias = new Alias { SiteId = PageState.Site.SiteId, TenantId = PageState.Site.TenantId, Name = _aliasname, IsDefault = bool.Parse(_defaultalias) };
|
||||||
|
await AliasService.AddAliasAsync(alias);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias = _aliases.Single(item => item.AliasId == _aliasid);
|
||||||
|
alias.Name = _aliasname;
|
||||||
|
alias.IsDefault = bool.Parse(_defaultalias);
|
||||||
|
await AliasService.UpdateAliasAsync(alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // duplicate alias
|
||||||
|
{
|
||||||
|
AddModuleMessage(Localizer["Message.Aliases.Taken"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await GetAliases();
|
||||||
|
_aliasid = -1;
|
||||||
|
_aliasname = "";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CancelAlias()
|
||||||
|
{
|
||||||
|
await GetAliases();
|
||||||
|
_aliasid = -1;
|
||||||
|
_aliasname = "";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ else
|
|||||||
</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="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>
|
<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)." ResourceKey="Aliases">Aliases: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
|
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
|
||||||
</div>
|
</div>
|
||||||
@ -128,25 +128,43 @@ else
|
|||||||
<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="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
|
@if (_databases != null)
|
||||||
@foreach (var database in _databases)
|
{
|
||||||
{
|
<div class="input-group">
|
||||||
if (database.IsDefault)
|
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
|
||||||
{
|
@foreach (var database in _databases)
|
||||||
<option value="@database.Name" selected>@Localizer[@database.Name]</option>
|
{
|
||||||
}
|
<option value="@database.Name">@Localizer[@database.Name]</option>
|
||||||
else
|
}
|
||||||
{
|
</select>
|
||||||
<option value="@database.Name">@Localizer[@database.Name]</option>
|
@if (!_showConnectionString)
|
||||||
}
|
{
|
||||||
}
|
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionString"]</button>
|
||||||
</select>
|
}
|
||||||
</div>
|
else
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionParameters"]</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
if (_databaseConfigType != null)
|
@if (!_showConnectionString)
|
||||||
{
|
{
|
||||||
@DatabaseConfigComponent;
|
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">String:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="connectionstring" class="form-control" @bind="@_connectionString" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="hostUsername" HelpText="Enter the username of an existing host user" ResourceKey="HostUsername">Host Username:</Label>
|
<Label Class="col-sm-3" For="hostUsername" HelpText="Enter the username of an existing host user" ResourceKey="HostUsername">Host Username:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@ -156,7 +174,7 @@ else
|
|||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="hostPassword" HelpText="Enter the password of an existing host user" ResourceKey="HostPassword">Host Password:</Label>
|
<Label Class="col-sm-3" For="hostPassword" HelpText="Enter the password of an existing host user" ResourceKey="HostPassword">Host Password:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" required />
|
<input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" autocomplete="new-password" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -169,153 +187,171 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Database> _databases;
|
private List<Database> _databases;
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private string _databaseName = "LocalDB";
|
private string _databaseName;
|
||||||
private Type _databaseConfigType;
|
private Type _databaseConfigType;
|
||||||
private object _databaseConfig;
|
private object _databaseConfig;
|
||||||
private RenderFragment DatabaseConfigComponent { get; set; }
|
private RenderFragment DatabaseConfigComponent { get; set; }
|
||||||
|
private bool _showConnectionString = false;
|
||||||
|
private string _connectionString = string.Empty;
|
||||||
|
|
||||||
|
private List<Theme> _themeList;
|
||||||
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
|
private List<SiteTemplate> _siteTemplates;
|
||||||
|
private List<Tenant> _tenants;
|
||||||
|
private string _tenantid = "-";
|
||||||
|
|
||||||
private List<Theme> _themeList;
|
private string _tenantName = string.Empty;
|
||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
|
||||||
private List<SiteTemplate> _siteTemplates;
|
|
||||||
private List<Tenant> _tenants;
|
|
||||||
private string _tenantid = "-";
|
|
||||||
|
|
||||||
private string _tenantName = string.Empty;
|
private string _hostusername = string.Empty;
|
||||||
|
private string _hostpassword = string.Empty;
|
||||||
|
|
||||||
private string _hostusername = string.Empty;
|
private string _name = string.Empty;
|
||||||
private string _hostpassword = string.Empty;
|
private string _urls = string.Empty;
|
||||||
|
private string _themetype = "-";
|
||||||
|
private string _containertype = "-";
|
||||||
|
private string _admincontainertype = "";
|
||||||
|
private string _sitetemplatetype = "-";
|
||||||
|
private string _runtime = "Server";
|
||||||
|
private string _prerender = "Prerendered";
|
||||||
|
|
||||||
private string _name = string.Empty;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
private string _urls = string.Empty;
|
|
||||||
private string _themetype = "-";
|
|
||||||
private string _containertype = "-";
|
|
||||||
private string _admincontainertype = "";
|
|
||||||
private string _sitetemplatetype = "-";
|
|
||||||
private string _runtime = "Server";
|
|
||||||
private string _prerender = "Prerendered";
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
_tenants = await TenantService.GetTenantsAsync();
|
||||||
|
_urls = PageState.Alias.Name;
|
||||||
|
_themeList = await ThemeService.GetThemesAsync();
|
||||||
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
|
_siteTemplates = await SiteTemplateService.GetSiteTemplatesAsync();
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
_databases = await DatabaseService.GetDatabasesAsync();
|
||||||
{
|
if (_databases.Exists(item => item.IsDefault))
|
||||||
_tenants = await TenantService.GetTenantsAsync();
|
{
|
||||||
_urls = PageState.Alias.Name;
|
_databaseName = _databases.Find(item => item.IsDefault).Name;
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
}
|
||||||
_themes = ThemeService.GetThemeControls(_themeList);
|
else
|
||||||
_siteTemplates = await SiteTemplateService.GetSiteTemplatesAsync();
|
{
|
||||||
_databases = await DatabaseService.GetDatabasesAsync();
|
_databaseName = "LocalDB";
|
||||||
LoadDatabaseConfigComponent();
|
}
|
||||||
}
|
LoadDatabaseConfigComponent();
|
||||||
|
}
|
||||||
|
|
||||||
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_databaseName = (string)eventArgs.Value;
|
_databaseName = (string)eventArgs.Value;
|
||||||
|
_showConnectionString = false;
|
||||||
|
LoadDatabaseConfigComponent();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
AddModuleMessage(Localizer["Error.Database.LoadConfig"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LoadDatabaseConfigComponent();
|
private void LoadDatabaseConfigComponent()
|
||||||
}
|
{
|
||||||
catch
|
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||||
{
|
if (database != null)
|
||||||
AddModuleMessage(Localizer["Error.Database.LoadConfig"], MessageType.Error);
|
{
|
||||||
}
|
_databaseConfigType = Type.GetType(database.ControlType);
|
||||||
}
|
DatabaseConfigComponent = builder =>
|
||||||
|
{
|
||||||
|
builder.OpenComponent(0, _databaseConfigType);
|
||||||
|
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
|
||||||
|
builder.CloseComponent();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void LoadDatabaseConfigComponent()
|
private void TenantChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
_tenantid = (string)e.Value;
|
||||||
if (database != null)
|
if (string.IsNullOrEmpty(_tenantName))
|
||||||
{
|
{
|
||||||
_databaseConfigType = Type.GetType(database.ControlType);
|
_tenantName = _name;
|
||||||
DatabaseConfigComponent = builder =>
|
}
|
||||||
{
|
StateHasChanged();
|
||||||
builder.OpenComponent(0, _databaseConfigType);
|
}
|
||||||
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
|
|
||||||
builder.CloseComponent();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TenantChanged(ChangeEventArgs e)
|
private async void ThemeChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_tenantid = (string)e.Value;
|
try
|
||||||
if (string.IsNullOrEmpty(_tenantName))
|
{
|
||||||
{
|
_themetype = (string)e.Value;
|
||||||
_tenantName = _name;
|
if (_themetype != "-")
|
||||||
}
|
{
|
||||||
StateHasChanged();
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_containers = new List<ThemeControl>();
|
||||||
|
}
|
||||||
|
_containertype = "-";
|
||||||
|
_admincontainertype = "";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Loading Containers For Theme {ThemeType} {Error}", _themetype, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error.Theme.LoadContainers"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void ThemeChanged(ChangeEventArgs e)
|
private async Task SaveSite()
|
||||||
{
|
{
|
||||||
try
|
validated = true;
|
||||||
{
|
var interop = new Interop(JSRuntime);
|
||||||
_themetype = (string)e.Value;
|
if (await interop.FormValid(form))
|
||||||
if (_themetype != "-")
|
{
|
||||||
{
|
if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-")
|
||||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
{
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_containers = new List<ThemeControl>();
|
|
||||||
}
|
|
||||||
_containertype = "-";
|
|
||||||
_admincontainertype = "";
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Loading Containers For Theme {ThemeType} {Error}", _themetype, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Theme.LoadContainers"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveSite()
|
|
||||||
{
|
|
||||||
validated = true;
|
|
||||||
var interop = new Interop(JSRuntime);
|
|
||||||
if (await interop.FormValid(form))
|
|
||||||
{
|
|
||||||
if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-")
|
|
||||||
{
|
|
||||||
_urls = Regex.Replace(_urls, @"\r\n?|\n", ",");
|
_urls = Regex.Replace(_urls, @"\r\n?|\n", ",");
|
||||||
var duplicates = new List<string>();
|
var duplicates = new List<string>();
|
||||||
var aliases = await AliasService.GetAliasesAsync();
|
var aliases = await AliasService.GetAliasesAsync();
|
||||||
foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
if (aliases.Exists(item => item.Name == name))
|
if (aliases.Exists(item => item.Name == name))
|
||||||
{
|
{
|
||||||
duplicates.Add(name);
|
duplicates.Add(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (duplicates.Count == 0)
|
if (duplicates.Count == 0)
|
||||||
{
|
{
|
||||||
InstallConfig config = new InstallConfig();
|
InstallConfig config = new InstallConfig();
|
||||||
|
|
||||||
if (_tenantid == "+")
|
if (_tenantid == "+")
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_tenantName) && _tenants.FirstOrDefault(item => item.Name == _tenantName) == null)
|
if (!string.IsNullOrEmpty(_tenantName) && _tenants.FirstOrDefault(item => item.Name == _tenantName) == null)
|
||||||
{
|
{
|
||||||
// validate host credentials
|
// validate host credentials
|
||||||
var user = new User();
|
var user = new User();
|
||||||
user.SiteId = PageState.Site.SiteId;
|
user.SiteId = PageState.Site.SiteId;
|
||||||
user.Username = _hostusername;
|
user.Username = _hostusername;
|
||||||
user.Password = _hostpassword;
|
user.Password = _hostpassword;
|
||||||
user = await UserService.LoginUserAsync(user, false, false);
|
user.LastIPAddress = PageState.RemoteIPAddress;
|
||||||
|
user = await UserService.LoginUserAsync(user);
|
||||||
if (user.IsAuthenticated)
|
if (user.IsAuthenticated)
|
||||||
{
|
{
|
||||||
var connectionString = String.Empty;
|
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||||
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
var connectionString = String.Empty;
|
||||||
{
|
if (_showConnectionString)
|
||||||
connectionString = databaseConfigControl.GetConnectionString();
|
{
|
||||||
}
|
connectionString = _connectionString;
|
||||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||||
|
{
|
||||||
|
connectionString = databaseConfigControl.GetConnectionString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (connectionString != "")
|
if (connectionString != "")
|
||||||
{
|
{
|
||||||
@ -396,4 +432,13 @@ else
|
|||||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleConnectionString()
|
||||||
|
{
|
||||||
|
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||||
|
{
|
||||||
|
_connectionString = databaseConfigControl.GetConnectionString();
|
||||||
|
}
|
||||||
|
_showConnectionString = !_showConnectionString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,13 @@
|
|||||||
<input id="ipaddress" class="form-control" @bind="@_ipaddress" readonly />
|
<input id="ipaddress" class="form-control" @bind="@_ipaddress" readonly />
|
||||||
</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="environment" HelpText="Environment name" ResourceKey="Environment">Environment: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="environment" class="form-control" @bind="@_environment" readonly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="contentrootpath" HelpText="Root Path" ResourceKey="ContentRootPath">Root Path: </Label>
|
<Label Class="col-sm-3" For="contentrootpath" HelpText="Root Path" ResourceKey="ContentRootPath">Root Path: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="contentrootpath" class="form-control" @bind="@_contentrootpath" readonly />
|
<input id="contentrootpath" class="form-control" @bind="@_contentrootpath" readonly />
|
||||||
@ -142,6 +148,7 @@
|
|||||||
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
@ -151,6 +158,7 @@
|
|||||||
private string _osversion = string.Empty;
|
private string _osversion = string.Empty;
|
||||||
private string _machinename = string.Empty;
|
private string _machinename = string.Empty;
|
||||||
private string _ipaddress = string.Empty;
|
private string _ipaddress = string.Empty;
|
||||||
|
private string _environment = string.Empty;
|
||||||
private string _contentrootpath = string.Empty;
|
private string _contentrootpath = string.Empty;
|
||||||
private string _webrootpath = string.Empty;
|
private string _webrootpath = string.Empty;
|
||||||
private string _servertime = string.Empty;
|
private string _servertime = string.Empty;
|
||||||
@ -175,6 +183,7 @@
|
|||||||
_osversion = systeminfo["OSVersion"].ToString();
|
_osversion = systeminfo["OSVersion"].ToString();
|
||||||
_machinename = systeminfo["MachineName"].ToString();
|
_machinename = systeminfo["MachineName"].ToString();
|
||||||
_ipaddress = systeminfo["IPAddress"].ToString();
|
_ipaddress = systeminfo["IPAddress"].ToString();
|
||||||
|
_environment = systeminfo["Environment"].ToString();
|
||||||
_contentrootpath = systeminfo["ContentRootPath"].ToString();
|
_contentrootpath = systeminfo["ContentRootPath"].ToString();
|
||||||
_webrootpath = systeminfo["WebRootPath"].ToString();
|
_webrootpath = systeminfo["WebRootPath"].ToString();
|
||||||
_servertime = systeminfo["ServerTime"].ToString() + " UTC";
|
_servertime = systeminfo["ServerTime"].ToString() + " UTC";
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||||
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||||
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||||
|
@((MarkupString)(!string.IsNullOrEmpty(context.PackageUrl) ? " | " + SharedLocalizer["Search.Source"] + ": <strong>" + new Uri(context.PackageUrl).Host + "</strong>" : ""))
|
||||||
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 1px; vertical-align: middle;">
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
private List<Template> _templates;
|
private List<Template> _templates;
|
||||||
private string _template = "-";
|
private string _template = "-";
|
||||||
private string[] _versions;
|
private string[] _versions;
|
||||||
private string _reference = Constants.Version;
|
private string _reference = "local";
|
||||||
private string _minversion = "2.0.0";
|
private string _minversion = "2.0.0";
|
||||||
private string _location = string.Empty;
|
private string _location = string.Empty;
|
||||||
|
|
||||||
|
@ -40,9 +40,12 @@ else
|
|||||||
@((MarkupString)PurchaseLink(context.PackageName))
|
@((MarkupString)PurchaseLink(context.PackageName))
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@if (UpgradeAvailable(context.PackageName, context.Version))
|
@{
|
||||||
|
var version = UpgradeAvailable(context.PackageName, context.Version);
|
||||||
|
}
|
||||||
|
@if (version != context.Version)
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.PackageName, context.Version))>@SharedLocalizer["Upgrade"]</button>
|
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.PackageName, version))>@SharedLocalizer["Upgrade"]</button>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
@ -94,18 +97,17 @@ else
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpgradeAvailable(string packagename, string version)
|
private string UpgradeAvailable(string packagename, string version)
|
||||||
{
|
{
|
||||||
var upgradeavailable = false;
|
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
||||||
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
{
|
||||||
{
|
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||||
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
if (package != null && Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0)
|
||||||
if (package != null)
|
{
|
||||||
{
|
return package.Version;
|
||||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return upgradeavailable;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadTheme(string packagename, string version)
|
private async Task DownloadTheme(string packagename, string version)
|
||||||
|
@ -25,7 +25,13 @@
|
|||||||
<input id="version" class="form-control" @bind="@_version" disabled />
|
<input id="version" class="form-control" @bind="@_version" disabled />
|
||||||
</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="packagename" HelpText="The unique name of the package from which this module was installed" ResourceKey="PackageName">Package Name: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the theme" ResourceKey="Owner">Owner: </Label>
|
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the theme" ResourceKey="Owner">Owner: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
||||||
@ -53,28 +59,30 @@
|
|||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _themeName = "";
|
private string _themeName = "";
|
||||||
private string _name;
|
private string _name;
|
||||||
private string _version;
|
private string _version;
|
||||||
private string _owner = "";
|
private string _packagename;
|
||||||
private string _url = "";
|
private string _owner = "";
|
||||||
private string _contact = "";
|
private string _url = "";
|
||||||
private string _license = "";
|
private string _contact = "";
|
||||||
|
private string _license = "";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themeName = WebUtility.UrlDecode(PageState.QueryString["name"]);
|
_themeName = WebUtility.UrlDecode(PageState.QueryString["name"]);
|
||||||
var themes = await ThemeService.GetThemesAsync();
|
var themes = await ThemeService.GetThemesAsync();
|
||||||
var theme = themes.FirstOrDefault(item => item.ThemeName == _themeName);
|
var theme = themes.FirstOrDefault(item => item.ThemeName == _themeName);
|
||||||
if (theme != null)
|
if (theme != null)
|
||||||
{
|
{
|
||||||
_name = theme.Name;
|
_name = theme.Name;
|
||||||
_version = theme.Version;
|
_version = theme.Version;
|
||||||
_owner = theme.Owner;
|
_packagename = theme.PackageName;
|
||||||
|
_owner = theme.Owner;
|
||||||
_url = theme.Url;
|
_url = theme.Url;
|
||||||
_contact = theme.Contact;
|
_contact = theme.Contact;
|
||||||
_license = theme.License;
|
_license = theme.License;
|
||||||
|
@ -31,14 +31,20 @@ else
|
|||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="password" HelpText="If you wish to change your password you can enter it here. Please choose a sufficiently secure password." ResourceKey="Password"></Label>
|
<Label Class="col-sm-3" For="password" HelpText="If you wish to change your password you can enter it here. Please choose a sufficiently secure password." ResourceKey="Password"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="password" type="password" class="form-control" @bind="@password" autocomplete="new-password" />
|
<div class="input-group">
|
||||||
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</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="confirm" HelpText="If you are changing your password you must enter it again to confirm it matches" ResourceKey="Confirm"></Label>
|
<Label Class="col-sm-3" For="confirm" HelpText="If you are changing your password you must enter it again to confirm it matches" ResourceKey="Confirm"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="confirm" type="password" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
<div class="input-group">
|
||||||
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@if (allowtwofactor)
|
@if (allowtwofactor)
|
||||||
@ -154,7 +160,7 @@ else
|
|||||||
<td><ActionDialog Header="Delete Notification" Message="Are You Sure You Wish To Delete This Notification?" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" ResourceKey="DeleteNotification" /></td>
|
<td><ActionDialog Header="Delete Notification" Message="Are You Sure You Wish To Delete This Notification?" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" ResourceKey="DeleteNotification" /></td>
|
||||||
<td>@context.FromDisplayName</td>
|
<td>@context.FromDisplayName</td>
|
||||||
<td>@context.Subject</td>
|
<td>@context.Subject</td>
|
||||||
<td>@context.CreatedOn</td>
|
<td>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn)</td>
|
||||||
</Row>
|
</Row>
|
||||||
<Detail>
|
<Detail>
|
||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
@ -187,7 +193,7 @@ else
|
|||||||
<td><ActionDialog Header="Delete Notification" Message="Are You Sure You Wish To Delete This Notification?" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" ResourceKey="DeleteNotification" /></td>
|
<td><ActionDialog Header="Delete Notification" Message="Are You Sure You Wish To Delete This Notification?" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" ResourceKey="DeleteNotification" /></td>
|
||||||
<td>@context.ToDisplayName</td>
|
<td>@context.ToDisplayName</td>
|
||||||
<td>@context.Subject</td>
|
<td>@context.Subject</td>
|
||||||
<td>@context.CreatedOn</td>
|
<td>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn)</td>
|
||||||
</Row>
|
</Row>
|
||||||
<Detail>
|
<Detail>
|
||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
@ -205,6 +211,8 @@ else
|
|||||||
</Detail>
|
</Detail>
|
||||||
</Pager>
|
</Pager>
|
||||||
}
|
}
|
||||||
|
<br />
|
||||||
|
<ActionDialog Header="Clear Notifications" Message="Are You Sure You Wish To Permanently Delete All Notifications ?" Action="Delete All Notifications" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteAllNotifications())" ResourceKey="DeleteAllNotifications" />
|
||||||
<br /><hr />
|
<br /><hr />
|
||||||
<select class="form-select" @onchange="(e => FilterChanged(e))">
|
<select class="form-select" @onchange="(e => FilterChanged(e))">
|
||||||
<option value="to">@Localizer["Inbox"]</option>
|
<option value="to">@Localizer["Inbox"]</option>
|
||||||
@ -216,122 +224,126 @@ else
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string username = string.Empty;
|
private string username = string.Empty;
|
||||||
private string password = string.Empty;
|
private string _password = string.Empty;
|
||||||
private string confirm = string.Empty;
|
private string _passwordtype = "password";
|
||||||
private bool allowtwofactor = false;
|
private string _togglepassword = string.Empty;
|
||||||
private string twofactor = "False";
|
private string confirm = string.Empty;
|
||||||
private string email = string.Empty;
|
private bool allowtwofactor = false;
|
||||||
private string displayname = string.Empty;
|
private string twofactor = "False";
|
||||||
private FileManager filemanager;
|
private string email = string.Empty;
|
||||||
private int folderid = -1;
|
private string displayname = string.Empty;
|
||||||
private int photofileid = -1;
|
private FileManager filemanager;
|
||||||
private File photo = null;
|
private int folderid = -1;
|
||||||
private List<Profile> profiles;
|
private int photofileid = -1;
|
||||||
private Dictionary<string, string> settings;
|
private File photo = null;
|
||||||
private string category = string.Empty;
|
private List<Profile> profiles;
|
||||||
private string filter = "to";
|
private Dictionary<string, string> settings;
|
||||||
private List<Notification> notifications;
|
private string category = string.Empty;
|
||||||
|
private string filter = "to";
|
||||||
|
private List<Notification> notifications;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (PageState.Site.Settings.ContainsKey("LoginOptions:TwoFactor") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:TwoFactor"]))
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
{
|
|
||||||
allowtwofactor = bool.Parse(PageState.Site.Settings["LoginOptions:TwoFactor"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PageState.User != null)
|
if (PageState.Site.Settings.ContainsKey("LoginOptions:TwoFactor") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:TwoFactor"]))
|
||||||
{
|
{
|
||||||
username = PageState.User.Username;
|
allowtwofactor = (PageState.Site.Settings["LoginOptions:TwoFactor"] == "true");
|
||||||
twofactor = PageState.User.TwoFactorRequired.ToString();
|
}
|
||||||
email = PageState.User.Email;
|
|
||||||
displayname = PageState.User.DisplayName;
|
|
||||||
|
|
||||||
// get user folder
|
if (PageState.User != null)
|
||||||
var folder = await FolderService.GetFolderAsync(ModuleState.SiteId, PageState.User.FolderPath);
|
{
|
||||||
if (folder != null)
|
username = PageState.User.Username;
|
||||||
{
|
twofactor = PageState.User.TwoFactorRequired.ToString();
|
||||||
folderid = folder.FolderId;
|
email = PageState.User.Email;
|
||||||
}
|
displayname = PageState.User.DisplayName;
|
||||||
|
|
||||||
if (PageState.User.PhotoFileId != null)
|
// get user folder
|
||||||
{
|
var folder = await FolderService.GetFolderAsync(ModuleState.SiteId, PageState.User.FolderPath);
|
||||||
photofileid = PageState.User.PhotoFileId.Value;
|
if (folder != null)
|
||||||
photo = await FileService.GetFileAsync(photofileid);
|
{
|
||||||
}
|
folderid = folder.FolderId;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
photofileid = -1;
|
|
||||||
photo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
if (PageState.User.PhotoFileId != null)
|
||||||
settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
{
|
||||||
|
photofileid = PageState.User.PhotoFileId.Value;
|
||||||
|
photo = await FileService.GetFileAsync(photofileid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
photofileid = -1;
|
||||||
|
photo = null;
|
||||||
|
}
|
||||||
|
|
||||||
await LoadNotificationsAsync();
|
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||||
}
|
settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
else
|
|
||||||
{
|
|
||||||
AddModuleMessage(Localizer["Message.User.NoLogIn"], MessageType.Warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Loading User Profile {Error}", ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Profile.Load"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadNotificationsAsync()
|
await LoadNotificationsAsync();
|
||||||
{
|
}
|
||||||
notifications = await NotificationService.GetNotificationsAsync(PageState.Site.SiteId, filter, PageState.User.UserId);
|
else
|
||||||
notifications = notifications.Where(item => item.DeletedBy != PageState.User.Username).ToList();
|
{
|
||||||
}
|
AddModuleMessage(Localizer["Message.User.NoLogIn"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Loading User Profile {Error}", ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error.Profile.Load"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
private async Task LoadNotificationsAsync()
|
||||||
=> SettingService.GetSetting(settings, SettingName, DefaultValue);
|
{
|
||||||
|
notifications = await NotificationService.GetNotificationsAsync(PageState.Site.SiteId, filter, PageState.User.UserId);
|
||||||
|
notifications = notifications.Where(item => item.DeletedBy != PageState.User.Username).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
private async Task Save()
|
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||||
{
|
=> SettingService.GetSetting(settings, SettingName, DefaultValue);
|
||||||
try
|
|
||||||
{
|
|
||||||
if (username != string.Empty && email != string.Empty && ValidateProfiles())
|
|
||||||
{
|
|
||||||
if (password == confirm)
|
|
||||||
{
|
|
||||||
var user = PageState.User;
|
|
||||||
user.Username = username;
|
|
||||||
user.Password = password;
|
|
||||||
user.TwoFactorRequired = bool.Parse(twofactor);
|
|
||||||
user.Email = email;
|
|
||||||
user.DisplayName = (displayname == string.Empty ? username : displayname);
|
|
||||||
user.PhotoFileId = filemanager.GetFileId();
|
|
||||||
if (user.PhotoFileId == -1)
|
|
||||||
{
|
|
||||||
user.PhotoFileId = null;
|
|
||||||
}
|
|
||||||
if (user.PhotoFileId != null)
|
|
||||||
{
|
|
||||||
photofileid = user.PhotoFileId.Value;
|
|
||||||
photo = await FileService.GetFileAsync(photofileid);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
photofileid = -1;
|
|
||||||
photo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
await UserService.UpdateUserAsync(user);
|
private async Task Save()
|
||||||
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
{
|
||||||
await logger.LogInformation("User Profile Saved");
|
try
|
||||||
|
{
|
||||||
|
if (username != string.Empty && email != string.Empty && ValidateProfiles())
|
||||||
|
{
|
||||||
|
if (_password == confirm)
|
||||||
|
{
|
||||||
|
var user = PageState.User;
|
||||||
|
user.Username = username;
|
||||||
|
user.Password = _password;
|
||||||
|
user.TwoFactorRequired = bool.Parse(twofactor);
|
||||||
|
user.Email = email;
|
||||||
|
user.DisplayName = (displayname == string.Empty ? username : displayname);
|
||||||
|
user.PhotoFileId = filemanager.GetFileId();
|
||||||
|
if (user.PhotoFileId == -1)
|
||||||
|
{
|
||||||
|
user.PhotoFileId = null;
|
||||||
|
}
|
||||||
|
if (user.PhotoFileId != null)
|
||||||
|
{
|
||||||
|
photofileid = user.PhotoFileId.Value;
|
||||||
|
photo = await FileService.GetFileAsync(photofileid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
photofileid = -1;
|
||||||
|
photo = null;
|
||||||
|
}
|
||||||
|
|
||||||
AddModuleMessage(Localizer["Success.Profile.Update"], MessageType.Success);
|
await UserService.UpdateUserAsync(user);
|
||||||
StateHasChanged();
|
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
||||||
}
|
await logger.LogInformation("User Profile Saved");
|
||||||
|
|
||||||
|
AddModuleMessage(Localizer["Success.Profile.Update"], MessageType.Success);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Message.Password.Invalid"], MessageType.Warning);
|
AddModuleMessage(Localizer["Message.Password.Invalid"], MessageType.Warning);
|
||||||
@ -413,4 +425,47 @@ else
|
|||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task DeleteAllNotifications()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach(var Notification in notifications)
|
||||||
|
{
|
||||||
|
if (!Notification.IsDeleted)
|
||||||
|
{
|
||||||
|
Notification.IsDeleted = true;
|
||||||
|
await NotificationService.UpdateNotificationAsync(Notification);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await NotificationService.DeleteNotificationAsync(Notification.NotificationId);
|
||||||
|
}
|
||||||
|
await logger.LogInformation("Notification Deleted {Notification}", Notification);
|
||||||
|
}
|
||||||
|
await logger.LogInformation("Notifications Permanently Deleted");
|
||||||
|
await LoadNotificationsAsync();
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Deleting Notifications {Error}", ex.Message);
|
||||||
|
AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TogglePassword()
|
||||||
|
{
|
||||||
|
if (_passwordtype == "password")
|
||||||
|
{
|
||||||
|
_passwordtype = "text";
|
||||||
|
_togglepassword = SharedLocalizer["HidePassword"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_passwordtype = "password";
|
||||||
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,20 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="password" HelpText="The user's password. Please choose a password which is sufficiently secure." ResourceKey="Password"></Label>
|
<Label Class="col-sm-3" For="password" HelpText="The user's password. Please choose a password which is sufficiently secure." ResourceKey="Password"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="password" type="password" class="form-control" @bind="@password" />
|
<div class="input-group">
|
||||||
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</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="confirm" HelpText="Please enter the password again to confirm it matches with the value above" ResourceKey="Confirm"></Label>
|
<Label Class="col-sm-3" For="confirm" HelpText="Please enter the password again to confirm it matches with the value above" ResourceKey="Confirm"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="confirm" type="password" class="form-control" @bind="@confirm" />
|
<div class="input-group">
|
||||||
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" required />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@ -88,7 +94,9 @@
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string username = string.Empty;
|
private string username = string.Empty;
|
||||||
private string password = string.Empty;
|
private string _password = string.Empty;
|
||||||
|
private string _passwordtype = "password";
|
||||||
|
private string _togglepassword = string.Empty;
|
||||||
private string confirm = string.Empty;
|
private string confirm = string.Empty;
|
||||||
private string email = string.Empty;
|
private string email = string.Empty;
|
||||||
private string displayname = string.Empty;
|
private string displayname = string.Empty;
|
||||||
@ -102,6 +110,7 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||||
settings = new Dictionary<string, string>();
|
settings = new Dictionary<string, string>();
|
||||||
}
|
}
|
||||||
@ -119,9 +128,9 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (username != string.Empty && password != string.Empty && confirm != string.Empty && email != string.Empty && ValidateProfiles())
|
if (username != string.Empty && _password != string.Empty && confirm != string.Empty && email != string.Empty && ValidateProfiles())
|
||||||
{
|
{
|
||||||
if (password == confirm)
|
if (_password == confirm)
|
||||||
{
|
{
|
||||||
var user = await UserService.GetUserAsync(username, PageState.Site.SiteId);
|
var user = await UserService.GetUserAsync(username, PageState.Site.SiteId);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
@ -129,7 +138,7 @@
|
|||||||
user = new User();
|
user = new User();
|
||||||
user.SiteId = PageState.Site.SiteId;
|
user.SiteId = PageState.Site.SiteId;
|
||||||
user.Username = username;
|
user.Username = username;
|
||||||
user.Password = password;
|
user.Password = _password;
|
||||||
user.Email = email;
|
user.Email = email;
|
||||||
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
||||||
user.PhotoFileId = null;
|
user.PhotoFileId = null;
|
||||||
@ -193,4 +202,17 @@
|
|||||||
settings = SettingService.SetSetting(settings, SettingName, value);
|
settings = SettingService.SetSetting(settings, SettingName, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TogglePassword()
|
||||||
|
{
|
||||||
|
if (_passwordtype == "password")
|
||||||
|
{
|
||||||
|
_passwordtype = "text";
|
||||||
|
_togglepassword = SharedLocalizer["HidePassword"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_passwordtype = "password";
|
||||||
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,20 @@ else
|
|||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="password" HelpText="The user's password. Please choose a password which is sufficiently secure." ResourceKey="Password"></Label>
|
<Label Class="col-sm-3" For="password" HelpText="The user's password. Please choose a password which is sufficiently secure." ResourceKey="Password"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="password" type="password" class="form-control" @bind="@password" />
|
<div class="input-group">
|
||||||
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</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="confirm" HelpText="Please enter the password again to confirm it matches with the value above" ResourceKey="Confirm"></Label>
|
<Label Class="col-sm-3" For="confirm" HelpText="Please enter the password again to confirm it matches with the value above" ResourceKey="Confirm"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="confirm" type="password" class="form-control" @bind="@confirm" />
|
<div class="input-group">
|
||||||
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@ -66,8 +72,19 @@ else
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="lastlogin" HelpText="The date and time when the user last signed in" ResourceKey="LastLogin"></Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="lastlogin" class="form-control" @bind="@lastlogin" readonly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="lastipaddress" HelpText="The IP Address of the user recorded during their last login" ResourceKey="LastIPAddress"></Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="lastipaddress" class="form-control" @bind="@lastipaddress" readonly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
}
|
}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Profile" ResourceKey="Profile">
|
<TabPanel Name="Profile" ResourceKey="Profile">
|
||||||
@ -131,61 +148,70 @@ else
|
|||||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
|
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private int userid;
|
private int userid;
|
||||||
private string username = string.Empty;
|
private string username = string.Empty;
|
||||||
private string password = string.Empty;
|
private string _password = string.Empty;
|
||||||
private string confirm = string.Empty;
|
private string _passwordtype = "password";
|
||||||
private string email = string.Empty;
|
private string _togglepassword = string.Empty;
|
||||||
private string displayname = string.Empty;
|
private string confirm = string.Empty;
|
||||||
private FileManager filemanager;
|
private string email = string.Empty;
|
||||||
private int photofileid = -1;
|
private string displayname = string.Empty;
|
||||||
private File photo = null;
|
private FileManager filemanager;
|
||||||
private List<Profile> profiles;
|
private int photofileid = -1;
|
||||||
private Dictionary<string, string> settings;
|
private File photo = null;
|
||||||
private string category = string.Empty;
|
private string isdeleted;
|
||||||
private string createdby;
|
private string lastlogin;
|
||||||
private DateTime createdon;
|
private string lastipaddress;
|
||||||
private string modifiedby;
|
|
||||||
private DateTime modifiedon;
|
|
||||||
private string deletedby;
|
|
||||||
private DateTime? deletedon;
|
|
||||||
private string isdeleted;
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
private List<Profile> profiles;
|
||||||
|
private Dictionary<string, string> settings;
|
||||||
|
private string category = string.Empty;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
private string createdby;
|
||||||
{
|
private DateTime createdon;
|
||||||
try
|
private string modifiedby;
|
||||||
{
|
private DateTime modifiedon;
|
||||||
// OnParametersSetAsync is called when the edit modal is closed - in which case there is no id parameter
|
private string deletedby;
|
||||||
if (PageState.QueryString.ContainsKey("id"))
|
private DateTime? deletedon;
|
||||||
{
|
|
||||||
profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
userid = Int32.Parse(PageState.QueryString["id"]);
|
|
||||||
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
protected override async Task OnParametersSetAsync()
|
||||||
if (user != null)
|
{
|
||||||
{
|
try
|
||||||
username = user.Username;
|
{
|
||||||
email = user.Email;
|
if (PageState.QueryString.ContainsKey("id"))
|
||||||
displayname = user.DisplayName;
|
{
|
||||||
if (user.PhotoFileId != null)
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
{
|
profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
|
||||||
photofileid = user.PhotoFileId.Value;
|
userid = Int32.Parse(PageState.QueryString["id"]);
|
||||||
photo = await FileService.GetFileAsync(photofileid);
|
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||||
}
|
if (user != null)
|
||||||
else
|
{
|
||||||
{
|
username = user.Username;
|
||||||
photofileid = -1;
|
email = user.Email;
|
||||||
photo = null;
|
displayname = user.DisplayName;
|
||||||
}
|
if (user.PhotoFileId != null)
|
||||||
settings = await SettingService.GetUserSettingsAsync(user.UserId);
|
{
|
||||||
|
photofileid = user.PhotoFileId.Value;
|
||||||
|
photo = await FileService.GetFileAsync(photofileid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
photofileid = -1;
|
||||||
|
photo = null;
|
||||||
|
}
|
||||||
|
isdeleted = user.IsDeleted.ToString();
|
||||||
|
lastlogin = string.Format("{0:MMM dd yyyy HH:mm:ss}", user.LastLoginOn);
|
||||||
|
lastipaddress = user.LastIPAddress;
|
||||||
|
|
||||||
|
settings = await SettingService.GetUserSettingsAsync(user.UserId);
|
||||||
createdby = user.CreatedBy;
|
createdby = user.CreatedBy;
|
||||||
createdon = user.CreatedOn;
|
createdon = user.CreatedOn;
|
||||||
modifiedby = user.ModifiedBy;
|
modifiedby = user.ModifiedBy;
|
||||||
modifiedon = user.ModifiedOn;
|
modifiedon = user.ModifiedOn;
|
||||||
deletedby = user.DeletedBy;
|
deletedby = user.DeletedBy;
|
||||||
deletedon = user.DeletedOn;
|
deletedon = user.DeletedOn;
|
||||||
isdeleted = user.IsDeleted.ToString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,12 +231,12 @@ else
|
|||||||
{
|
{
|
||||||
if (username != string.Empty && email != string.Empty && ValidateProfiles())
|
if (username != string.Empty && email != string.Empty && ValidateProfiles())
|
||||||
{
|
{
|
||||||
if (password == confirm)
|
if (_password == confirm)
|
||||||
{
|
{
|
||||||
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||||
user.SiteId = PageState.Site.SiteId;
|
user.SiteId = PageState.Site.SiteId;
|
||||||
user.Username = username;
|
user.Username = username;
|
||||||
user.Password = password;
|
user.Password = _password;
|
||||||
user.Email = email;
|
user.Email = email;
|
||||||
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
||||||
user.PhotoFileId = null;
|
user.PhotoFileId = null;
|
||||||
@ -268,4 +294,17 @@ else
|
|||||||
settings = SettingService.SetSetting(settings, SettingName, value);
|
settings = SettingService.SetSetting(settings, SettingName, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TogglePassword()
|
||||||
|
{
|
||||||
|
if (_passwordtype == "password")
|
||||||
|
{
|
||||||
|
_passwordtype = "text";
|
||||||
|
_togglepassword = SharedLocalizer["HidePassword"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_passwordtype = "password";
|
||||||
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
@inject ISiteService SiteService
|
@inject ISiteService SiteService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
@inject SiteState SiteState
|
||||||
|
|
||||||
@if (userroles == null)
|
@if (users == null)
|
||||||
{
|
{
|
||||||
<p>
|
<p>
|
||||||
<em>@SharedLocalizer["Loading"]</em>
|
<em>@SharedLocalizer["Loading"]</em>
|
||||||
@ -30,13 +31,14 @@ else
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Pager Items="@userroles">
|
<Pager Items="@users" RowClass="align-middle">
|
||||||
<Header>
|
<Header>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>@SharedLocalizer["Name"]</th>
|
<th>@SharedLocalizer["Username"]</th>
|
||||||
<th>@SharedLocalizer["Username"]</th>
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
|
<th>@Localizer["LastLoginOn"]</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td>
|
<td>
|
||||||
@ -48,8 +50,9 @@ else
|
|||||||
<td>
|
<td>
|
||||||
<ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="Roles" />
|
<ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="Roles" />
|
||||||
</td>
|
</td>
|
||||||
<td>@context.User.DisplayName</td>
|
|
||||||
<td>@context.User.Username</td>
|
<td>@context.User.Username</td>
|
||||||
|
<td>@((MarkupString)string.Format("<a href=\"mailto:{0}\">{1}</a>", @context.User.Email, @context.User.DisplayName))</td>
|
||||||
|
<td>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", context.User.LastLoginOn)</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
@ -86,250 +89,260 @@ else
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div class="row mb-1 align-items-center">
|
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
<Label Class="col-sm-3" For="twofactor" HelpText="Do you want to allow users to use two factor authentication? Note that the Notification Job in Scheduled Jobs needs to be enabled for this option to work properly." ResourceKey="TwoFactor">Allow Two Factor?</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="twofactor" class="form-select" @bind="@_twofactor">
|
|
||||||
<option value="true">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="false">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@if (!string.IsNullOrEmpty(PageState.Alias.Path))
|
|
||||||
{
|
{
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="cookietype" HelpText="Cookies are usually managed per domain. However you can also choose to have distinct cookies for each site (this option is only applicable to micro-sites)." ResourceKey="CookieType">Cookie Type:</Label>
|
<Label Class="col-sm-3" For="twofactor" HelpText="Do you want users to use two factor authentication? Note that you should use the Disabled option until you have successfully verified that the Notification Job in Scheduled Jobs is enabled and your SMTP options in Site Settings are configured or else you will lock yourself out." ResourceKey="TwoFactor">Two Factor?</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="cookietype" class="form-select" @bind="@_cookietype">
|
<select id="twofactor" class="form-select" @bind="@_twofactor">
|
||||||
<option value="domain">@Localizer["Domain"]</option>
|
<option value="false">@Localizer["Disabled"]</option>
|
||||||
<option value="site">@Localizer["Site"]</option>
|
<option value="true">@Localizer["Optional"]</option>
|
||||||
|
<option value="required">@Localizer["Required"]</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="cookiename" HelpText="You can choose to use a custom authentication cookie name for each site. However please be aware that if you want to share an authentication cookie between sites on the same domain they need to use a consistent cookie name. Also be aware that changing the authentication cookie name will logout all current users." ResourceKey="CookieName">Cookie Name:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="cookiename" class="form-control" @bind="@_cookiename" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</Section>
|
</Section>
|
||||||
<Section Name="Password" Heading="Password Settings" ResourceKey="PasswordSettings">
|
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
<div class="row mb-1 align-items-center">
|
{
|
||||||
<Label Class="col-sm-3" For="minimumlength" HelpText="The Minimum Length For A Password" ResourceKey="RequiredLength">Minimum Length:</Label>
|
<Section Name="Password" Heading="Password Settings" ResourceKey="PasswordSettings">
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="minimumlength" class="form-control" @bind="@_minimumlength" required />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="uniquecharacters" HelpText="The Minimum Number Of Unique Characters Which A Password Must Contain" ResourceKey="UniqueCharacters">Unique Characters:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="uniquecharacters" class="form-control" @bind="@_uniquecharacters" required />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="requiredigit" HelpText="Indicate If Passwords Must Contain A Digit" ResourceKey="RequireDigit">Require Digit?</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="requiredigit" class="form-select" @bind="@_requiredigit" required>
|
|
||||||
<option value="true">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="false">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="requireupper" HelpText="Indicate If Passwords Must Contain An Upper Case Character" ResourceKey="RequireUpper">Require Uppercase?</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="requireupper" class="form-select" @bind="@_requireupper" required>
|
|
||||||
<option value="true">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="false">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="requirelower" HelpText="Indicate If Passwords Must Contain A Lower Case Character" ResourceKey="RequireLower">Require Lowercase?</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="requirelower" class="form-select" @bind="@_requirelower" required>
|
|
||||||
<option value="true">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="false">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="requirepunctuation" HelpText="Indicate if Passwords Must Contain A Non-alphanumeric Character (ie. Punctuation)" ResourceKey="RequirePunctuation">Require Punctuation?</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="requirepunctuation" class="form-select" @bind="@_requirepunctuation" required>
|
|
||||||
<option value="true">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="false">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
<Section Name="Lockout" Heading="Lockout Settings" ResourceKey="LockoutSettings">
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="maximum" HelpText="The Maximum Number Of Sign In Attempts Before A User Is Locked Out" ResourceKey="MaximumFailures">Maximum Failures:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="maximum" class="form-control" @bind="@_maximumfailures" required />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="lockoutduration" HelpText="The Number Of Minutes A User Should Be Locked Out" ResourceKey="LockoutDuration">Lockout Duration:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="lockoutduration" class="form-control" @bind="@_lockoutduration" required />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
<Section Name="ExternalLogin" Heading="External Login Settings" ResourceKey="ExternalLoginSettings">
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="providertype" HelpText="Select the external login provider type" ResourceKey="ProviderType">Provider Type:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="providertype" class="form-select" value="@_providertype" @onchange="(e => ProviderTypeChanged(e))">
|
|
||||||
<option value="" selected>@Localizer["Not Specified"]</option>
|
|
||||||
<option value="@AuthenticationProviderTypes.OpenIDConnect">@Localizer["OpenID Connect"]</option>
|
|
||||||
<option value="@AuthenticationProviderTypes.OAuth2">@Localizer["OAuth 2.0"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@if (_providertype != "")
|
|
||||||
{
|
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="providername" HelpText="The external login provider name which will be displayed on the login page" ResourceKey="ProviderName">Provider Name:</Label>
|
<Label Class="col-sm-3" For="minimumlength" HelpText="The Minimum Length For A Password" ResourceKey="RequiredLength">Minimum Length:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="providername" class="form-control" @bind="@_providername" />
|
<input id="minimumlength" class="form-control" @bind="@_minimumlength" required />
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (_providertype == AuthenticationProviderTypes.OpenIDConnect)
|
|
||||||
{
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="authority" HelpText="The Authority Url or Issuer Url associated with the OpenID Connect provider" ResourceKey="Authority">Authority:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="authority" class="form-control" @bind="@_authority" />
|
|
||||||
</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="metadataurl" HelpText="The discovery endpoint for obtaining metadata for this provider. Only specify if the OpenID Connect provider does not use the standard approach (ie. /.well-known/openid-configuration)" ResourceKey="MetadataUrl">Metadata Url:</Label>
|
<Label Class="col-sm-3" For="uniquecharacters" HelpText="The Minimum Number Of Unique Characters Which A Password Must Contain" ResourceKey="UniqueCharacters">Unique Characters:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="metadataurl" class="form-control" @bind="@_metadataurl" />
|
<input id="uniquecharacters" class="form-control" @bind="@_uniquecharacters" required />
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (_providertype == AuthenticationProviderTypes.OAuth2)
|
|
||||||
{
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="authorizationurl" HelpText="The endpoint for obtaining an Authorization Code" ResourceKey="AuthorizationUrl">Authorization Url:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="authorizationurl" class="form-control" @bind="@_authorizationurl" />
|
|
||||||
</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="tokenurl" HelpText="The endpoint for obtaining an Auth Token" ResourceKey="TokenUrl">Token Url:</Label>
|
<Label Class="col-sm-3" For="requiredigit" HelpText="Indicate If Passwords Must Contain A Digit" ResourceKey="RequireDigit">Require Digit?</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="tokenurl" class="form-control" @bind="@_tokenurl" />
|
<select id="requiredigit" class="form-select" @bind="@_requiredigit" required>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="userinfourl" HelpText="The endpoint for obtaining user information. This should be an API or Page Url which contains the users email address." ResourceKey="UserInfoUrl">User Info Url:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="userinfourl" class="form-control" @bind="@_userinfourl" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (_providertype != "")
|
|
||||||
{
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="clientid" HelpText="The Client ID from the provider" ResourceKey="ClientID">Client ID:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="clientid" class="form-control" @bind="@_clientid" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="clientsecret" HelpText="The Client Secret from the provider" ResourceKey="ClientSecret">Client Secret:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="@_clientsecrettype" id="clientsecret" class="form-control" @bind="@_clientsecret" />
|
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@ToggleClientSecret">@_toggleclientsecret</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="scopes" HelpText="A list of Scopes to request from the provider (separated by commas). If none are specified, standard Scopes will be used by default." ResourceKey="Scopes">Scopes:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="scopes" class="form-control" @bind="@_scopes" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="pkce" HelpText="Indicate if the provider supports Proof Key for Code Exchange (PKCE)" ResourceKey="PKCE">Use PKCE?</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="pkce" class="form-select" @bind="@_pkce" required>
|
|
||||||
<option value="true">@SharedLocalizer["Yes"]</option>
|
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||||
<option value="false">@SharedLocalizer["No"]</option>
|
<option value="false">@SharedLocalizer["No"]</option>
|
||||||
</select>
|
</select>
|
||||||
</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="redirecturl" HelpText="The Redirect Url (or Callback Url) which usually needs to be registered with the provider" ResourceKey="RedirectUrl">Redirect Url:</Label>
|
<Label Class="col-sm-3" For="requireupper" HelpText="Indicate If Passwords Must Contain An Upper Case Character" ResourceKey="RequireUpper">Require Uppercase?</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="redirecturl" class="form-control" @bind="@_redirecturl" readonly />
|
<select id="requireupper" class="form-select" @bind="@_requireupper" required>
|
||||||
|
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="false">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="requirelower" HelpText="Indicate If Passwords Must Contain A Lower Case Character" ResourceKey="RequireLower">Require Lowercase?</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="requirelower" class="form-select" @bind="@_requirelower" required>
|
||||||
|
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="false">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="requirepunctuation" HelpText="Indicate if Passwords Must Contain A Non-alphanumeric Character (ie. Punctuation)" ResourceKey="RequirePunctuation">Require Punctuation?</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="requirepunctuation" class="form-select" @bind="@_requirepunctuation" required>
|
||||||
|
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="false">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<Section Name="Lockout" Heading="Lockout Settings" ResourceKey="LockoutSettings">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="maximum" HelpText="The Maximum Number Of Sign In Attempts Before A User Is Locked Out" ResourceKey="MaximumFailures">Maximum Failures:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="maximum" class="form-control" @bind="@_maximumfailures" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="lockoutduration" HelpText="The Number Of Minutes A User Should Be Locked Out" ResourceKey="LockoutDuration">Lockout Duration:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="lockoutduration" class="form-control" @bind="@_lockoutduration" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<Section Name="ExternalLogin" Heading="External Login Settings" ResourceKey="ExternalLoginSettings">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="providertype" HelpText="Select the external login provider type" ResourceKey="ProviderType">Provider Type:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="providertype" class="form-select" value="@_providertype" @onchange="(e => ProviderTypeChanged(e))">
|
||||||
|
<option value="" selected>@Localizer["Not Specified"]</option>
|
||||||
|
<option value="@AuthenticationProviderTypes.OpenIDConnect">@Localizer["OpenID Connect"]</option>
|
||||||
|
<option value="@AuthenticationProviderTypes.OAuth2">@Localizer["OAuth 2.0"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if (_providertype != "")
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="providername" HelpText="The external login provider name which will be displayed on the login page" ResourceKey="ProviderName">Provider Name:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="providername" class="form-control" @bind="@_providername" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@if (_providertype == AuthenticationProviderTypes.OpenIDConnect)
|
@if (_providertype == AuthenticationProviderTypes.OpenIDConnect)
|
||||||
{
|
{
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="emailclaimtype" HelpText="The type name for the email address claim provided by the provider" ResourceKey="EmailClaimType">Email Claim Type:</Label>
|
<Label Class="col-sm-3" For="authority" HelpText="The Authority Url or Issuer Url associated with the OpenID Connect provider" ResourceKey="Authority">Authority:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="authority" class="form-control" @bind="@_authority" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="metadataurl" HelpText="The discovery endpoint for obtaining metadata for this provider. Only specify if the OpenID Connect provider does not use the standard approach (ie. /.well-known/openid-configuration)" ResourceKey="MetadataUrl">Metadata Url:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="metadataurl" class="form-control" @bind="@_metadataurl" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (_providertype == AuthenticationProviderTypes.OAuth2)
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="authorizationurl" HelpText="The endpoint for obtaining an Authorization Code" ResourceKey="AuthorizationUrl">Authorization Url:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="authorizationurl" class="form-control" @bind="@_authorizationurl" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="tokenurl" HelpText="The endpoint for obtaining an Auth Token" ResourceKey="TokenUrl">Token Url:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="tokenurl" class="form-control" @bind="@_tokenurl" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="userinfourl" HelpText="The endpoint for obtaining user information. This should be an API or Page Url which contains the users email address." ResourceKey="UserInfoUrl">User Info Url:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="userinfourl" class="form-control" @bind="@_userinfourl" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (_providertype != "")
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="clientid" HelpText="The Client ID from the provider" ResourceKey="ClientID">Client ID:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="clientid" class="form-control" @bind="@_clientid" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="clientsecret" HelpText="The Client Secret from the provider" ResourceKey="ClientSecret">Client Secret:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="@_clientsecrettype" id="clientsecret" class="form-control" @bind="@_clientsecret" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@ToggleClientSecret">@_toggleclientsecret</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="scopes" HelpText="A list of Scopes to request from the provider (separated by commas). If none are specified, standard Scopes will be used by default." ResourceKey="Scopes">Scopes:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="scopes" class="form-control" @bind="@_scopes" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="parameters" HelpText="Optionally specify any additional parameters as name/value pairs to send to the provider (separated by commas if there are multiple)." ResourceKey="Parameters">Parameters:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="parameters" class="form-control" @bind="@_parameters" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="pkce" HelpText="Indicate if the provider supports Proof Key for Code Exchange (PKCE)" ResourceKey="PKCE">Use PKCE?</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="pkce" class="form-select" @bind="@_pkce" required>
|
||||||
|
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="false">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="redirecturl" HelpText="The Redirect Url (or Callback Url) which usually needs to be registered with the provider" ResourceKey="RedirectUrl">Redirect Url:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="redirecturl" class="form-control" @bind="@_redirecturl" readonly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="identifierclaimtype" HelpText="The name of the unique user identifier claim provided by the provider" ResourceKey="IdentifierClaimType">Identifier Claim:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="identifierclaimtype" class="form-control" @bind="@_identifierclaimtype" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="emailclaimtype" HelpText="The name of the email address claim provided by the provider" ResourceKey="EmailClaimType">Email Claim:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="emailclaimtype" class="form-control" @bind="@_emailclaimtype" />
|
<input id="emailclaimtype" class="form-control" @bind="@_emailclaimtype" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="domainfilter" HelpText="Provide any email domain filter criteria (separated by commas). Domains to exclude should be prefixed with an exclamation point (!). For example 'microsoft.com,!hotmail.com' would include microsoft.com email addresses but not hotmail.com email addresses." ResourceKey="DomainFilter">Domain Filter:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="domainfilter" class="form-control" @bind="@_domainfilter" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="createusers" HelpText="Do you want new users to be created automatically? If you disable this option, users must already be registered on the site in order to sign in with their external login." ResourceKey="CreateUsers">Create New Users?</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="createusers" class="form-select" @bind="@_createusers">
|
||||||
|
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="false">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
</Section>
|
||||||
|
<Section Name="Token" Heading="Token Settings" ResourceKey="TokenSettings">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="domainfilter" HelpText="Provide any email domain filter criteria (separated by commas). Domains to exclude should be prefixed with an exclamation point (!). For example 'microsoft.com,!hotmail.com' would include microsoft.com email addresses but not hotmail.com email addresses." ResourceKey="DomainFilter">Domain Filter:</Label>
|
<Label Class="col-sm-3" For="secret" HelpText="If you want to want to provide API access, please specify a secret which will be used to encrypt your tokens. The secret should be 16 characters or more to ensure optimal security. Please note that if you change this secret, all existing tokens will become invalid and will need to be regenerated." ResourceKey="Secret">Secret:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="domainfilter" class="form-control" @bind="@_domainfilter" />
|
<div class="input-group">
|
||||||
|
<input type="@_secrettype" id="secret" class="form-control" @bind="@_secret" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@ToggleSecret">@_togglesecret</button>
|
||||||
|
</div>
|
||||||
</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="createusers" HelpText="Do you want new users to be created automatically? If you disable this option, users must already be registered on the site in order to sign in with their external login." ResourceKey="CreateUsers">Create New Users?</Label>
|
<Label Class="col-sm-3" For="issuer" HelpText="Optionally provide the issuer of the token" ResourceKey="Issuer">Issuer:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="createusers" class="form-select" @bind="@_createusers">
|
<input id="issuer" class="form-control" @bind="@_issuer" />
|
||||||
<option value="true">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="false">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
<div class="row mb-1 align-items-center">
|
||||||
</Section>
|
<Label Class="col-sm-3" For="audience" HelpText="Optionally provide the audience for the token" ResourceKey="Audience">Audience:</Label>
|
||||||
<Section Name="Token" Heading="Token Settings" ResourceKey="TokenSettings">
|
<div class="col-sm-9">
|
||||||
<div class="row mb-1 align-items-center">
|
<input id="audience" class="form-control" @bind="@_audience" />
|
||||||
<Label Class="col-sm-3" For="secret" HelpText="If you want to want to provide API access, please specify a secret which will be used to encrypt your tokens. The secret should be 16 characters or more to ensure optimal security. Please note that if you change this secret, all existing tokens will become invalid and will need to be regenerated." ResourceKey="Secret">Secret:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="@_secrettype" id="secret" class="form-control" @bind="@_secret" />
|
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@ToggleSecret">@_togglesecret</button>
|
|
||||||
</div>
|
</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="lifetime" HelpText="The number of minutes for which a token should be valid" ResourceKey="Lifetime">Lifetime:</Label>
|
||||||
<Label Class="col-sm-3" For="issuer" HelpText="Optionally provide the issuer of the token" ResourceKey="Issuer">Issuer:</Label>
|
<div class="col-sm-9">
|
||||||
<div class="col-sm-9">
|
<input id="lifetime" class="form-control" @bind="@_lifetime" />
|
||||||
<input id="issuer" class="form-control" @bind="@_issuer" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="audience" HelpText="Optionally provide the audience for the token" ResourceKey="Audience">Audience:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="audience" class="form-control" @bind="@_audience" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="lifetime" HelpText="The number of minutes for which a token should be valid" ResourceKey="Lifetime">Lifetime:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="lifetime" class="form-control" @bind="@_lifetime" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="token" HelpText="Select the Create Token button to generate a long-lived access token (valid for 1 year). Be sure to store this token in a safe location as you will not be able to access it in the future." ResourceKey="Token">Access Token:</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<div class="input-group">
|
|
||||||
<input id="token" class="form-control" @bind="@_token" />
|
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@CreateToken">@Localizer["CreateToken"]</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row mb-1 align-items-center">
|
||||||
</Section>
|
<Label Class="col-sm-3" For="token" HelpText="Select the Create Token button to generate a long-lived access token (valid for 1 year). Be sure to store this token in a safe location as you will not be able to access it in the future." ResourceKey="Token">Access Token:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="input-group">
|
||||||
|
<input id="token" class="form-control" @bind="@_token" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@CreateToken">@Localizer["CreateToken"]</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveSiteSettings">@SharedLocalizer["Save"]</button>
|
<button type="button" class="btn btn-success" @onclick="SaveSiteSettings">@SharedLocalizer["Save"]</button>
|
||||||
@ -338,14 +351,14 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<UserRole> allroles;
|
private List<UserRole> allusers;
|
||||||
private List<UserRole> userroles;
|
private List<UserRole> users;
|
||||||
private string _search;
|
private string _search = "";
|
||||||
|
|
||||||
private string _allowregistration;
|
private string _allowregistration;
|
||||||
private string _allowsitelogin;
|
private string _allowsitelogin;
|
||||||
private string _twofactor;
|
private string _twofactor;
|
||||||
private string _cookietype;
|
private string _cookiename;
|
||||||
|
|
||||||
private string _minimumlength;
|
private string _minimumlength;
|
||||||
private string _uniquecharacters;
|
private string _uniquecharacters;
|
||||||
@ -368,8 +381,10 @@ else
|
|||||||
private string _clientsecrettype = "password";
|
private string _clientsecrettype = "password";
|
||||||
private string _toggleclientsecret = string.Empty;
|
private string _toggleclientsecret = string.Empty;
|
||||||
private string _scopes;
|
private string _scopes;
|
||||||
|
private string _parameters;
|
||||||
private string _pkce;
|
private string _pkce;
|
||||||
private string _redirecturl;
|
private string _redirecturl;
|
||||||
|
private string _identifierclaimtype;
|
||||||
private string _emailclaimtype;
|
private string _emailclaimtype;
|
||||||
private string _domainfilter;
|
private string _domainfilter;
|
||||||
private string _createusers;
|
private string _createusers;
|
||||||
@ -386,71 +401,84 @@ else
|
|||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
allroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
await LoadUserSettingsAsync();
|
||||||
await LoadSettingsAsync();
|
await LoadUsersAsync(true);
|
||||||
userroles = Search(_search);
|
|
||||||
|
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
||||||
_allowregistration = PageState.Site.AllowRegistration.ToString();
|
_allowregistration = PageState.Site.AllowRegistration.ToString();
|
||||||
_allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true");
|
_allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true");
|
||||||
_twofactor = SettingService.GetSetting(settings, "LoginOptions:TwoFactor", "false");
|
|
||||||
_cookietype = SettingService.GetSetting(settings, "LoginOptions:CookieType", "domain");
|
|
||||||
|
|
||||||
_minimumlength = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredLength", "6");
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
_uniquecharacters = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", "1");
|
{
|
||||||
_requiredigit = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireDigit", "true");
|
_twofactor = SettingService.GetSetting(settings, "LoginOptions:TwoFactor", "false");
|
||||||
_requireupper = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireUppercase", "true");
|
_cookiename = SettingService.GetSetting(settings, "LoginOptions:CookieName", ".AspNetCore.Identity.Application");
|
||||||
_requirelower = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireLowercase", "true");
|
|
||||||
_requirepunctuation = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireNonAlphanumeric", "true");
|
|
||||||
|
|
||||||
_maximumfailures = SettingService.GetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", "5");
|
_minimumlength = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredLength", "6");
|
||||||
_lockoutduration = TimeSpan.Parse(SettingService.GetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", "00:05:00")).TotalMinutes.ToString();
|
_uniquecharacters = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", "1");
|
||||||
|
_requiredigit = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireDigit", "true");
|
||||||
|
_requireupper = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireUppercase", "true");
|
||||||
|
_requirelower = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireLowercase", "true");
|
||||||
|
_requirepunctuation = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireNonAlphanumeric", "true");
|
||||||
|
|
||||||
_providertype = SettingService.GetSetting(settings, "ExternalLogin:ProviderType", "");
|
_maximumfailures = SettingService.GetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", "5");
|
||||||
_providername = SettingService.GetSetting(settings, "ExternalLogin:ProviderName", "");
|
_lockoutduration = TimeSpan.Parse(SettingService.GetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", "00:05:00")).TotalMinutes.ToString();
|
||||||
_authority = SettingService.GetSetting(settings, "ExternalLogin:Authority", "");
|
|
||||||
_metadataurl = SettingService.GetSetting(settings, "ExternalLogin:MetadataUrl", "");
|
|
||||||
_authorizationurl = SettingService.GetSetting(settings, "ExternalLogin:AuthorizationUrl", "");
|
|
||||||
_tokenurl = SettingService.GetSetting(settings, "ExternalLogin:TokenUrl", "");
|
|
||||||
_userinfourl = SettingService.GetSetting(settings, "ExternalLogin:UserInfoUrl", "");
|
|
||||||
_clientid = SettingService.GetSetting(settings, "ExternalLogin:ClientId", "");
|
|
||||||
_clientsecret = SettingService.GetSetting(settings, "ExternalLogin:ClientSecret", "");
|
|
||||||
_toggleclientsecret = Localizer["Show"];
|
|
||||||
_scopes = SettingService.GetSetting(settings, "ExternalLogin:Scopes", "");
|
|
||||||
_pkce = SettingService.GetSetting(settings, "ExternalLogin:PKCE", "false");
|
|
||||||
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
|
||||||
_emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress");
|
|
||||||
_domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
|
|
||||||
_createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
|
|
||||||
|
|
||||||
_secret = SettingService.GetSetting(settings, "JwtOptions:Secret", "");
|
_providertype = SettingService.GetSetting(settings, "ExternalLogin:ProviderType", "");
|
||||||
_togglesecret = Localizer["Show"];
|
_providername = SettingService.GetSetting(settings, "ExternalLogin:ProviderName", "");
|
||||||
_issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name);
|
_authority = SettingService.GetSetting(settings, "ExternalLogin:Authority", "");
|
||||||
_audience = SettingService.GetSetting(settings, "JwtOptions:Audience", "");
|
_metadataurl = SettingService.GetSetting(settings, "ExternalLogin:MetadataUrl", "");
|
||||||
_lifetime = SettingService.GetSetting(settings, "JwtOptions:Lifetime", "20");
|
_authorizationurl = SettingService.GetSetting(settings, "ExternalLogin:AuthorizationUrl", "");
|
||||||
|
_tokenurl = SettingService.GetSetting(settings, "ExternalLogin:TokenUrl", "");
|
||||||
|
_userinfourl = SettingService.GetSetting(settings, "ExternalLogin:UserInfoUrl", "");
|
||||||
|
_clientid = SettingService.GetSetting(settings, "ExternalLogin:ClientId", "");
|
||||||
|
_clientsecret = SettingService.GetSetting(settings, "ExternalLogin:ClientSecret", "");
|
||||||
|
_toggleclientsecret = SharedLocalizer["ShowPassword"];
|
||||||
|
_scopes = SettingService.GetSetting(settings, "ExternalLogin:Scopes", "");
|
||||||
|
_parameters = SettingService.GetSetting(settings, "ExternalLogin:Parameters", "");
|
||||||
|
_pkce = SettingService.GetSetting(settings, "ExternalLogin:PKCE", "false");
|
||||||
|
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
||||||
|
_identifierclaimtype = SettingService.GetSetting(settings, "ExternalLogin:IdentifierClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
|
||||||
|
_emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress");
|
||||||
|
_domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
|
||||||
|
_createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
|
||||||
|
|
||||||
|
_secret = SettingService.GetSetting(settings, "JwtOptions:Secret", "");
|
||||||
|
_togglesecret = SharedLocalizer["ShowPassword"];
|
||||||
|
_issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name);
|
||||||
|
_audience = SettingService.GetSetting(settings, "JwtOptions:Audience", "");
|
||||||
|
_lifetime = SettingService.GetSetting(settings, "JwtOptions:Lifetime", "20"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<UserRole> Search(string search)
|
private async Task LoadUsersAsync(bool load)
|
||||||
{
|
{
|
||||||
var results = allroles.Where(item => item.Role.Name == RoleNames.Registered || (item.Role.Name == RoleNames.Host && UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)));
|
if (load)
|
||||||
|
{
|
||||||
|
allusers = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered);
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
var hosts = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Host);
|
||||||
|
allusers.AddRange(hosts);
|
||||||
|
allusers = allusers.OrderBy(u => u.User.DisplayName).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
users = allusers;
|
||||||
if (!string.IsNullOrEmpty(_search))
|
if (!string.IsNullOrEmpty(_search))
|
||||||
{
|
{
|
||||||
results = results.Where(item =>
|
users = users.Where(item =>
|
||||||
(
|
(
|
||||||
item.User.Username.Contains(search, StringComparison.OrdinalIgnoreCase) ||
|
item.User.Username.Contains(_search, StringComparison.OrdinalIgnoreCase) ||
|
||||||
item.User.Email.Contains(search, StringComparison.OrdinalIgnoreCase) ||
|
item.User.Email.Contains(_search, StringComparison.OrdinalIgnoreCase) ||
|
||||||
item.User.DisplayName.Contains(search, StringComparison.OrdinalIgnoreCase)
|
item.User.DisplayName.Contains(_search, StringComparison.OrdinalIgnoreCase)
|
||||||
)
|
)
|
||||||
);
|
).ToList();
|
||||||
}
|
}
|
||||||
return results.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnSearch()
|
private async Task OnSearch()
|
||||||
{
|
{
|
||||||
userroles = Search(_search);
|
await UpdateUserSettingsAsync();
|
||||||
await UpdateSettingsAsync();
|
await LoadUsersAsync(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteUser(UserRole UserRole)
|
private async Task DeleteUser(UserRole UserRole)
|
||||||
@ -462,8 +490,7 @@ else
|
|||||||
{
|
{
|
||||||
await UserService.DeleteUserAsync(user.UserId, PageState.Site.SiteId);
|
await UserService.DeleteUserAsync(user.UserId, PageState.Site.SiteId);
|
||||||
await logger.LogInformation("User Deleted {User}", UserRole.User);
|
await logger.LogInformation("User Deleted {User}", UserRole.User);
|
||||||
allroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
await LoadUsersAsync(true);
|
||||||
userroles = Search(_search);
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -476,13 +503,13 @@ else
|
|||||||
|
|
||||||
private string settingSearch = "AU-search";
|
private string settingSearch = "AU-search";
|
||||||
|
|
||||||
private async Task LoadSettingsAsync()
|
private async Task LoadUserSettingsAsync()
|
||||||
{
|
{
|
||||||
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
_search = SettingService.GetSetting(settings, settingSearch, "");
|
_search = SettingService.GetSetting(settings, settingSearch, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateSettingsAsync()
|
private async Task UpdateUserSettingsAsync()
|
||||||
{
|
{
|
||||||
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
SettingService.SetSetting(settings, settingSearch, _search);
|
SettingService.SetSetting(settings, settingSearch, _search);
|
||||||
@ -499,43 +526,54 @@ else
|
|||||||
|
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
||||||
settings = SettingService.SetSetting(settings, "LoginOptions:AllowSiteLogin", _allowsitelogin, false);
|
settings = SettingService.SetSetting(settings, "LoginOptions:AllowSiteLogin", _allowsitelogin, false);
|
||||||
settings = SettingService.SetSetting(settings, "LoginOptions:TwoFactor", _twofactor, false);
|
|
||||||
settings = SettingService.SetSetting(settings, "LoginOptions:CookieType", _cookietype, true);
|
|
||||||
|
|
||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredLength", _minimumlength, true);
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", _uniquecharacters, true);
|
{
|
||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireDigit", _requiredigit, true);
|
settings = SettingService.SetSetting(settings, "LoginOptions:TwoFactor", _twofactor, false);
|
||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireUppercase", _requireupper, true);
|
settings = SettingService.SetSetting(settings, "LoginOptions:CookieName", _cookiename, true);
|
||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireLowercase", _requirelower, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireNonAlphanumeric", _requirepunctuation, true);
|
|
||||||
|
|
||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", _maximumfailures, true);
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredLength", _minimumlength, true);
|
||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", TimeSpan.FromMinutes(Convert.ToInt64(_lockoutduration)).ToString(), true);
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", _uniquecharacters, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireDigit", _requiredigit, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireUppercase", _requireupper, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireLowercase", _requirelower, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Password:RequireNonAlphanumeric", _requirepunctuation, true);
|
||||||
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderType", _providertype, false);
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", _maximumfailures, true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderName", _providername, false);
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", TimeSpan.FromMinutes(Convert.ToInt64(_lockoutduration)).ToString(), true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:Authority", _authority, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:MetadataUrl", _metadataurl, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:AuthorizationUrl", _authorizationurl, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:TokenUrl", _tokenurl, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:UserInfoUrl", _userinfourl, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:ClientId", _clientid, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:ClientSecret", _clientsecret, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:Scopes", _scopes, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:PKCE", _pkce, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:EmailClaimType", _emailclaimtype, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:DomainFilter", _domainfilter, true);
|
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(_secret) && _secret.Length < 16) _secret = (_secret + "????????????????").Substring(0, 16);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderType", _providertype, false);
|
||||||
settings = SettingService.SetSetting(settings, "JwtOptions:Secret", _secret, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderName", _providername, false);
|
||||||
settings = SettingService.SetSetting(settings, "JwtOptions:Issuer", _issuer, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:Authority", _authority, true);
|
||||||
settings = SettingService.SetSetting(settings, "JwtOptions:Audience", _audience, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:MetadataUrl", _metadataurl, true);
|
||||||
settings = SettingService.SetSetting(settings, "JwtOptions:Lifetime", _lifetime, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:AuthorizationUrl", _authorizationurl, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:TokenUrl", _tokenurl, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:UserInfoUrl", _userinfourl, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:ClientId", _clientid, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:ClientSecret", _clientsecret, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:Scopes", _scopes, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:Parameters", _parameters, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:PKCE", _pkce, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:IdentifierClaimType", _identifierclaimtype, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:EmailClaimType", _emailclaimtype, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:DomainFilter", _domainfilter, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_secret) && _secret.Length < 16) _secret = (_secret + "????????????????").Substring(0, 16);
|
||||||
|
settings = SettingService.SetSetting(settings, "JwtOptions:Secret", _secret, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "JwtOptions:Issuer", _issuer, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "JwtOptions:Audience", _audience, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "JwtOptions:Lifetime", _lifetime, true);
|
||||||
|
}
|
||||||
|
|
||||||
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
||||||
await SettingService.ClearSiteSettingsCacheAsync();
|
await SettingService.ClearSiteSettingsCacheAsync();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_secret))
|
||||||
|
{
|
||||||
|
SiteState.AuthorizationToken = await UserService.GetTokenAsync();
|
||||||
|
}
|
||||||
|
|
||||||
AddModuleMessage(Localizer["Success.SaveSiteSettings"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.SaveSiteSettings"], MessageType.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -548,13 +586,20 @@ else
|
|||||||
private void ProviderTypeChanged(ChangeEventArgs e)
|
private void ProviderTypeChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_providertype = (string)e.Value;
|
_providertype = (string)e.Value;
|
||||||
if (_providertype == AuthenticationProviderTypes.OpenIDConnect)
|
if (string.IsNullOrEmpty(_providername))
|
||||||
{
|
{
|
||||||
_scopes = "openid,profile,email";
|
if (_providertype == AuthenticationProviderTypes.OpenIDConnect)
|
||||||
}
|
{
|
||||||
else
|
_scopes = "openid,profile,email";
|
||||||
{
|
_identifierclaimtype = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
|
||||||
_scopes = "";
|
_emailclaimtype = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_scopes = "";
|
||||||
|
_identifierclaimtype = "sub";
|
||||||
|
_emailclaimtype = "email";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
@ -562,7 +607,7 @@ else
|
|||||||
|
|
||||||
private async Task CreateToken()
|
private async Task CreateToken()
|
||||||
{
|
{
|
||||||
_token = await UserService.GetTokenAsync();
|
_token = await UserService.GetPersonalAccessTokenAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ToggleClientSecret()
|
private void ToggleClientSecret()
|
||||||
@ -570,12 +615,12 @@ else
|
|||||||
if (_clientsecrettype == "password")
|
if (_clientsecrettype == "password")
|
||||||
{
|
{
|
||||||
_clientsecrettype = "text";
|
_clientsecrettype = "text";
|
||||||
_toggleclientsecret = Localizer["Hide"];
|
_toggleclientsecret = SharedLocalizer["HidePassword"];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_clientsecrettype = "password";
|
_clientsecrettype = "password";
|
||||||
_toggleclientsecret = Localizer["Show"];
|
_toggleclientsecret = SharedLocalizer["ShowPassword"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,12 +629,12 @@ else
|
|||||||
if (_secrettype == "password")
|
if (_secrettype == "password")
|
||||||
{
|
{
|
||||||
_secrettype = "text";
|
_secrettype = "text";
|
||||||
_togglesecret = Localizer["Hide"];
|
_togglesecret = SharedLocalizer["HidePassword"];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_secrettype = "password";
|
_secrettype = "password";
|
||||||
_togglesecret = Localizer["Show"];
|
_togglesecret = SharedLocalizer["ShowPassword"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,15 +88,17 @@ else
|
|||||||
userid = Int32.Parse(PageState.QueryString["id"]);
|
userid = Int32.Parse(PageState.QueryString["id"]);
|
||||||
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||||
name = user.DisplayName;
|
name = user.DisplayName;
|
||||||
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
|
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
|
||||||
roles = roles.Where(item => item.Name != RoleNames.Everyone).ToList();
|
roles.RemoveAll(item => item.Name == RoleNames.Everyone || item.Name == RoleNames.Unauthenticated);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
|
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await GetUserRoles();
|
await GetUserRoles();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -110,8 +112,7 @@ else
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, userid);
|
||||||
userroles = userroles.Where(item => item.UserId == userid).ToList();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -86,279 +86,296 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _id;
|
private string _id;
|
||||||
private List<Folder> _folders;
|
private List<Folder> _folders;
|
||||||
private List<File> _files = new List<File>();
|
private List<File> _files = new List<File>();
|
||||||
private string _fileinputid = string.Empty;
|
private string _fileinputid = string.Empty;
|
||||||
private string _progressinfoid = string.Empty;
|
private string _progressinfoid = string.Empty;
|
||||||
private string _progressbarid = string.Empty;
|
private string _progressbarid = string.Empty;
|
||||||
private string _filter = "*";
|
private string _filter = "*";
|
||||||
private bool _haseditpermission = false;
|
private bool _haseditpermission = false;
|
||||||
private string _image = string.Empty;
|
private string _image = string.Empty;
|
||||||
private File _file = null;
|
private File _file = null;
|
||||||
private string _guid;
|
private string _guid;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private MessageType _messagetype;
|
private MessageType _messagetype;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
|
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int FolderId { get; set; } = -1; // optional - for setting a specific default folder by folderid
|
public int FolderId { get; set; } = -1; // optional - for setting a specific default folder by folderid
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Folder { get; set; } = ""; // optional - for setting a specific default folder by folder path
|
public string Folder { get; set; } = ""; // optional - for setting a specific default folder by folder path
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int FileId { get; set; } = -1; // optional - for selecting a specific file by default
|
public int FileId { get; set; } = -1; // optional - for selecting a specific file by default
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
|
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowFiles { get; set; } = true; // optional - for indicating whether a list of files should be displayed - default is true
|
public bool ShowFiles { get; set; } = true; // optional - for indicating whether a list of files should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowUpload { get; set; } = true; // optional - for indicating whether a Upload controls should be displayed - default is true
|
public bool ShowUpload { get; set; } = true; // optional - for indicating whether a Upload controls should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
|
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowImage { get; set; } = true; // optional - for indicating whether an image thumbnail should be displayed - default is true
|
public bool ShowImage { get; set; } = true; // optional - for indicating whether an image thumbnail should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowSuccess { get; set; } = false; // optional - for indicating whether a success message should be displayed upon successful upload - default is false
|
public bool ShowSuccess { get; set; } = false; // optional - for indicating whether a success message should be displayed upon successful upload - default is false
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
|
public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<int> OnUpload { get; set; } // optional - executes a method in the calling component when a file is uploaded
|
public EventCallback<int> OnUpload { get; set; } // optional - executes a method in the calling component when a file is uploaded
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<int> OnSelect { get; set; } // optional - executes a method in the calling component when a file is selected
|
public EventCallback<int> OnSelect { get; set; } // optional - executes a method in the calling component when a file is selected
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<int> OnDelete { get; set; } // optional - executes a method in the calling component when a file is deleted
|
public EventCallback<int> OnDelete { get; set; } // optional - executes a method in the calling component when a file is deleted
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(Id))
|
if (!string.IsNullOrEmpty(Id))
|
||||||
{
|
{
|
||||||
_id = Id;
|
_id = Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// packages folder is a framework folder for uploading installable nuget packages
|
// packages folder is a framework folder for uploading installable nuget packages
|
||||||
if (Folder == Constants.PackagesFolder)
|
if (Folder == Constants.PackagesFolder)
|
||||||
{
|
{
|
||||||
ShowFiles = false;
|
ShowFiles = false;
|
||||||
ShowFolders = false;
|
ShowFolders = false;
|
||||||
Filter = "nupkg";
|
Filter = "nupkg";
|
||||||
ShowSuccess = true;
|
ShowSuccess = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ShowFiles)
|
if (!ShowFiles)
|
||||||
{
|
{
|
||||||
ShowImage = false;
|
ShowImage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
|
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Folder) && Folder != Constants.PackagesFolder)
|
if (!string.IsNullOrEmpty(Folder) && Folder != Constants.PackagesFolder)
|
||||||
{
|
{
|
||||||
Folder folder = await FolderService.GetFolderAsync(ModuleState.SiteId, Folder);
|
Folder folder = await FolderService.GetFolderAsync(ModuleState.SiteId, Folder);
|
||||||
if (folder != null)
|
if (folder != null)
|
||||||
{
|
{
|
||||||
FolderId = folder.FolderId;
|
FolderId = folder.FolderId;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FolderId = -1;
|
FolderId = -1;
|
||||||
_message = "Folder Path " + Folder + "Does Not Exist";
|
_message = "Folder Path " + Folder + "Does Not Exist";
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileId != -1)
|
if (FileId != -1)
|
||||||
{
|
{
|
||||||
File file = await FileService.GetFileAsync(FileId);
|
File file = await FileService.GetFileAsync(FileId);
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
FolderId = file.FolderId;
|
FolderId = file.FolderId;
|
||||||
await OnSelect.InvokeAsync(FileId);
|
await OnSelect.InvokeAsync(FileId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FileId = -1; // file does not exist
|
FileId = -1; // file does not exist
|
||||||
_message = "FileId " + FileId.ToString() + "Does Not Exist";
|
_message = "FileId " + FileId.ToString() + "Does Not Exist";
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await SetImage();
|
await SetImage();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Filter))
|
if (!string.IsNullOrEmpty(Filter))
|
||||||
{
|
{
|
||||||
_filter = "." + Filter.Replace(",", ",.");
|
_filter = "." + Filter.Replace(",", ",.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
|
|
||||||
// create unique id for component
|
// create unique id for component
|
||||||
_guid = Guid.NewGuid().ToString("N");
|
_guid = Guid.NewGuid().ToString("N");
|
||||||
_fileinputid = _guid + "FileInput";
|
_fileinputid = _guid + "FileInput";
|
||||||
_progressinfoid = _guid + "ProgressInfo";
|
_progressinfoid = _guid + "ProgressInfo";
|
||||||
_progressbarid = _guid + "ProgressBar";
|
_progressbarid = _guid + "ProgressBar";
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetFiles()
|
private async Task GetFiles()
|
||||||
{
|
{
|
||||||
_haseditpermission = false;
|
_haseditpermission = false;
|
||||||
if (Folder == Constants.PackagesFolder)
|
if (Folder == Constants.PackagesFolder)
|
||||||
{
|
{
|
||||||
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
|
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
|
||||||
_files = new List<File>();
|
_files = new List<File>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
|
Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
|
||||||
if (folder != null)
|
if (folder != null)
|
||||||
{
|
{
|
||||||
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.Permissions);
|
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.Permissions);
|
||||||
_files = await FileService.GetFilesAsync(FolderId);
|
_files = await FileService.GetFilesAsync(FolderId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_haseditpermission = false;
|
_haseditpermission = false;
|
||||||
_files = new List<File>();
|
_files = new List<File>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_filter != "*")
|
if (_filter != "*")
|
||||||
{
|
{
|
||||||
List<File> filtered = new List<File>();
|
List<File> filtered = new List<File>();
|
||||||
foreach (File file in _files)
|
foreach (File file in _files)
|
||||||
{
|
{
|
||||||
if (_filter.ToUpper().IndexOf("." + file.Extension.ToUpper()) != -1)
|
if (_filter.ToUpper().IndexOf("." + file.Extension.ToUpper()) != -1)
|
||||||
{
|
{
|
||||||
filtered.Add(file);
|
filtered.Add(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_files = filtered;
|
_files = filtered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FolderChanged(ChangeEventArgs e)
|
private async Task FolderChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FolderId = int.Parse((string)e.Value);
|
FolderId = int.Parse((string)e.Value);
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
FileId = -1;
|
FileId = -1;
|
||||||
_file = null;
|
_file = null;
|
||||||
_image = string.Empty;
|
_image = string.Empty;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading Files {Error}", ex.Message);
|
await logger.LogError(ex, "Error Loading Files {Error}", ex.Message);
|
||||||
_message = Localizer["Error.File.Load"];
|
_message = Localizer["Error.File.Load"];
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FileChanged(ChangeEventArgs e)
|
private async Task FileChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
FileId = int.Parse((string)e.Value);
|
FileId = int.Parse((string)e.Value);
|
||||||
if (FileId != -1)
|
if (FileId != -1)
|
||||||
{
|
{
|
||||||
await OnSelect.InvokeAsync(FileId);
|
await OnSelect.InvokeAsync(FileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await SetImage();
|
await SetImage();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SetImage()
|
private async Task SetImage()
|
||||||
{
|
{
|
||||||
_image = string.Empty;
|
_image = string.Empty;
|
||||||
_file = null;
|
_file = null;
|
||||||
if (FileId != -1)
|
if (FileId != -1)
|
||||||
{
|
{
|
||||||
_file = await FileService.GetFileAsync(FileId);
|
_file = await FileService.GetFileAsync(FileId);
|
||||||
if (_file != null && ShowImage && _file.ImageHeight != 0 && _file.ImageWidth != 0)
|
if (_file != null && ShowImage && _file.ImageHeight != 0 && _file.ImageWidth != 0)
|
||||||
{
|
{
|
||||||
var maxwidth = 200;
|
var maxwidth = 200;
|
||||||
var maxheight = 200;
|
var maxheight = 200;
|
||||||
|
|
||||||
var ratioX = (double)maxwidth / (double)_file.ImageWidth;
|
var ratioX = (double)maxwidth / (double)_file.ImageWidth;
|
||||||
var ratioY = (double)maxheight / (double)_file.ImageHeight;
|
var ratioY = (double)maxheight / (double)_file.ImageHeight;
|
||||||
var ratio = ratioX < ratioY ? ratioX : ratioY;
|
var ratio = ratioX < ratioY ? ratioX : ratioY;
|
||||||
|
|
||||||
_image = "<img src=\"" + _file.Url + "\" alt=\"" + _file.Name +
|
_image = "<img src=\"" + _file.Url + "\" alt=\"" + _file.Name +
|
||||||
"\" width=\"" + Convert.ToInt32(_file.ImageWidth * ratio).ToString() +
|
"\" width=\"" + Convert.ToInt32(_file.ImageWidth * ratio).ToString() +
|
||||||
"\" height=\"" + Convert.ToInt32(_file.ImageHeight * ratio).ToString() + "\" />";
|
"\" height=\"" + Convert.ToInt32(_file.ImageHeight * ratio).ToString() + "\" />";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UploadFile()
|
private async Task UploadFile()
|
||||||
{
|
{
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
var upload = await interop.GetFiles(_fileinputid);
|
var upload = await interop.GetFiles(_fileinputid);
|
||||||
if (upload.Length > 0)
|
if (upload.Length > 0)
|
||||||
{
|
{
|
||||||
try
|
string restricted = "";
|
||||||
{
|
foreach (var file in upload)
|
||||||
string result;
|
{
|
||||||
if (Folder == Constants.PackagesFolder)
|
var extension = (file.LastIndexOf(".") != -1) ? file.Substring(file.LastIndexOf(".") + 1) : "";
|
||||||
{
|
if (!Constants.UploadableFiles.Split(',').Contains(extension.ToLower()))
|
||||||
result = await FileService.UploadFilesAsync(Folder, upload, _guid);
|
{
|
||||||
}
|
restricted += (restricted == "" ? "" : ",") + extension;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
result = await FileService.UploadFilesAsync(FolderId, upload, _guid);
|
if (restricted == "")
|
||||||
}
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (Folder == Constants.PackagesFolder)
|
||||||
|
{
|
||||||
|
result = await FileService.UploadFilesAsync(Folder, upload, _guid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = await FileService.UploadFilesAsync(FolderId, upload, _guid);
|
||||||
|
}
|
||||||
|
|
||||||
if (result == string.Empty)
|
if (result == string.Empty)
|
||||||
{
|
{
|
||||||
await logger.LogInformation("File Upload Succeeded {Files}", upload);
|
await logger.LogInformation("File Upload Succeeded {Files}", upload);
|
||||||
if (ShowSuccess)
|
if (ShowSuccess)
|
||||||
{
|
{
|
||||||
_message = Localizer["Success.File.Upload"];
|
_message = Localizer["Success.File.Upload"];
|
||||||
_messagetype = MessageType.Success;
|
_messagetype = MessageType.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set FileId to first file in upload collection
|
// set FileId to first file in upload collection
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
var file = _files.Where(item => item.Name == upload[0]).FirstOrDefault();
|
var file = _files.Where(item => item.Name == upload[0]).FirstOrDefault();
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
FileId = file.FileId;
|
FileId = file.FileId;
|
||||||
await SetImage();
|
await SetImage();
|
||||||
await OnUpload.InvokeAsync(FileId);
|
await OnUpload.InvokeAsync(FileId);
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await logger.LogError("File Upload Failed For {Files}", result.Replace(",", ", "));
|
await logger.LogError("File Upload Failed For {Files}", result.Replace(",", ", "));
|
||||||
|
|
||||||
_message = Localizer["Error.File.Upload"];
|
_message = Localizer["Error.File.Upload"];
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "File Upload Failed {Error}", ex.Message);
|
await logger.LogError(ex, "File Upload Failed {Error}", ex.Message);
|
||||||
|
|
||||||
_message = Localizer["Error.File.Upload"];
|
_message = Localizer["Error.File.Upload"];
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_message = string.Format(Localizer["Message.File.Restricted"], restricted);
|
||||||
|
_messagetype = MessageType.Warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = Localizer["Message.File.NotSelected"];
|
_message = Localizer["Message.File.NotSelected"];
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using Oqtane.Shared;
|
|
||||||
|
|
||||||
namespace Oqtane.Modules.Controls
|
namespace Oqtane.Modules.Controls
|
||||||
{
|
{
|
||||||
public class LocalizableComponent : ModuleControlBase
|
public class LocalizableComponent : ModuleControlBase
|
||||||
{
|
{
|
||||||
|
[Inject] public IStringLocalizerFactory LocalizerFactory { get; set; }
|
||||||
|
|
||||||
private IStringLocalizer _localizer;
|
private IStringLocalizer _localizer;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
@ -30,22 +30,15 @@ namespace Oqtane.Modules.Controls
|
|||||||
var key = $"{ResourceKey}.{propertyName}";
|
var key = $"{ResourceKey}.{propertyName}";
|
||||||
var value = Localize(key);
|
var value = Localize(key);
|
||||||
|
|
||||||
if (value == key)
|
if (value == key || value == String.Empty)
|
||||||
{
|
{
|
||||||
// Returns default property value (English version) instead of ResourceKey.PropertyName
|
// return default property value if key does not exist in resource file or value is empty
|
||||||
return propertyValue;
|
return propertyValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (value == String.Empty)
|
// return localized value
|
||||||
{
|
return value;
|
||||||
// Returns default property value (English version)
|
|
||||||
return propertyValue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,24 +46,15 @@ namespace Oqtane.Modules.Controls
|
|||||||
{
|
{
|
||||||
IsLocalizable = false;
|
IsLocalizable = false;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(ResourceType))
|
if (String.IsNullOrEmpty(ResourceType))
|
||||||
{
|
{
|
||||||
ResourceType = ModuleState?.ModuleType;
|
ResourceType = ModuleState?.ModuleType;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(ResourceKey) && !string.IsNullOrEmpty(ResourceType))
|
if (!String.IsNullOrEmpty(ResourceKey) && !String.IsNullOrEmpty(ResourceType))
|
||||||
{
|
{
|
||||||
var moduleType = Type.GetType(ResourceType);
|
_localizer = LocalizerFactory.Create(ResourceType);
|
||||||
if (moduleType != null)
|
IsLocalizable = true;
|
||||||
{
|
|
||||||
using (var scope = ServiceActivator.GetScope())
|
|
||||||
{
|
|
||||||
var localizerFactory = scope.ServiceProvider.GetService<IStringLocalizerFactory>();
|
|
||||||
_localizer = localizerFactory.Create(moduleType);
|
|
||||||
|
|
||||||
IsLocalizable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
@namespace Oqtane.Modules.Controls
|
@namespace Oqtane.Modules.Controls
|
||||||
@inherits ModuleControlBase
|
@inherits ModuleControlBase
|
||||||
|
@inject IStringLocalizerFactory LocalizerFactory
|
||||||
@typeparam TableItem
|
@typeparam TableItem
|
||||||
|
|
||||||
@if (ItemList != null)
|
@if (ItemList != null)
|
||||||
@ -48,7 +49,7 @@
|
|||||||
<a class="page-link" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="end" aria-hidden="true"></span></a>
|
<a class="page-link" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="end" aria-hidden="true"></span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="page-item disabled">
|
<li class="page-item disabled">
|
||||||
<a class="page-link" style="white-space: nowrap;">Page @_page of @_pages</a>
|
<a class="page-link" style="white-space: nowrap;">@Localizer["PageOfPages", _page, _pages]</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
}
|
}
|
||||||
@ -156,67 +157,73 @@
|
|||||||
<a class="page-link" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="end" aria-hidden="true"></span></a>
|
<a class="page-link" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="end" aria-hidden="true"></span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="page-item disabled">
|
<li class="page-item disabled">
|
||||||
<a class="page-link" style="white-space: nowrap;">Page @_page of @_pages</a>
|
<a class="page-link" style="white-space: nowrap;">@Localizer["PageOfPages", _page, _pages]</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private int _pages = 0;
|
private IStringLocalizer Localizer;
|
||||||
private int _page = 1;
|
private int _pages = 0;
|
||||||
private int _maxItems = 10;
|
private int _page = 1;
|
||||||
private int _displayPages = 5;
|
private int _maxItems = 10;
|
||||||
private int _startPage = 0;
|
private int _displayPages = 5;
|
||||||
private int _endPage = 0;
|
private int _startPage = 0;
|
||||||
private int _columns = 0;
|
private int _endPage = 0;
|
||||||
|
private int _columns = 0;
|
||||||
[Parameter]
|
|
||||||
public string Format { get; set; } // Table or Grid
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string Toolbar { get; set; } // Top, Bottom or Both
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment Header { get; set; } = null; // only applicable to Table layouts
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment<TableItem> Row { get; set; } = null; // required
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public RenderFragment<TableItem> Detail { get; set; } = null; // only applicable to Table layouts
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public IEnumerable<TableItem> Items { get; set; } // the IEnumerable data source
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string PageSize { get; set; } // number of items to display on a page
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string Columns { get; set; } // only applicable to Grid layouts - default is zero indicating use responsive behavior
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string CurrentPage { get; set; } // sets the initial page to display
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string DisplayPages { get; set; } // maximum number of page numbers to display for user selection
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string Class { get; set; } // class for the containing element - ie. <table> for Table or <div> for Grid
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string RowClass { get; set; } // class for row element - ie. <tr> for Table or <div> for Grid
|
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string ColumnClass { get; set; } // class for column element - only applicable to Grid format
|
public string Format { get; set; } // Table or Grid
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Action<int> OnPageChange { get; set; } // a method to be executed in the calling component when the page changes
|
public string Toolbar { get; set; } // Top, Bottom or Both
|
||||||
|
|
||||||
private IEnumerable<TableItem> ItemList { get; set; }
|
[Parameter]
|
||||||
|
public RenderFragment Header { get; set; } = null; // only applicable to Table layouts
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
[Parameter]
|
||||||
{
|
public RenderFragment<TableItem> Row { get; set; } = null; // required
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment<TableItem> Detail { get; set; } = null; // only applicable to Table layouts
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public IEnumerable<TableItem> Items { get; set; } // the IEnumerable data source
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string PageSize { get; set; } // number of items to display on a page
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string Columns { get; set; } // only applicable to Grid layouts - default is zero indicating use responsive behavior
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string CurrentPage { get; set; } // sets the initial page to display
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string DisplayPages { get; set; } // maximum number of page numbers to display for user selection
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string Class { get; set; } // class for the containing element - ie. <table> for Table or <div> for Grid
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string RowClass { get; set; } // class for row element - ie. <tr> for Table or <div> for Grid
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string ColumnClass { get; set; } // class for column element - only applicable to Grid format
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public Action<int> OnPageChange { get; set; } // a method to be executed in the calling component when the page changes
|
||||||
|
|
||||||
|
private IEnumerable<TableItem> ItemList { get; set; }
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
Localizer = LocalizerFactory.Create(GetType().FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnParametersSet()
|
||||||
|
{
|
||||||
if (string.IsNullOrEmpty(Format))
|
if (string.IsNullOrEmpty(Format))
|
||||||
{
|
{
|
||||||
Format = "Table";
|
Format = "Table";
|
||||||
|
@ -127,11 +127,10 @@
|
|||||||
_permissionnames = PermissionNames;
|
_permissionnames = PermissionNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
_roles = await RoleService.GetRolesAsync(ModuleState.SiteId);
|
_roles = await RoleService.GetRolesAsync(ModuleState.SiteId, true);
|
||||||
_roles.Insert(0, new Role { Name = RoleNames.Everyone });
|
if (!UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
|
||||||
{
|
{
|
||||||
_roles.Add(new Role { Name = RoleNames.Host });
|
_roles.RemoveAll(item => item.Name == RoleNames.Host);
|
||||||
}
|
}
|
||||||
|
|
||||||
_permissions = new List<PermissionString>();
|
_permissions = new List<PermissionString>();
|
||||||
@ -254,6 +253,7 @@
|
|||||||
permission = _permissions[i];
|
permission = _permissions[i];
|
||||||
List<string> ids = permission.Permissions.Split(';', StringSplitOptions.RemoveEmptyEntries).ToList();
|
List<string> ids = permission.Permissions.Split(';', StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||||
ids.Remove("!" + RoleNames.Everyone); // remove deny all users
|
ids.Remove("!" + RoleNames.Everyone); // remove deny all users
|
||||||
|
ids.Remove("!" + RoleNames.Unauthenticated); // remove deny unauthenticated
|
||||||
ids.Remove("!" + RoleNames.Registered); // remove deny registered users
|
ids.Remove("!" + RoleNames.Registered); // remove deny registered users
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
|
@ -150,10 +150,6 @@
|
|||||||
// preserve a copy of the rich text content (Quill sanitizes content so we need to retrieve it from the editor)
|
// preserve a copy of the rich text content (Quill sanitizes content so we need to retrieve it from the editor)
|
||||||
_originalrichhtml = await interop.GetHtml(_editorElement);
|
_originalrichhtml = await interop.GetHtml(_editorElement);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
await interop.LoadEditorContent(_editorElement, _richhtml);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CloseFileManager()
|
public void CloseFileManager()
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RazorLangVersion>3.0</RazorLangVersion>
|
<RazorLangVersion>3.0</RazorLangVersion>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Version>3.1.0</Version>
|
<Version>3.1.4</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.0</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.4</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<RootNamespace>Oqtane</RootNamespace>
|
<RootNamespace>Oqtane</RootNamespace>
|
||||||
|
@ -114,6 +114,7 @@ namespace Oqtane.Client
|
|||||||
|
|
||||||
private static void RegisterModuleServices(Assembly assembly, IServiceCollection services)
|
private static void RegisterModuleServices(Assembly assembly, IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
// dynamically register module scoped services
|
||||||
var implementationTypes = assembly.GetInterfaces<IService>();
|
var implementationTypes = assembly.GetInterfaces<IService>();
|
||||||
foreach (var implementationType in implementationTypes)
|
foreach (var implementationType in implementationTypes)
|
||||||
{
|
{
|
||||||
|
@ -121,7 +121,7 @@
|
|||||||
<value>Server:</value>
|
<value>Server:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Server.HelpText" xml:space="preserve">
|
<data name="Server.HelpText" xml:space="preserve">
|
||||||
<value>Enter the database server</value>
|
<value>Enter the database server name. This might include a port number as well if you are using a cloud service (ie. servername.database.windows.net,1433) </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Database.Text" xml:space="preserve">
|
<data name="Database.Text" xml:space="preserve">
|
||||||
<value>Database:</value>
|
<value>Database:</value>
|
||||||
@ -133,7 +133,7 @@
|
|||||||
<value>Integrated Security:</value>
|
<value>Integrated Security:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IntegratedSecurity.HelpText" xml:space="preserve">
|
<data name="IntegratedSecurity.HelpText" xml:space="preserve">
|
||||||
<value>Select if you want integrated security or not</value>
|
<value>Select if you are using integrated security</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Uid.Text" xml:space="preserve">
|
<data name="Uid.Text" xml:space="preserve">
|
||||||
<value>User Id:</value>
|
<value>User Id:</value>
|
||||||
@ -163,7 +163,7 @@
|
|||||||
<value>Self Signed</value>
|
<value>Self Signed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TrustServerCertificate.HelpText" xml:space="preserve">
|
<data name="TrustServerCertificate.HelpText" xml:space="preserve">
|
||||||
<value>Specify the type of certificate you are using for encryption</value>
|
<value>Specify the type of certificate you are using for encryption. Verifiable is equivalent to False. Self Signed is equivalent to True.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TrustServerCertificate.Text" xml:space="preserve">
|
<data name="TrustServerCertificate.Text" xml:space="preserve">
|
||||||
<value>Trust Server Certificate:</value>
|
<value>Trust Server Certificate:</value>
|
||||||
|
@ -135,10 +135,10 @@
|
|||||||
<data name="Message.Require.DbInfo" xml:space="preserve">
|
<data name="Message.Require.DbInfo" xml:space="preserve">
|
||||||
<value>Please Enter All Required Fields. Ensure Passwords Match And Email Address Provided Is Valid.</value>
|
<value>Please Enter All Required Fields. Ensure Passwords Match And Email Address Provided Is Valid.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Password.Invalid" xml:space="preserve">
|
<data name="Message.Password.Invalid" xml:space="preserve">
|
||||||
<value>The Password Provided Does Not Meet The Password Policy. Please Verify The Minimum Password Length And Complexity Requirements.</value>
|
<value>The Password Provided Does Not Meet The Password Policy. Please Verify The Minimum Password Length And Complexity Requirements.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Register" xml:space="preserve">
|
<data name="Register" xml:space="preserve">
|
||||||
<value>Please Register Me For Major Product Updates And Security Bulletins</value>
|
<value>Please Register Me For Major Product Updates And Security Bulletins</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Confirm.HelpText" xml:space="preserve">
|
<data name="Confirm.HelpText" xml:space="preserve">
|
||||||
@ -168,4 +168,16 @@
|
|||||||
<data name="Username.Text" xml:space="preserve">
|
<data name="Username.Text" xml:space="preserve">
|
||||||
<value>Username:</value>
|
<value>Username:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectionString.HelpText" xml:space="preserve">
|
||||||
|
<value>Enter a complete connection string including all parameters and delimiters</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConnectionString.Text" xml:space="preserve">
|
||||||
|
<value>String:</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnterConnectionParameters" xml:space="preserve">
|
||||||
|
<value>Enter Connection Parameters</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnterConnectionString" xml:space="preserve">
|
||||||
|
<value>Enter Connection String</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@ -118,6 +118,6 @@
|
|||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="Error.Module.Load" xml:space="preserve">
|
<data name="Error.Module.Load" xml:space="preserve">
|
||||||
<value>A Problem Was Encountered Loading Module {0}</value>
|
<value>A Problem Was Encountered Loading Module {0}. The Module Is Either Invalid Or Does Not Exist.</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
@ -192,4 +192,7 @@
|
|||||||
<data name="Once" xml:space="preserve">
|
<data name="Once" xml:space="preserve">
|
||||||
<value>Execute Once</value>
|
<value>Execute Once</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.NoJobs" xml:space="preserve">
|
||||||
|
<value>Please Note That After An Initial Installation You Must &lt;a href={0}&gt;Restart&lt;/a&gt; The Application In Order To Activate The Default Scheduled Jobs.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -154,13 +154,13 @@
|
|||||||
<value>No Translations Match The Criteria Provided Or Package Service Is Disabled</value>
|
<value>No Translations Match The Criteria Provided Or Package Service Is Disabled</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Download.Heading" xml:space="preserve">
|
<data name="Download.Heading" xml:space="preserve">
|
||||||
<value>Download</value>
|
<value>Translations</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LanguageUpload.HelpText" xml:space="preserve">
|
<data name="LanguageUpload.HelpText" xml:space="preserve">
|
||||||
<value>Upload one or more translations. Once they are uploaded click Install to complete the installation.</value>
|
<value>Upload one or more translation packages. Once they are uploaded click Install to complete the installation.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LanguageUpload.Text" xml:space="preserve">
|
<data name="LanguageUpload.Text" xml:space="preserve">
|
||||||
<value>Upload Language</value>
|
<value>Translation</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Manage.Heading" xml:space="preserve">
|
<data name="Manage.Heading" xml:space="preserve">
|
||||||
<value>Manage</value>
|
<value>Manage</value>
|
||||||
|
@ -144,4 +144,7 @@
|
|||||||
<data name="DeleteLanguage.Text" xml:space="preserve">
|
<data name="DeleteLanguage.Text" xml:space="preserve">
|
||||||
<value>Delete</value>
|
<value>Delete</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Translation" xml:space="preserve">
|
||||||
|
<value>Translation</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@ -123,9 +123,15 @@
|
|||||||
<data name="Success.Account.Verified" xml:space="preserve">
|
<data name="Success.Account.Verified" xml:space="preserve">
|
||||||
<value>User Account Verified Successfully. You Can Now Login With Your Username And Password Below.</value>
|
<value>User Account Verified Successfully. You Can Now Login With Your Username And Password Below.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Account.NotVerfied" xml:space="preserve">
|
<data name="Message.Account.NotVerified" xml:space="preserve">
|
||||||
<value>User Account Could Not Be Verified. Please Contact Your Administrator For Further Instructions.</value>
|
<value>User Account Could Not Be Verified. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Success.Account.Linked" xml:space="preserve">
|
||||||
|
<value>User Account Linked Successfully. You Can Now Login With Your External Login Below.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Message.Account.NotLinked" xml:space="preserve">
|
||||||
|
<value>External Login Could Not Be Linked. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
|
</data>
|
||||||
<data name="Error.Login.Fail" xml:space="preserve">
|
<data name="Error.Login.Fail" xml:space="preserve">
|
||||||
<value>Login Failed. Please Remember That Passwords Are Case Sensitive. If You Have Attempted To Sign In Multiple Times Unsuccessfully, Your Account Will Be Locked Out For A Period Of Time. Note That User Accounts Require Verification When They Are Initially Created So You May Wish To Check Your Email If You Are A New User.</value>
|
<value>Login Failed. Please Remember That Passwords Are Case Sensitive. If You Have Attempted To Sign In Multiple Times Unsuccessfully, Your Account Will Be Locked Out For A Period Of Time. Note That User Accounts Require Verification When They Are Initially Created So You May Wish To Check Your Email If You Are A New User.</value>
|
||||||
</data>
|
</data>
|
||||||
@ -183,12 +189,6 @@
|
|||||||
<data name="Username.Text" xml:space="preserve">
|
<data name="Username.Text" xml:space="preserve">
|
||||||
<value>Username:</value>
|
<value>Username:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="HidePassword" xml:space="preserve">
|
|
||||||
<value>Hide</value>
|
|
||||||
</data>
|
|
||||||
<data name="ShowPassword" xml:space="preserve">
|
|
||||||
<value>Show</value>
|
|
||||||
</data>
|
|
||||||
<data name="Use" xml:space="preserve">
|
<data name="Use" xml:space="preserve">
|
||||||
<value>Use</value>
|
<value>Use</value>
|
||||||
</data>
|
</data>
|
||||||
@ -201,4 +201,28 @@
|
|||||||
<data name="Error.ResetPassword" xml:space="preserve">
|
<data name="Error.ResetPassword" xml:space="preserve">
|
||||||
<value>Error Resetting Password</value>
|
<value>Error Resetting Password</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ExternalLoginStatus.DuplicateEmail" xml:space="preserve">
|
||||||
|
<value>Multiple User Accounts Already Exist With The Email Address Of Your External Login. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExternalLoginStatus.InvalidEmail" xml:space="preserve">
|
||||||
|
<value>The External Login Provider Did Not Provide A Valid Email Address For Your Account. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExternalLoginStatus.ProviderKeyMismatch" xml:space="preserve">
|
||||||
|
<value>An Error Occurred Verifying Your External Login. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExternalLoginStatus.UserDoesNotExist" xml:space="preserve">
|
||||||
|
<value>A User Account Matching The Email Address Of Your External Login Does Not Exist. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExternalLoginStatus.UserNotCreated" xml:space="preserve">
|
||||||
|
<value>A User Account Could Not Be Created For Your External Login. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExternalLoginStatus.VerificationRequired" xml:space="preserve">
|
||||||
|
<value>In Order To Link Your External Login With Your User Account You Must Verify Your Identity. Please Check Your Email For Further Instructions.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExternalLoginStatus.AccessDenied" xml:space="preserve">
|
||||||
|
<value>Your External Login Was Denied Access. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExternalLoginStatus.RemoteFailure" xml:space="preserve">
|
||||||
|
<value>Your External Login Failed. Please Contact Your Administrator For Further Instructions.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -195,4 +195,25 @@
|
|||||||
<data name="Information.Text" xml:space="preserve">
|
<data name="Information.Text" xml:space="preserve">
|
||||||
<value>Information</value>
|
<value>Information</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PackageName.HelpText" xml:space="preserve">
|
||||||
|
<value>The unique name of the package from which this module was installed</value>
|
||||||
|
</data>
|
||||||
|
<data name="PackageName.Text" xml:space="preserve">
|
||||||
|
<value>Package Name:</value>
|
||||||
|
</data>
|
||||||
|
<data name="Error.Translation.Download" xml:space="preserve">
|
||||||
|
<value>Error Downloading Translation</value>
|
||||||
|
</data>
|
||||||
|
<data name="Search.NoResults" xml:space="preserve">
|
||||||
|
<value>No Translations Exist For This Module Or Package Service Is Disabled</value>
|
||||||
|
</data>
|
||||||
|
<data name="Success.Translation.Download" xml:space="preserve">
|
||||||
|
<value>Translation Downloaded Successfully. Click Install To Complete Installation.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Success.Translation.Install" xml:space="preserve">
|
||||||
|
<value>Translation Installed Successfully. You Must <a href={0}>Restart</a> Your Application To Apply These Changes.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Translations.Heading" xml:space="preserve">
|
||||||
|
<value>Translations</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -150,4 +150,7 @@
|
|||||||
<data name="EditModule.Text" xml:space="preserve">
|
<data name="EditModule.Text" xml:space="preserve">
|
||||||
<value>Edit</value>
|
<value>Edit</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Modules" xml:space="preserve">
|
||||||
|
<value>Modules</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -147,4 +147,7 @@
|
|||||||
<data name="Message.Required.Title" xml:space="preserve">
|
<data name="Message.Required.Title" xml:space="preserve">
|
||||||
<value>You Must Provide A Title For The Module</value>
|
<value>You Must Provide A Title For The Module</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Error.Module.Load" xml:space="preserve">
|
||||||
|
<value>A Problem Was Encountered Loading Module {0}. The Module Is Either Invalid Or Does Not Exist.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -142,7 +142,7 @@
|
|||||||
<value>Site Settings Saved</value>
|
<value>Site Settings Saved</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Aliases.Taken" xml:space="preserve">
|
<data name="Message.Aliases.Taken" xml:space="preserve">
|
||||||
<value>The Default Alias Has Not Been Specified Or An Alias Was Specified That Has Already Been Used For Another Site</value>
|
<value>An Alias Was Specified That Has Already Been Used For Another Site</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Required.SiteName" xml:space="preserve">
|
<data name="Message.Required.SiteName" xml:space="preserve">
|
||||||
<value>You Must Provide A Site Name, Alias, And Default Theme/Container</value>
|
<value>You Must Provide A Site Name, Alias, And Default Theme/Container</value>
|
||||||
@ -166,7 +166,7 @@
|
|||||||
<value>Enter the tenant for the site</value>
|
<value>Enter the tenant for the site</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Aliases.HelpText" xml:space="preserve">
|
<data name="Aliases.HelpText" xml:space="preserve">
|
||||||
<value>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 should be separated by commas.</value>
|
<value>The aliases for the site. An alias can be a domain name (www.site.com) or a virtual folder (ie. www.site.com/folder).</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsDeleted.HelpText" xml:space="preserve">
|
<data name="IsDeleted.HelpText" xml:space="preserve">
|
||||||
<value>Is this site deleted?</value>
|
<value>Is this site deleted?</value>
|
||||||
@ -324,10 +324,13 @@
|
|||||||
<data name="Aliases.Heading" xml:space="preserve">
|
<data name="Aliases.Heading" xml:space="preserve">
|
||||||
<value>Aliases</value>
|
<value>Aliases</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Hide" xml:space="preserve">
|
<data name="AliasName" xml:space="preserve">
|
||||||
<value>Hide</value>
|
<value>Name</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Show" xml:space="preserve">
|
<data name="AliasDefault" xml:space="preserve">
|
||||||
<value>Show</value>
|
<value>Default?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Confirm.Alias.Delete" xml:space="preserve">
|
||||||
|
<value>Are You Sure You Wish To Delete {0}?</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
@ -270,4 +270,16 @@
|
|||||||
<data name="Runtime.Text" xml:space="preserve">
|
<data name="Runtime.Text" xml:space="preserve">
|
||||||
<value>Runtime: </value>
|
<value>Runtime: </value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectionString.HelpText" xml:space="preserve">
|
||||||
|
<value>Enter a complete connection string including all parameters and delimiters</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConnectionString.Text" xml:space="preserve">
|
||||||
|
<value>String:</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnterConnectionParameters" xml:space="preserve">
|
||||||
|
<value>Enter Connection Parameters</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnterConnectionString" xml:space="preserve">
|
||||||
|
<value>Enter Connection String</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -270,4 +270,10 @@
|
|||||||
<data name="WorkingSet.Text" xml:space="preserve">
|
<data name="WorkingSet.Text" xml:space="preserve">
|
||||||
<value>Memory Allocation:</value>
|
<value>Memory Allocation:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Environment.HelpText" xml:space="preserve">
|
||||||
|
<value>Environment Name</value>
|
||||||
|
</data>
|
||||||
|
<data name="Environment.Text" xml:space="preserve">
|
||||||
|
<value>Environment:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -162,4 +162,10 @@
|
|||||||
<data name="License.HelpText" xml:space="preserve">
|
<data name="License.HelpText" xml:space="preserve">
|
||||||
<value>The license of the theme</value>
|
<value>The license of the theme</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PackageName.HelpText" xml:space="preserve">
|
||||||
|
<value>The unique name of the package from which this module was installed</value>
|
||||||
|
</data>
|
||||||
|
<data name="PackageName.Text" xml:space="preserve">
|
||||||
|
<value>Package Name:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -210,4 +210,19 @@
|
|||||||
<data name="TwoFactor.Text" xml:space="preserve">
|
<data name="TwoFactor.Text" xml:space="preserve">
|
||||||
<value>Two Factor?</value>
|
<value>Two Factor?</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DeleteAllNotifications.Header" xml:space="preserve">
|
||||||
|
<value>Clear Notifications</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeleteAllNotifications.Message" xml:space="preserve">
|
||||||
|
<value>Are You Sure You Wish To Permanently Delete All Notifications?</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeleteAllNotifications.Text" xml:space="preserve">
|
||||||
|
<value>Delete ALL Notifications</value>
|
||||||
|
</data>
|
||||||
|
<data name="Notifications.Heading" xml:space="preserve">
|
||||||
|
<value>Notifications</value>
|
||||||
|
</data>
|
||||||
|
<data name="Profile.Heading" xml:space="preserve">
|
||||||
|
<value>Profile</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@ -168,4 +168,7 @@
|
|||||||
<data name="Username.Text" xml:space="preserve">
|
<data name="Username.Text" xml:space="preserve">
|
||||||
<value>Username:</value>
|
<value>Username:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Password.Placeholder" xml:space="preserve">
|
||||||
|
<value>Password</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@ -183,4 +183,19 @@
|
|||||||
<data name="Profile.Heading" xml:space="preserve">
|
<data name="Profile.Heading" xml:space="preserve">
|
||||||
<value>Profile</value>
|
<value>Profile</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Password.Placeholder" xml:space="preserve">
|
||||||
|
<value>Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="LastIPAddress.HelpText" xml:space="preserve">
|
||||||
|
<value>The IP Address of the user recorded during their last login</value>
|
||||||
|
</data>
|
||||||
|
<data name="LastIPAddress.Text" xml:space="preserve">
|
||||||
|
<value>Last IP Address: </value>
|
||||||
|
</data>
|
||||||
|
<data name="LastLogin.HelpText" xml:space="preserve">
|
||||||
|
<value>The date and time when the user last signed in</value>
|
||||||
|
</data>
|
||||||
|
<data name="LastLogin.Text" xml:space="preserve">
|
||||||
|
<value>Last Login:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@ -247,10 +247,10 @@
|
|||||||
<value>Domain Filter:</value>
|
<value>Domain Filter:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EmailClaimType.HelpText" xml:space="preserve">
|
<data name="EmailClaimType.HelpText" xml:space="preserve">
|
||||||
<value>The type name for the email address claim provided by the provider</value>
|
<value>The name of the email address claim provided by the provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EmailClaimType.Text" xml:space="preserve">
|
<data name="EmailClaimType.Text" xml:space="preserve">
|
||||||
<value>Email Claim Type:</value>
|
<value>Email Claim:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExternalLoginSettings.Heading" xml:space="preserve">
|
<data name="ExternalLoginSettings.Heading" xml:space="preserve">
|
||||||
<value>External Login Settings</value>
|
<value>External Login Settings</value>
|
||||||
@ -318,11 +318,11 @@
|
|||||||
<data name="UserSettings.Heading" xml:space="preserve">
|
<data name="UserSettings.Heading" xml:space="preserve">
|
||||||
<value>User Settings</value>
|
<value>User Settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CookieType.HelpText" xml:space="preserve">
|
<data name="CookieName.HelpText" xml:space="preserve">
|
||||||
<value>Cookies are usually managed per domain. However you can also choose to have distinct cookies for each site (this option is only applicable to micro-sites).</value>
|
<value>You can choose to use a custom authentication cookie name for each site. However please be aware that if you want to share an authentication cookie between sites on the same domain they need to use a consistent cookie name. Also be aware that changing the authentication cookie name will logout all current users.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CookieType.Text" xml:space="preserve">
|
<data name="CookieName.Text" xml:space="preserve">
|
||||||
<value>Login Cookie Type:</value>
|
<value>Cookie Name:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CreateToken" xml:space="preserve">
|
<data name="CreateToken" xml:space="preserve">
|
||||||
<value>Create Token</value>
|
<value>Create Token</value>
|
||||||
@ -355,15 +355,33 @@
|
|||||||
<value>Token Settings</value>
|
<value>Token Settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TwoFactor.HelpText" xml:space="preserve">
|
<data name="TwoFactor.HelpText" xml:space="preserve">
|
||||||
<value>Do you want to allow users to use two factor authentication? Note that the Notification Job in Scheduled Jobs needs to be enabled and your SMTP options need to be configured in Site Settings for this option to work properly.</value>
|
<value>Do you want users to use two factor authentication? Note that you should use the Disabled option until you have successfully verified that the Notification Job in Scheduled Jobs is enabled and your SMTP options in Site Settings are configured or else you will lock yourself out.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TwoFactor.Text" xml:space="preserve">
|
<data name="TwoFactor.Text" xml:space="preserve">
|
||||||
<value>Allow Two Factor?</value>
|
<value>Two Factor?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Hide" xml:space="preserve">
|
<data name="Disabled" xml:space="preserve">
|
||||||
<value>Hide</value>
|
<value>Disabled</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Show" xml:space="preserve">
|
<data name="Optional" xml:space="preserve">
|
||||||
<value>Show</value>
|
<value>Optional</value>
|
||||||
|
</data>
|
||||||
|
<data name="Required" xml:space="preserve">
|
||||||
|
<value>Required</value>
|
||||||
|
</data>
|
||||||
|
<data name="LastLoginOn" xml:space="preserve">
|
||||||
|
<value>Last Login</value>
|
||||||
|
</data>
|
||||||
|
<data name="IdentifierClaimType.HelpText" xml:space="preserve">
|
||||||
|
<value>The name of the unique user identifier claim provided by the provider</value>
|
||||||
|
</data>
|
||||||
|
<data name="IdentifierClaimType.Text" xml:space="preserve">
|
||||||
|
<value>Identifier Claim:</value>
|
||||||
|
</data>
|
||||||
|
<data name="Parameters.HelpText" xml:space="preserve">
|
||||||
|
<value>Optionally specify any additional parameters as name/value pairs to send to the provider (separated by commas if there are multiple).</value>
|
||||||
|
</data>
|
||||||
|
<data name="Parameters.Text" xml:space="preserve">
|
||||||
|
<value>Parameters:</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
@ -141,4 +141,7 @@
|
|||||||
<data name="Success.File.Upload" xml:space="preserve">
|
<data name="Success.File.Upload" xml:space="preserve">
|
||||||
<value>File Upload Succeeded</value>
|
<value>File Upload Succeeded</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.File.Restricted" xml:space="preserve">
|
||||||
|
<value>Files With Extension Of {0} Are Restricted From Upload. Please Contact Your Administrator For More Information.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
123
Oqtane.Client/Resources/Modules/Controls/Pager.resx
Normal file
123
Oqtane.Client/Resources/Modules/Controls/Pager.resx
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="PageOfPages" xml:space="preserve">
|
||||||
|
<value>Page {0} of {1}</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
@ -274,7 +274,7 @@
|
|||||||
<value>Full Name:</value>
|
<value>Full Name:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LocalVersion" xml:space="preserve">
|
<data name="LocalVersion" xml:space="preserve">
|
||||||
<value>Local Version</value>
|
<value>Installed Version</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Search.Source" xml:space="preserve">
|
<data name="Search.Source" xml:space="preserve">
|
||||||
<value>source</value>
|
<value>source</value>
|
||||||
@ -321,4 +321,19 @@
|
|||||||
<data name="Settings" xml:space="preserve">
|
<data name="Settings" xml:space="preserve">
|
||||||
<value>Settings</value>
|
<value>Settings</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="HidePassword" xml:space="preserve">
|
||||||
|
<value>Hide</value>
|
||||||
|
</data>
|
||||||
|
<data name="ShowPassword" xml:space="preserve">
|
||||||
|
<value>Show</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageOfPages" xml:space="preserve">
|
||||||
|
<value>Page {0} of {1}</value>
|
||||||
|
</data>
|
||||||
|
<data name="Url Mappings" xml:space="preserve">
|
||||||
|
<value>Url Mappings</value>
|
||||||
|
</data>
|
||||||
|
<data name="Visitor Management" xml:space="preserve">
|
||||||
|
<value>Visitor Management</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -138,6 +138,12 @@
|
|||||||
<data name="Register.Text" xml:space="preserve">
|
<data name="Register.Text" xml:space="preserve">
|
||||||
<value>Show Register?</value>
|
<value>Show Register?</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Scope.HelpText" xml:space="preserve">
|
||||||
|
<value>Specify if the settings are applicable to this page or the entire site.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Scope.Text" xml:space="preserve">
|
||||||
|
<value>Setting Scope:</value>
|
||||||
|
</data>
|
||||||
<data name="Site" xml:space="preserve">
|
<data name="Site" xml:space="preserve">
|
||||||
<value>Site</value>
|
<value>Site</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -12,18 +12,12 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class AliasService : ServiceBase, IAliasService
|
public class AliasService : ServiceBase, IAliasService
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor - should only be used by Dependency Injection
|
/// Constructor - should only be used by Dependency Injection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AliasService(HttpClient http, SiteState siteState) : base(http)
|
public AliasService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ApiUrl => CreateApiUrl("Alias", _siteState.Alias);
|
private string ApiUrl => CreateApiUrl("Alias");
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<List<Alias>> GetAliasesAsync()
|
public async Task<List<Alias>> GetAliasesAsync()
|
||||||
|
@ -11,15 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class DatabaseService : ServiceBase, IDatabaseService
|
public class DatabaseService : ServiceBase, IDatabaseService
|
||||||
{
|
{
|
||||||
|
public DatabaseService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("Database");
|
||||||
|
|
||||||
public DatabaseService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Database", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Database>> GetDatabasesAsync()
|
public async Task<List<Database>> GetDatabasesAsync()
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -17,13 +18,13 @@ namespace Oqtane.Services
|
|||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
private readonly IJSRuntime _jsRuntime;
|
private readonly IJSRuntime _jsRuntime;
|
||||||
|
|
||||||
public FileService(HttpClient http, SiteState siteState, IJSRuntime jsRuntime) : base(http)
|
public FileService(HttpClient http, SiteState siteState, IJSRuntime jsRuntime) : base(http, siteState)
|
||||||
{
|
{
|
||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
_jsRuntime = jsRuntime;
|
_jsRuntime = jsRuntime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("File", _siteState.Alias);
|
private string Apiurl => CreateApiUrl("File");
|
||||||
|
|
||||||
public async Task<List<File>> GetFilesAsync(int folderId)
|
public async Task<List<File>> GetFilesAsync(int folderId)
|
||||||
{
|
{
|
||||||
@ -32,7 +33,8 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
public async Task<List<File>> GetFilesAsync(string folder)
|
public async Task<List<File>> GetFilesAsync(string folder)
|
||||||
{
|
{
|
||||||
return await GetJsonAsync<List<File>>($"{Apiurl}?folder={folder}");
|
List<File> files = await GetJsonAsync<List<File>>($"{Apiurl}?folder={folder}");
|
||||||
|
return files.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<File>> GetFilesAsync(int siteId, string folderPath)
|
public async Task<List<File>> GetFilesAsync(int siteId, string folderPath)
|
||||||
@ -44,7 +46,8 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
var path = WebUtility.UrlEncode(folderPath);
|
var path = WebUtility.UrlEncode(folderPath);
|
||||||
|
|
||||||
return await GetJsonAsync<List<File>>($"{Apiurl}/{siteId}/{path}");
|
List<File> files = await GetJsonAsync<List<File>>($"{Apiurl}/{siteId}/{path}");
|
||||||
|
return files?.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<File> GetFileAsync(int fileId)
|
public async Task<File> GetFileAsync(int fileId)
|
||||||
@ -82,7 +85,7 @@ namespace Oqtane.Services
|
|||||||
string result = "";
|
string result = "";
|
||||||
|
|
||||||
var interop = new Interop(_jsRuntime);
|
var interop = new Interop(_jsRuntime);
|
||||||
await interop.UploadFiles($"{Apiurl}/upload", folder, id);
|
await interop.UploadFiles($"{Apiurl}/upload", folder, id, _siteState.AntiForgeryToken);
|
||||||
|
|
||||||
// uploading files is asynchronous so we need to wait for the upload to complete
|
// uploading files is asynchronous so we need to wait for the upload to complete
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
@ -14,14 +14,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class FolderService : ServiceBase, IFolderService
|
public class FolderService : ServiceBase, IFolderService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public FolderService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public FolderService(HttpClient http, SiteState siteState) : base(http)
|
private string ApiUrl => CreateApiUrl("Folder");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ApiUrl => CreateApiUrl("Folder", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Folder>> GetFoldersAsync(int siteId)
|
public async Task<List<Folder>> GetFoldersAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ namespace Oqtane.Services
|
|||||||
private readonly NavigationManager _navigationManager;
|
private readonly NavigationManager _navigationManager;
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
public InstallationService(HttpClient http, NavigationManager navigationManager, SiteState siteState) : base(http)
|
public InstallationService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http, siteState)
|
||||||
{
|
{
|
||||||
_navigationManager = navigationManager;
|
_navigationManager = navigationManager;
|
||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
|
@ -17,6 +17,14 @@ namespace Oqtane.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<Language>> GetLanguagesAsync(int siteId);
|
Task<List<Language>> GetLanguagesAsync(int siteId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of all available languages for the given <see cref="Site" /> and package
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="packageName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<Language>> GetLanguagesAsync(int siteId, string packageName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the given language
|
/// Returns the given language
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -16,6 +16,31 @@ namespace Oqtane.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<UserRole>> GetUserRolesAsync(int siteId);
|
Task<List<UserRole>> GetUserRolesAsync(int siteId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all <see cref="UserRole"/>s on a <see cref="Site"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId">ID-reference to a <see cref="Site"/></param>
|
||||||
|
/// <param name="userId">ID-reference to a <see cref="User"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<UserRole>> GetUserRolesAsync(int siteId, int userId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all <see cref="UserRole"/>s on a <see cref="Site"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId">ID-reference to a <see cref="Site"/></param>
|
||||||
|
/// <param name="roleName">Name reference a <see cref="Role"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<UserRole>> GetUserRolesAsync(int siteId, string roleName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all <see cref="UserRole"/>s on a <see cref="Site"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId">ID-reference to a <see cref="Site"/></param>
|
||||||
|
/// <param name="userId">ID-reference to a <see cref="User"/></param>
|
||||||
|
/// <param name="roleName">Name reference a <see cref="Role"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<UserRole>> GetUserRolesAsync(int siteId, int userId, string roleName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get one specific <see cref="UserRole"/>
|
/// Get one specific <see cref="UserRole"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -54,10 +54,8 @@ namespace Oqtane.Services
|
|||||||
/// Note that this will probably not be a real User, but a user object where the `Username` and `Password` have been filled.
|
/// Note that this will probably not be a real User, but a user object where the `Username` and `Password` have been filled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user">A <see cref="User"/> object which should have at least the <see cref="User.Username"/> and <see cref="User.Password"/> set.</param>
|
/// <param name="user">A <see cref="User"/> object which should have at least the <see cref="User.Username"/> and <see cref="User.Password"/> set.</param>
|
||||||
/// <param name="setCookie">Determines if the login should be stored in the cookie.</param>
|
|
||||||
/// <param name="isPersistent">Determines if the login should be persisted in the cookie for a long time.</param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<User> LoginUserAsync(User user, bool setCookie, bool isPersistent);
|
Task<User> LoginUserAsync(User user);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logout a <see cref="User"/>
|
/// Logout a <see cref="User"/>
|
||||||
@ -109,5 +107,24 @@ namespace Oqtane.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<string> GetTokenAsync();
|
Task<string> GetTokenAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get personal access token for current user (administrators only)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<string> GetPersonalAccessTokenAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Link an external login with a local user account
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The <see cref="User"/> we're verifying</param>
|
||||||
|
/// <param name="token">A Hash value in the URL which verifies this user got the e-mail (containing this token)</param>
|
||||||
|
/// <param name="type">External Login provider type</param>
|
||||||
|
/// <param name="key">External Login provider key</param>
|
||||||
|
/// <param name="name">External Login provider display name</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<User> LinkUserAsync(User user, string token, string type, string key, string name);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,14 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class JobLogService : ServiceBase, IJobLogService
|
public class JobLogService : ServiceBase, IJobLogService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public JobLogService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public JobLogService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("JobLog");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("JobLog", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<JobLog>> GetJobLogsAsync()
|
public async Task<List<JobLog>> GetJobLogsAsync()
|
||||||
{
|
{
|
||||||
|
@ -11,14 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class JobService : ServiceBase, IJobService
|
public class JobService : ServiceBase, IJobService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public JobService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public JobService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("Job");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Job", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Job>> GetJobsAsync()
|
public async Task<List<Job>> GetJobsAsync()
|
||||||
{
|
{
|
||||||
|
@ -11,30 +11,33 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class LanguageService : ServiceBase, ILanguageService
|
public class LanguageService : ServiceBase, ILanguageService
|
||||||
{
|
{
|
||||||
|
public LanguageService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("Language");
|
||||||
|
|
||||||
public LanguageService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Language", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Language>> GetLanguagesAsync(int siteId)
|
public async Task<List<Language>> GetLanguagesAsync(int siteId)
|
||||||
{
|
{
|
||||||
var languages = await GetJsonAsync<List<Language>>($"{Apiurl}?siteid={siteId}");
|
return await GetLanguagesAsync(siteId, "");
|
||||||
|
}
|
||||||
|
|
||||||
return languages?.OrderBy(l => l.Name).ToList() ?? Enumerable.Empty<Language>().ToList();
|
public async Task<List<Language>> GetLanguagesAsync(int siteId, string packageName)
|
||||||
|
{
|
||||||
|
return await GetJsonAsync<List<Language>>($"{Apiurl}?siteid={siteId}&packagename={packageName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Language> GetLanguageAsync(int languageId)
|
public async Task<Language> GetLanguageAsync(int languageId)
|
||||||
=> await GetJsonAsync<Language>($"{Apiurl}/{languageId}");
|
{
|
||||||
|
return await GetJsonAsync<Language>($"{Apiurl}/{languageId}");
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Language> AddLanguageAsync(Language language)
|
public async Task<Language> AddLanguageAsync(Language language)
|
||||||
=> await PostJsonAsync<Language>(Apiurl, language);
|
{
|
||||||
|
return await PostJsonAsync<Language>(Apiurl, language);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task DeleteLanguageAsync(int languageId)
|
public async Task DeleteLanguageAsync(int languageId)
|
||||||
=> await DeleteAsync($"{Apiurl}/{languageId}");
|
{
|
||||||
|
await DeleteAsync($"{Apiurl}/{languageId}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class LocalizationService : ServiceBase, ILocalizationService
|
public class LocalizationService : ServiceBase, ILocalizationService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public LocalizationService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public LocalizationService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("Localization");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Localization", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<IEnumerable<Culture>> GetCulturesAsync() => await GetJsonAsync<IEnumerable<Culture>>(Apiurl);
|
public async Task<IEnumerable<Culture>> GetCulturesAsync() => await GetJsonAsync<IEnumerable<Culture>>(Apiurl);
|
||||||
}
|
}
|
||||||
|
@ -14,18 +14,16 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class LogService : ServiceBase, ILogService
|
public class LogService : ServiceBase, ILogService
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
private readonly NavigationManager _navigationManager;
|
private readonly NavigationManager _navigationManager;
|
||||||
|
|
||||||
public LogService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
|
public LogService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http, siteState)
|
||||||
{
|
{
|
||||||
|
|
||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
_navigationManager = navigationManager;
|
_navigationManager = navigationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Log", _siteState.Alias);
|
private string Apiurl => CreateApiUrl("Log");
|
||||||
|
|
||||||
public async Task<List<Log>> GetLogsAsync(int siteId, string level, string function, int rows)
|
public async Task<List<Log>> GetLogsAsync(int siteId, string level, string function, int rows)
|
||||||
{
|
{
|
||||||
|
@ -14,16 +14,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class ModuleDefinitionService : ServiceBase, IModuleDefinitionService
|
public class ModuleDefinitionService : ServiceBase, IModuleDefinitionService
|
||||||
{
|
{
|
||||||
private readonly HttpClient _http;
|
public ModuleDefinitionService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
private readonly SiteState _siteState;
|
|
||||||
|
|
||||||
public ModuleDefinitionService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("ModuleDefinition");
|
||||||
{
|
|
||||||
_http = http;
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("ModuleDefinition", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync(int siteId)
|
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -11,15 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class ModuleService : ServiceBase, IModuleService
|
public class ModuleService : ServiceBase, IModuleService
|
||||||
{
|
{
|
||||||
|
public ModuleService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("Module");
|
||||||
|
|
||||||
public ModuleService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Module", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Module>> GetModulesAsync(int siteId)
|
public async Task<List<Module>> GetModulesAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -11,14 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class NotificationService : ServiceBase, INotificationService
|
public class NotificationService : ServiceBase, INotificationService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public NotificationService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public NotificationService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("Notification");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Notification", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId)
|
public async Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId)
|
||||||
{
|
{
|
||||||
|
@ -12,13 +12,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class PackageService : ServiceBase, IPackageService
|
public class PackageService : ServiceBase, IPackageService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public PackageService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public PackageService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("Package");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
private string Apiurl => CreateApiUrl("Package", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Package>> GetPackagesAsync(string type)
|
public async Task<List<Package>> GetPackagesAsync(string type)
|
||||||
{
|
{
|
||||||
|
@ -9,15 +9,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class PageModuleService : ServiceBase, IPageModuleService
|
public class PageModuleService : ServiceBase, IPageModuleService
|
||||||
{
|
{
|
||||||
|
public PageModuleService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("PageModule");
|
||||||
|
|
||||||
public PageModuleService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("PageModule", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<PageModule> GetPageModuleAsync(int pageModuleId)
|
public async Task<PageModule> GetPageModuleAsync(int pageModuleId)
|
||||||
{
|
{
|
||||||
|
@ -13,16 +13,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class PageService : ServiceBase, IPageService
|
public class PageService : ServiceBase, IPageService
|
||||||
{
|
{
|
||||||
|
public PageService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("Page");
|
||||||
|
|
||||||
public PageService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Page", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Page>> GetPagesAsync(int siteId)
|
public async Task<List<Page>> GetPagesAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -11,15 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class ProfileService : ServiceBase, IProfileService
|
public class ProfileService : ServiceBase, IProfileService
|
||||||
{
|
{
|
||||||
|
public ProfileService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("Profile");
|
||||||
|
|
||||||
public ProfileService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Profile", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Profile>> GetProfilesAsync(int siteId)
|
public async Task<List<Profile>> GetProfilesAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -21,11 +21,16 @@ namespace Oqtane.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
private HttpClient GetHttpClient()
|
private HttpClient GetHttpClient()
|
||||||
|
{
|
||||||
|
return GetHttpClient(_siteState?.AuthorizationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpClient GetHttpClient(string AuthorizationToken)
|
||||||
{
|
{
|
||||||
var httpClient = _httpClientFactory.CreateClient("Remote");
|
var httpClient = _httpClientFactory.CreateClient("Remote");
|
||||||
if (!httpClient.DefaultRequestHeaders.Contains(HeaderNames.Authorization) && _siteState != null && !string.IsNullOrEmpty(_siteState.AuthorizationToken))
|
if (!httpClient.DefaultRequestHeaders.Contains(HeaderNames.Authorization) && !string.IsNullOrEmpty(AuthorizationToken))
|
||||||
{
|
{
|
||||||
httpClient.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + _siteState.AuthorizationToken);
|
httpClient.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + AuthorizationToken);
|
||||||
}
|
}
|
||||||
return httpClient;
|
return httpClient;
|
||||||
}
|
}
|
||||||
|
@ -11,16 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class RoleService : ServiceBase, IRoleService
|
public class RoleService : ServiceBase, IRoleService
|
||||||
{
|
{
|
||||||
|
public RoleService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("Role");
|
||||||
|
|
||||||
public RoleService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Role", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Role>> GetRolesAsync(int siteId)
|
public async Task<List<Role>> GetRolesAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -12,15 +12,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SettingService : ServiceBase, ISettingService
|
public class SettingService : ServiceBase, ISettingService
|
||||||
{
|
{
|
||||||
|
public SettingService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("Setting");
|
||||||
|
|
||||||
public SettingService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Setting", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<Dictionary<string, string>> GetTenantSettingsAsync()
|
public async Task<Dictionary<string, string>> GetTenantSettingsAsync()
|
||||||
{
|
{
|
||||||
|
@ -12,15 +12,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SiteService : ServiceBase, ISiteService
|
public class SiteService : ServiceBase, ISiteService
|
||||||
{
|
{
|
||||||
|
public SiteService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("Site");
|
||||||
|
|
||||||
public SiteService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Site", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Site>> GetSitesAsync()
|
public async Task<List<Site>> GetSitesAsync()
|
||||||
{
|
{
|
||||||
|
@ -11,13 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SiteTemplateService : ServiceBase, ISiteTemplateService
|
public class SiteTemplateService : ServiceBase, ISiteTemplateService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public SiteTemplateService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public SiteTemplateService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("SiteTemplate");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
private string Apiurl => CreateApiUrl("SiteTemplate", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<SiteTemplate>> GetSiteTemplatesAsync()
|
public async Task<List<SiteTemplate>> GetSiteTemplatesAsync()
|
||||||
{
|
{
|
||||||
|
@ -9,14 +9,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SqlService : ServiceBase, ISqlService
|
public class SqlService : ServiceBase, ISqlService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public SqlService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public SqlService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("Sql");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Sql", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
|
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
|
||||||
{
|
{
|
||||||
|
@ -11,18 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SyncService : ServiceBase, ISyncService
|
public class SyncService : ServiceBase, ISyncService
|
||||||
{
|
{
|
||||||
|
public SyncService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string ApiUrl => CreateApiUrl("Sync");
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor - should only be used by Dependency Injection
|
|
||||||
/// </summary>
|
|
||||||
public SyncService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ApiUrl => CreateApiUrl("Sync", _siteState.Alias);
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<Sync> GetSyncAsync(DateTime lastSyncDate)
|
public async Task<Sync> GetSyncAsync(DateTime lastSyncDate)
|
||||||
|
@ -9,14 +9,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SystemService : ServiceBase, ISystemService
|
public class SystemService : ServiceBase, ISystemService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public SystemService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public SystemService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("System");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("System", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<Dictionary<string, object>> GetSystemInfoAsync()
|
public async Task<Dictionary<string, object>> GetSystemInfoAsync()
|
||||||
{
|
{
|
||||||
|
@ -11,14 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class TenantService : ServiceBase, ITenantService
|
public class TenantService : ServiceBase, ITenantService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public TenantService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public TenantService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("Tenant");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Tenant", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Tenant>> GetTenantsAsync()
|
public async Task<List<Tenant>> GetTenantsAsync()
|
||||||
{
|
{
|
||||||
|
@ -11,14 +11,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class ThemeService : ServiceBase, IThemeService
|
public class ThemeService : ServiceBase, IThemeService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public ThemeService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public ThemeService(HttpClient http, SiteState siteState) : base(http)
|
private string ApiUrl => CreateApiUrl("Theme");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ApiUrl => CreateApiUrl("Theme", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Theme>> GetThemesAsync()
|
public async Task<List<Theme>> GetThemesAsync()
|
||||||
{
|
{
|
||||||
|
@ -12,16 +12,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class UrlMappingService : ServiceBase, IUrlMappingService
|
public class UrlMappingService : ServiceBase, IUrlMappingService
|
||||||
{
|
{
|
||||||
|
public UrlMappingService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("UrlMapping");
|
||||||
|
|
||||||
public UrlMappingService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("UrlMapping", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<UrlMapping>> GetUrlMappingsAsync(int siteId, bool isMapped)
|
public async Task<List<UrlMapping>> GetUrlMappingsAsync(int siteId, bool isMapped)
|
||||||
{
|
{
|
||||||
|
@ -10,19 +10,37 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class UserRoleService : ServiceBase, IUserRoleService
|
public class UserRoleService : ServiceBase, IUserRoleService
|
||||||
{
|
{
|
||||||
|
public UserRoleService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("UserRole");
|
||||||
|
|
||||||
public UserRoleService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("UserRole", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<UserRole>> GetUserRolesAsync(int siteId)
|
public async Task<List<UserRole>> GetUserRolesAsync(int siteId)
|
||||||
{
|
{
|
||||||
return await GetJsonAsync<List<UserRole>>($"{Apiurl}?siteid={siteId}");
|
return await GetUserRolesAsync(siteId, -1, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<UserRole>> GetUserRolesAsync(int siteId, int userId)
|
||||||
|
{
|
||||||
|
return await GetUserRolesAsync(siteId, userId, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<UserRole>> GetUserRolesAsync(int siteId, string roleName)
|
||||||
|
{
|
||||||
|
return await GetUserRolesAsync(siteId, -1, roleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<UserRole>> GetUserRolesAsync(int siteId, int userId, string roleName)
|
||||||
|
{
|
||||||
|
var url = $"{Apiurl}?siteid={siteId}";
|
||||||
|
if (userId != -1)
|
||||||
|
{
|
||||||
|
url += $"&userid={userId}";
|
||||||
|
}
|
||||||
|
if (roleName != "")
|
||||||
|
{
|
||||||
|
url += $"&rolename={roleName}";
|
||||||
|
}
|
||||||
|
return await GetJsonAsync<List<UserRole>>(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserRole> GetUserRoleAsync(int userRoleId)
|
public async Task<UserRole> GetUserRoleAsync(int userRoleId)
|
||||||
|
@ -10,14 +10,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class UserService : ServiceBase, IUserService
|
public class UserService : ServiceBase, IUserService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public UserService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
public UserService(HttpClient http, SiteState siteState) : base(http)
|
private string Apiurl => CreateApiUrl("User");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("User", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<User> GetUserAsync(int userId, int siteId)
|
public async Task<User> GetUserAsync(int userId, int siteId)
|
||||||
{
|
{
|
||||||
@ -44,9 +39,9 @@ namespace Oqtane.Services
|
|||||||
await DeleteAsync($"{Apiurl}/{userId}?siteid={siteId}");
|
await DeleteAsync($"{Apiurl}/{userId}?siteid={siteId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<User> LoginUserAsync(User user, bool setCookie, bool isPersistent)
|
public async Task<User> LoginUserAsync(User user)
|
||||||
{
|
{
|
||||||
return await PostJsonAsync<User>($"{Apiurl}/login?setcookie={setCookie}&persistent={isPersistent}", user);
|
return await PostJsonAsync<User>($"{Apiurl}/login", user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LogoutUserAsync(User user)
|
public async Task LogoutUserAsync(User user)
|
||||||
@ -84,5 +79,16 @@ namespace Oqtane.Services
|
|||||||
{
|
{
|
||||||
return await GetStringAsync($"{Apiurl}/token");
|
return await GetStringAsync($"{Apiurl}/token");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetPersonalAccessTokenAsync()
|
||||||
|
{
|
||||||
|
return await GetStringAsync($"{Apiurl}/personalaccesstoken");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<User> LinkUserAsync(User user, string token, string type, string key, string name)
|
||||||
|
{
|
||||||
|
return await PostJsonAsync<User>($"{Apiurl}/link?token={token}&type={type}&key={key}&name={name}", user);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,16 +12,9 @@ namespace Oqtane.Services
|
|||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class VisitorService : ServiceBase, IVisitorService
|
public class VisitorService : ServiceBase, IVisitorService
|
||||||
{
|
{
|
||||||
|
public VisitorService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private string Apiurl => CreateApiUrl("Visitor");
|
||||||
|
|
||||||
public VisitorService(HttpClient http, SiteState siteState) : base(http)
|
|
||||||
{
|
|
||||||
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Visitor", _siteState.Alias);
|
|
||||||
|
|
||||||
public async Task<List<Visitor>> GetVisitorsAsync(int siteId, DateTime fromDate)
|
public async Task<List<Visitor>> GetVisitorsAsync(int siteId, DateTime fromDate)
|
||||||
{
|
{
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<LanguageSwitcher />
|
<LanguageSwitcher />
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) || (PageState.Page.IsPersonalizable && PageState.User != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Registered)))
|
@if (_showEditMode || (PageState.Page.IsPersonalizable && PageState.User != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Registered)))
|
||||||
{
|
{
|
||||||
if (PageState.EditMode)
|
if (PageState.EditMode)
|
||||||
{
|
{
|
||||||
@ -218,6 +218,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code{
|
@code{
|
||||||
|
private bool _showEditMode = false;
|
||||||
private bool _deleteConfirmation = false;
|
private bool _deleteConfirmation = false;
|
||||||
private List<string> _categories = new List<string>();
|
private List<string> _categories = new List<string>();
|
||||||
private List<ModuleDefinition> _allModuleDefinitions;
|
private List<ModuleDefinition> _allModuleDefinitions;
|
||||||
@ -285,8 +286,10 @@
|
|||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
|
_showEditMode = false;
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
|
_showEditMode = true;
|
||||||
_pages?.Clear();
|
_pages?.Clear();
|
||||||
|
|
||||||
foreach (Page p in PageState.Pages)
|
foreach (Page p in PageState.Pages)
|
||||||
@ -305,6 +308,17 @@
|
|||||||
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList();
|
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList();
|
||||||
_categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList();
|
_categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId))
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, module.Permissions))
|
||||||
|
{
|
||||||
|
_showEditMode = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CategoryChanged(ChangeEventArgs e)
|
private void CategoryChanged(ChangeEventArgs e)
|
||||||
@ -405,21 +419,21 @@
|
|||||||
Message = $"<div class=\"alert alert-success mt-2 text-center\" role=\"alert\">{Localizer["Success.Page.ModuleAdd"]}</div>";
|
Message = $"<div class=\"alert alert-success mt-2 text-center\" role=\"alert\">{Localizer["Success.Page.ModuleAdd"]}</div>";
|
||||||
Title = "";
|
Title = "";
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Message = $"<div class=\"alert alert-warning mt-2 text-center\" role=\"alert\">{Localizer["Message.Require.ModuleSelect"]}</div>";
|
Message = $"<div class=\"alert alert-warning mt-2 text-center\" role=\"alert\">{Localizer["Message.Require.ModuleSelect"]}</div>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Message = $"<div class=\"alert alert-error mt-2 text-center\" role=\"alert\">{Localizer["Error.Authorize.No"]}</div>";
|
Message = $"<div class=\"alert alert-error mt-2 text-center\" role=\"alert\">{Localizer["Error.Authorize.No"]}</div>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ToggleEditMode(bool EditMode)
|
private async Task ToggleEditMode(bool EditMode)
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
if (_showEditMode)
|
||||||
{
|
{
|
||||||
if (EditMode)
|
if (EditMode)
|
||||||
{
|
{
|
||||||
@ -445,7 +459,6 @@
|
|||||||
|
|
||||||
private void Navigate(string location)
|
private void Navigate(string location)
|
||||||
{
|
{
|
||||||
//HideControlPanel();
|
|
||||||
Module module;
|
Module module;
|
||||||
switch (location)
|
switch (location)
|
||||||
{
|
{
|
||||||
|
@ -24,13 +24,9 @@
|
|||||||
@code{
|
@code{
|
||||||
private IEnumerable<Culture> _supportedCultures;
|
private IEnumerable<Culture> _supportedCultures;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
var languages = PageState.Languages;
|
||||||
var defaultCulture = CultureInfo.GetCultureInfo(Constants.DefaultCulture);
|
|
||||||
|
|
||||||
languages.Add(new Language { Code = defaultCulture.Name, Name = defaultCulture.DisplayName });
|
|
||||||
|
|
||||||
_supportedCultures = languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
|
_supportedCultures = languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
using Oqtane.Providers;
|
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
@ -33,28 +31,19 @@ namespace Oqtane.Themes.Controls
|
|||||||
|
|
||||||
protected async Task LogoutUser()
|
protected async Task LogoutUser()
|
||||||
{
|
{
|
||||||
await UserService.LogoutUserAsync(PageState.User);
|
|
||||||
await LoggingService.Log(PageState.Alias, PageState.Page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "Logout", LogFunction.Security, LogLevel.Information, null, "User Logout For Username {Username}", PageState.User.Username);
|
await LoggingService.Log(PageState.Alias, PageState.Page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "Logout", LogFunction.Security, LogLevel.Information, null, "User Logout For Username {Username}", PageState.User.Username);
|
||||||
PageState.User = null;
|
|
||||||
|
|
||||||
|
// check if anonymous user can access page
|
||||||
var url = PageState.Alias.Path + "/" + PageState.Page.Path;
|
var url = PageState.Alias.Path + "/" + PageState.Page.Path;
|
||||||
if (!UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, PageState.Page.Permissions))
|
if (!UserSecurity.IsAuthorized(null, PermissionNames.View, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
url = PageState.Alias.Path;
|
url = PageState.Alias.Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PageState.Runtime == Shared.Runtime.Server)
|
// post to the Logout page to complete the logout process
|
||||||
{
|
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, returnurl = url };
|
||||||
// server-side Blazor needs to redirect to the Logout page
|
var interop = new Interop(jsRuntime);
|
||||||
NavigationManager.NavigateTo(Utilities.TenantUrl(PageState.Alias, "/pages/logout/") + "?returnurl=" + WebUtility.UrlEncode(url), true);
|
await interop.SubmitForm(Utilities.TenantUrl(PageState.Alias, "/pages/logout/"), fields);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// client-side Blazor
|
|
||||||
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
|
|
||||||
authstateprovider.NotifyAuthenticationChanged();
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl(url, true));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user