Merge branch 'oqtane:dev' into dev
This commit is contained in:
commit
efe803f147
|
@ -1,11 +1,10 @@
|
|||
@namespace Oqtane.Installer
|
||||
@using Oqtane.Interfaces
|
||||
@using Oqtane.Installer.Controls
|
||||
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IInstallationService InstallationService
|
||||
@inject ISiteService SiteService
|
||||
@inject IUserService UserService
|
||||
@inject IDatabaseService DatabaseService
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject IStringLocalizer<Installer> Localizer
|
||||
|
||||
|
@ -22,25 +21,28 @@
|
|||
<h2>@Localizer["Database Configuration"]</h2><br />
|
||||
<table class="form-group" cellpadding="4" cellspacing="4" style="margin: auto;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label" style="font-weight: bold">@Localizer["Database Type:"]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||
@foreach (var database in _databases)
|
||||
{
|
||||
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@{
|
||||
if (_databaseConfigType != null)
|
||||
{
|
||||
@DatabaseConfigComponent;
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label" style="font-weight: bold">@Localizer["Database Type:"]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||
@if (_databases != null)
|
||||
{
|
||||
foreach (var database in _databases)
|
||||
{
|
||||
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@{
|
||||
if (_databaseConfigType != null)
|
||||
{
|
||||
@DatabaseConfigComponent;
|
||||
}
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -95,7 +97,7 @@
|
|||
</div>
|
||||
|
||||
@code {
|
||||
private IList<Database> _databases;
|
||||
private List<Database> _databases;
|
||||
private string _databaseName = "LocalDB";
|
||||
private Type _databaseConfigType;
|
||||
private object _databaseConfig;
|
||||
|
@ -108,44 +110,9 @@
|
|||
private string _message = string.Empty;
|
||||
private string _loadingDisplay = "display: none;";
|
||||
|
||||
protected override void OnInitialized()
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
_databases = new List<Database>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Name = "LocalDB",
|
||||
FriendlyName = "Local Database",
|
||||
Type = "Oqtane.Installer.Controls.LocalDBConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "SqlServer",
|
||||
FriendlyName = "SQL Server",
|
||||
Type = "Oqtane.Installer.Controls.SqlServerConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "Sqlite",
|
||||
FriendlyName = "Sqlite",
|
||||
Type = "Oqtane.Installer.Controls.SqliteConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "MySQL",
|
||||
FriendlyName = "MySQL",
|
||||
Type = "Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "PostgreSQL",
|
||||
FriendlyName = "PostgreSQL",
|
||||
Type = "Oqtane.Installer.Controls.PostgreSQLConfig, Oqtane.Client"
|
||||
}
|
||||
};
|
||||
|
||||
_databases = await DatabaseService.GetDatabasesAsync();
|
||||
LoadDatabaseConfigComponent();
|
||||
}
|
||||
|
||||
|
@ -157,7 +124,7 @@
|
|||
|
||||
LoadDatabaseConfigComponent();
|
||||
}
|
||||
catch (Exception exception)
|
||||
catch
|
||||
{
|
||||
_message = Localizer["Error loading Database Configuration Control"];
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
@inject NavigationManager NavigationManager
|
||||
@inject ILocalizationService LocalizationService
|
||||
@inject ILanguageService LanguageService
|
||||
@inject IPackageService PackageService
|
||||
@inject IStringLocalizer<Add> Localizer
|
||||
|
||||
@if (_supportedCultures == null)
|
||||
|
@ -13,57 +14,114 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
@if (_supportedCultures?.Count() > 1)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="name" HelpText="Name Of The Langauage" ResourceKey="Name">Name:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="_code" class="form-control" @bind="@_code">
|
||||
@foreach (var culture in _supportedCultures)
|
||||
{
|
||||
<option value="@culture.Name">@culture.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="default" HelpText="Indicates Whether Or Not This Language Is The Default For The Site" ResourceKey="IsDefault">Default?</Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="default" class="form-control" @bind="@_isDefault">
|
||||
<option value="True">@Localizer["Yes"]</option>
|
||||
<option value="False">@Localizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveLanguage">@Localizer["Save"]</button>
|
||||
}
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||
<TabStrip>
|
||||
<TabPanel Name="Manage" ResourceKey="Manage">
|
||||
@if (_availableCultures.Count() == 0)
|
||||
{
|
||||
<ModuleMessage Type="MessageType.Info" Message="@_message"></ModuleMessage>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="name" HelpText="Name Of The Language" ResourceKey="Name">Name:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="_code" class="form-control" @bind="@_code">
|
||||
@foreach (var culture in _availableCultures)
|
||||
{
|
||||
<option value="@culture.Name">@culture.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="default" HelpText="Indicates Whether Or Not This Language Is The Default For The Site" ResourceKey="IsDefault">Default?</Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="default" class="form-control" @bind="@_isDefault">
|
||||
<option value="True">@Localizer["Yes"]</option>
|
||||
<option value="False">@Localizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveLanguage">@Localizer["Save"]</button>
|
||||
}
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||
</TabPanel>
|
||||
<TabPanel Name="Download" ResourceKey="Download" Security="SecurityAccessLevel.Host">
|
||||
@if (_packages != null && _packages.Count > 0)
|
||||
{
|
||||
<ModuleMessage Type="MessageType.Info" Message="Download one or more language packages from the list below. Once you are ready click Install to complete the installation."></ModuleMessage>
|
||||
<Pager Items="@_packages">
|
||||
<Header>
|
||||
<th>@Localizer["Name"]</th>
|
||||
<th>@Localizer["Version"]</th>
|
||||
<th style="width: 1px"></th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.Version</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadLanguage(context.PackageId, context.Version))>@Localizer["Download"]</button>
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
<button type="button" class="btn btn-success" @onclick="InstallLanguages">@Localizer["Install"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ModuleMessage Type="MessageType.Info" Message="No Language Packages Are Available To Download"></ModuleMessage>
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Upload" ResourceKey="Upload" Security="SecurityAccessLevel.Host">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label HelpText="Upload one or more language packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Language: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" UploadMultiple="true" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="InstallLanguages">@Localizer["Install"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
}
|
||||
|
||||
@code {
|
||||
private string _code = string.Empty;
|
||||
private string _isDefault = "False";
|
||||
private string _message;
|
||||
private IEnumerable<Culture> _supportedCultures;
|
||||
private IEnumerable<Culture> _availableCultures;
|
||||
private List<Package> _packages;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||
|
||||
private IEnumerable<Culture> _supportedCultures;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
||||
var languagesCodes = languages.Select(l => l.Code).ToList();
|
||||
|
||||
_supportedCultures = await LocalizationService.GetCulturesAsync();
|
||||
if (_supportedCultures.Count() <= 1)
|
||||
_availableCultures = _supportedCultures
|
||||
.Where(c => !c.Name.Equals(Constants.DefaultCulture) && !languagesCodes.Contains(c.Name));
|
||||
_packages = await PackageService.GetPackagesAsync("language");
|
||||
|
||||
if (_supportedCultures.Count() == 1)
|
||||
{
|
||||
AddModuleMessage(Localizer["The Only Supported Culture That Has Been Defined Is English"], MessageType.Warning);
|
||||
_message = Localizer["The Only Installed Language Is English"];
|
||||
}
|
||||
else
|
||||
else if (_availableCultures.Count() == 0)
|
||||
{
|
||||
_supportedCultures = _supportedCultures.Where(c => !c.Name.Equals(Constants.DefaultCulture));
|
||||
_message = Localizer["All The Installed Languages Have Been Added."];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +155,35 @@ else
|
|||
}
|
||||
}
|
||||
|
||||
private async Task InstallLanguages()
|
||||
{
|
||||
try
|
||||
{
|
||||
await PackageService.InstallPackagesAsync();
|
||||
AddModuleMessage(Localizer["Language Packages Installed Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Installing Language Package");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadLanguage(string packageid, string version)
|
||||
{
|
||||
try
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(packageid, version, "Packages");
|
||||
await logger.LogInformation("Language Paclage {Name} {Version} Downloaded Successfully", packageid, version);
|
||||
AddModuleMessage(Localizer["Language Package Downloaded Successfully. Click Install To Complete Installation."], MessageType.Success);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Language Package {Name} {Version}", packageid, version);
|
||||
AddModuleMessage(Localizer["Error Downloading Language Package"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SetCultureAsync(string culture)
|
||||
{
|
||||
if (culture != CultureInfo.CurrentUICulture.Name)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
@namespace Oqtane.Modules.Admin.Languages
|
||||
@inherits ModuleBase
|
||||
@inject ILanguageService LanguageService
|
||||
@inject ILocalizationService LocalizationService
|
||||
@inject IPackageService PackageService
|
||||
@inject IStringLocalizer<Index> Localizer
|
||||
|
||||
@if (_languages == null)
|
||||
|
@ -17,24 +19,43 @@ else
|
|||
<th>@Localizer["Name"]</th>
|
||||
<th>@Localizer["Code"]</th>
|
||||
<th>@Localizer["Default?"]</th>
|
||||
<th style="width: 1px;"> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionDialog Header="Delete Langauge" Message="@Localizer["Are You Sure You Wish To Delete The {0} Language?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteLanguage(context))" Disabled="@(context.IsDefault)" ResourceKey="DeleteLanguage" /></td>
|
||||
<td><ActionDialog Header="Delete Langauge" Message="@Localizer["Are You Sure You Wish To Delete The {0} Language From This Site?", 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.Code</td>
|
||||
<td><TriStateCheckBox Value="@(context.IsDefault)" Disabled="true"></TriStateCheckBox></td>
|
||||
<td>
|
||||
@if (UpgradeAvailable(context.Code))
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadLanguage(context.Code))>@Localizer["Upgrade"]</button>
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<Language> _languages;
|
||||
private List<Package> _packages;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
||||
|
||||
var cultures = await LocalizationService.GetCulturesAsync();
|
||||
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))
|
||||
{
|
||||
_packages = await PackageService.GetPackagesAsync("language");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteLanguage(Language language)
|
||||
|
@ -53,4 +74,38 @@ else
|
|||
AddModuleMessage(Localizer["Error Deleting Language"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private bool UpgradeAvailable(string code)
|
||||
{
|
||||
var upgradeavailable = false;
|
||||
if (_packages != null)
|
||||
{
|
||||
var package = _packages.Where(item => item.PackageId == (Constants.PackageId + ".Client." + code)).FirstOrDefault();
|
||||
if (package != null)
|
||||
{
|
||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) > 0);
|
||||
}
|
||||
|
||||
}
|
||||
return upgradeavailable;
|
||||
}
|
||||
|
||||
private async Task DownloadLanguage(string code)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(Constants.PackageId + ".Client." + code, Constants.Version, "Packages");
|
||||
await logger.LogInformation("Language Package Downloaded {Code} {Version}", code, Constants.Version);
|
||||
await PackageService.InstallPackagesAsync();
|
||||
AddModuleMessage(Localizer["Language Package Installed Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Language Package {Code} {Version} {Error}", code, Constants.Version, ex.Message);
|
||||
AddModuleMessage(Localizer["Error Downloading Language Package"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,9 @@
|
|||
// complete the login on the server so that the cookies are set correctly on SignalR
|
||||
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
|
||||
var fields = new { __RequestVerificationToken = antiforgerytoken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
|
||||
await interop.SubmitForm($"/{PageState.Alias.AliasId}/pages/login/", fields);
|
||||
string url = "/pages/login/";
|
||||
if (!string.IsNullOrEmpty(PageState.Alias.Path)) url = "/" + PageState.Alias.Path + url;
|
||||
await interop.SubmitForm(url, fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -167,46 +167,53 @@
|
|||
|
||||
private async Task SaveModule()
|
||||
{
|
||||
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)
|
||||
if (!string.IsNullOrEmpty(_title))
|
||||
{
|
||||
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.Permissions = _permissionGrid.GetPermissions();
|
||||
await ModuleService.UpdateModuleAsync(module);
|
||||
|
||||
if (_moduleSettingsType != null)
|
||||
{
|
||||
if (_moduleSettings is ISettingsControl moduleSettingsControl)
|
||||
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)
|
||||
{
|
||||
// module settings updated using explicit interface
|
||||
await moduleSettingsControl.UpdateSettings();
|
||||
pagemodule.ContainerType = string.Empty;
|
||||
}
|
||||
else
|
||||
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
|
||||
{
|
||||
// legacy support - module settings updated by convention ( ie. by calling a public method named "UpdateSettings" in settings component )
|
||||
_moduleSettings?.GetType().GetMethod("UpdateSettings")?.Invoke(_moduleSettings, null);
|
||||
pagemodule.ContainerType = string.Empty;
|
||||
}
|
||||
}
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
|
||||
if (_containerSettingsType != null && _containerSettings is ISettingsControl containerSettingsControl)
|
||||
var module = ModuleState;
|
||||
module.AllPages = bool.Parse(_allPages);
|
||||
module.Permissions = _permissionGrid.GetPermissions();
|
||||
await ModuleService.UpdateModuleAsync(module);
|
||||
|
||||
if (_moduleSettingsType != null)
|
||||
{
|
||||
if (_moduleSettings is ISettingsControl moduleSettingsControl)
|
||||
{
|
||||
// module settings updated using explicit interface
|
||||
await moduleSettingsControl.UpdateSettings();
|
||||
}
|
||||
else
|
||||
{
|
||||
// legacy support - module settings updated by convention ( ie. by calling a public method named "UpdateSettings" in settings component )
|
||||
_moduleSettings?.GetType().GetMethod("UpdateSettings")?.Invoke(_moduleSettings, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (_containerSettingsType != null && _containerSettings is ISettingsControl containerSettingsControl)
|
||||
{
|
||||
await containerSettingsControl.UpdateSettings();
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
await containerSettingsControl.UpdateSettings();
|
||||
AddModuleMessage(Localizer["You Must Provide A Title For The Module"], MessageType.Warning);
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="alias" HelpText="Enter the alias for the server" ResourceKey="Aliases">Aliases: </Label>
|
||||
<Label 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>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
|
||||
|
@ -60,67 +60,67 @@
|
|||
</tr>
|
||||
</table>
|
||||
<Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultTheme" class="form-control" value="@_themetype" @onchange="(e => ThemeChanged(e))">
|
||||
<option value="-"><@Localizer["Select Theme"]></option>
|
||||
@foreach (var theme in _themes)
|
||||
{
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultAdminContainer" class="form-control" @bind="@_admincontainertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
<option value=""><@Localizer["Default Admin Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultTheme" class="form-control" value="@_themetype" @onchange="(e => ThemeChanged(e))">
|
||||
<option value="-"><@Localizer["Select Theme"]></option>
|
||||
@foreach (var theme in _themes)
|
||||
{
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultAdminContainer" class="form-control" @bind="@_admincontainertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
<option value=""><@Localizer["Default Admin Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Section>
|
||||
<Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
|
||||
<table class="table table-borderless">
|
||||
|
@ -218,6 +218,7 @@
|
|||
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@Localizer["Save"]</button>
|
||||
<ActionDialog Header="Delete Site" Message="@Localizer["Are You Sure You Wish To Delete This Site?"]" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteSite())" ResourceKey="DeleteSite" />
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||
|
@ -276,7 +277,7 @@
|
|||
_tenant = _tenantList.Find(item => item.TenantId == site.TenantId).Name;
|
||||
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
||||
{
|
||||
_urls += alias.Name + "\n";
|
||||
_urls += alias.Name + ",";
|
||||
}
|
||||
if (site.LogoFileId != null)
|
||||
{
|
||||
|
@ -424,7 +425,6 @@
|
|||
|
||||
site = await SiteService.UpdateSiteAsync(site);
|
||||
|
||||
_urls = _urls.Replace("\n", ",");
|
||||
var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
||||
{
|
||||
|
@ -476,6 +476,36 @@
|
|||
}
|
||||
}
|
||||
|
||||
private async Task DeleteSite()
|
||||
{
|
||||
try
|
||||
{
|
||||
var sites = await SiteService.GetSitesAsync();
|
||||
if (sites.Count > 1)
|
||||
{
|
||||
await SiteService.DeleteSiteAsync(PageState.Site.SiteId);
|
||||
await logger.LogInformation("Site Deleted {SiteId}", PageState.Site.SiteId);
|
||||
|
||||
var aliases = await AliasService.GetAliasesAsync();
|
||||
foreach (Alias a in aliases.Where(item => item.SiteId == PageState.Site.SiteId))
|
||||
{
|
||||
await AliasService.DeleteAliasAsync(a.AliasId);
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl("admin/sites"));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["You Are Not Authorized To Delete The Site"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Deleting Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error Deleting Site"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SendEmail()
|
||||
{
|
||||
if (_smtphost != "" && _smtpport != "" && _smtpsender != "")
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
@inject ISiteTemplateService SiteTemplateService
|
||||
@inject IUserService UserService
|
||||
@inject IInstallationService InstallationService
|
||||
@inject IDatabaseService DatabaseService
|
||||
@inject IStringLocalizer<Add> Localizer
|
||||
@inject IEnumerable<IOqtaneDatabase> Databases
|
||||
|
||||
|
@ -18,151 +19,151 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="name" HelpText="Enter the name of the site" ResourceKey="Name">Site Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="alias" HelpText="Enter the alias for the server" ResourceKey="Aliases">Aliases: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultTheme" HelpText="Select the default theme for the website" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||
<option value="-"><@Localizer["Select Theme"]></option>
|
||||
@foreach (var theme in _themes)
|
||||
{
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="adminContainer" HelpText="Select the admin container for the site" ResourceKey="AdminContainer">Admin Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="adminContainer" class="form-control" @bind="@_admincontainertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
<option value=""><@Localizer["Default Admin Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="siteTemplate" HelpText="Select the site template" ResourceKey="SiteTemplate">Site Template: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="siteTemplate" class="form-control" @bind="@_sitetemplatetype">
|
||||
<option value="-"><@Localizer["Select Site Template"]></option>
|
||||
@foreach (SiteTemplate siteTemplate in _siteTemplates)
|
||||
{
|
||||
<option value="@siteTemplate.TypeName">@siteTemplate.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="tenant" HelpText="Select the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="tenant" class="form-control" @onchange="(e => TenantChanged(e))">
|
||||
<option value="-"><@Localizer["Select Tenant"]></option>
|
||||
<option value="+"><@Localizer["Create New Tenant"]></option>
|
||||
@foreach (Tenant tenant in _tenants)
|
||||
{
|
||||
<option value="@tenant.TenantId">@tenant.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@if (_tenantid == "+")
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<hr class="app-rule" />
|
||||
<td>
|
||||
<Label For="name" HelpText="Enter the name of the site" ResourceKey="Name">Site Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="name" HelpText="Enter the name for the tenant" ResourceKey="TenantName">Tenant Name: </Label>
|
||||
<Label 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>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_tenantName" />
|
||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label>
|
||||
<Label For="defaultTheme" HelpText="Select the default theme for the website" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="databaseType" class="custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||
@foreach (var database in _databases)
|
||||
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||
<option value="-"><@Localizer["Select Theme"]></option>
|
||||
@foreach (var theme in _themes)
|
||||
{
|
||||
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
if (_databaseConfigType != null)
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="adminContainer" HelpText="Select the admin container for the site" ResourceKey="AdminContainer">Admin Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="adminContainer" class="form-control" @bind="@_admincontainertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
<option value=""><@Localizer["Default Admin Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="siteTemplate" HelpText="Select the site template" ResourceKey="SiteTemplate">Site Template: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="siteTemplate" class="form-control" @bind="@_sitetemplatetype">
|
||||
<option value="-"><@Localizer["Select Site Template"]></option>
|
||||
@foreach (SiteTemplate siteTemplate in _siteTemplates)
|
||||
{
|
||||
<option value="@siteTemplate.TypeName">@siteTemplate.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="tenant" HelpText="Select the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="tenant" class="form-control" @onchange="(e => TenantChanged(e))">
|
||||
<option value="-"><@Localizer["Select Tenant"]></option>
|
||||
<option value="+"><@Localizer["Create New Tenant"]></option>
|
||||
@foreach (Tenant tenant in _tenants)
|
||||
{
|
||||
<option value="@tenant.TenantId">@tenant.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@if (_tenantid == "+")
|
||||
{
|
||||
@DatabaseConfigComponent;
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<hr class="app-rule" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="name" HelpText="Enter the name for the tenant" ResourceKey="TenantName">Tenant Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_tenantName" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="databaseType" class="custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||
@foreach (var database in _databases)
|
||||
{
|
||||
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
if (_databaseConfigType != null)
|
||||
{
|
||||
@DatabaseConfigComponent;
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="hostUsername" HelpText="Enter the username of the host for this site" ResourceKey="HostUsername">Host Username:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="hostUsername" class="form-control" @bind="@_hostUserName" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="hostPassword" HelpText="Enter the password for the host of this site" ResourceKey="HostPassword">Host Password:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="hostUsername" HelpText="Enter the username of the host for this site" ResourceKey="HostUsername">Host Username:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="hostUsername" class="form-control" @bind="@_hostUserName" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="hostPassword" HelpText="Enter the password for the host of this site" ResourceKey="HostPassword">Host Password:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@Localizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||
}
|
||||
|
||||
@code {
|
||||
private IList<Database> _databases;
|
||||
private List<Database> _databases;
|
||||
private string _databaseName = "LocalDB";
|
||||
private Type _databaseConfigType;
|
||||
private object _databaseConfig;
|
||||
|
@ -177,7 +178,7 @@ else
|
|||
private string _tenantid = "-";
|
||||
|
||||
private string _tenantName = string.Empty;
|
||||
|
||||
|
||||
private string _hostUserName = UserNames.Host;
|
||||
private string _hostpassword = string.Empty;
|
||||
|
||||
|
@ -197,44 +198,10 @@ else
|
|||
_themeList = await ThemeService.GetThemesAsync();
|
||||
_themes = ThemeService.GetThemeControls(_themeList);
|
||||
_siteTemplates = await SiteTemplateService.GetSiteTemplatesAsync();
|
||||
|
||||
_databases = new List<Database>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Name = "LocalDB",
|
||||
FriendlyName = "Local Database",
|
||||
Type = "Oqtane.Installer.Controls.LocalDBConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "SqlServer",
|
||||
FriendlyName = "SQL Server",
|
||||
Type = "Oqtane.Installer.Controls.SqlServerConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "Sqlite",
|
||||
FriendlyName = "Sqlite",
|
||||
Type = "Oqtane.Installer.Controls.SqliteConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "MySQL",
|
||||
FriendlyName = "MySQL",
|
||||
Type = "Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "PostgreSQL",
|
||||
FriendlyName = "PostgreSQL",
|
||||
Type = "Oqtane.Installer.Controls.PostGreSQLConfig, Oqtane.Client"
|
||||
}
|
||||
};
|
||||
|
||||
_databases = await DatabaseService.GetDatabasesAsync();
|
||||
LoadDatabaseConfigComponent();
|
||||
}
|
||||
|
||||
|
||||
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
|
@ -243,7 +210,7 @@ else
|
|||
|
||||
LoadDatabaseConfigComponent();
|
||||
}
|
||||
catch (Exception exception)
|
||||
catch
|
||||
{
|
||||
AddModuleMessage(Localizer["Error loading Database Configuration Control"], MessageType.Error);
|
||||
}
|
||||
|
@ -365,15 +332,15 @@ else
|
|||
if (tenant != null)
|
||||
{
|
||||
config.TenantName = tenant.Name;
|
||||
config.ConnectionString= tenant.DBConnectionString;
|
||||
config.ConnectionString = tenant.DBConnectionString;
|
||||
config.IsNewTenant = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(config.TenantName))
|
||||
if (!string.IsNullOrEmpty(config.TenantName))
|
||||
{
|
||||
config.SiteName = _name;
|
||||
config.Aliases = _urls.Replace("\n", ",");
|
||||
config.Aliases = _urls;
|
||||
config.DefaultTheme = _themetype;
|
||||
config.DefaultContainer = _containertype;
|
||||
config.DefaultAdminContainer = _admincontainertype;
|
||||
|
|
|
@ -1,283 +0,0 @@
|
|||
@namespace Oqtane.Modules.Admin.Sites
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISiteService SiteService
|
||||
@inject ITenantService TenantService
|
||||
@inject IAliasService AliasService
|
||||
@inject IThemeService ThemeService
|
||||
@inject IStringLocalizer<Edit> Localizer
|
||||
|
||||
@if (_initialized)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="name" HelpText="Enter the name of the site" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="alias" HelpText="Enter the alias for the server" ResourceKey="Aliases">Aliases: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultTheme" HelpText="Select the default theme for the website" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultTheme" class="form-control" value="@_themetype" @onchange="(e => ThemeChanged(e))">
|
||||
<option value="-"><@Localizer["Select Theme"]></option>
|
||||
@foreach (var theme in _themes)
|
||||
{
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultIdea" class="form-control" @bind="@_containertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultAdminContainer" class="form-control" @bind="@_admincontainertype">
|
||||
<option value="-"><@Localizer["Select Container"]></option>
|
||||
<option value=""><@Localizer["Default Admin Container"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="isDeleted" HelpText="Has this site been deleted?" ResourceKey="IsDeleted">Is Deleted? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="isDeleted" class="form-control" @bind="@_isdeleted">
|
||||
<option value="True">@Localizer["Yes"]</option>
|
||||
<option value="False">@Localizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="tenant" HelpText="The tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="connectionstring" HelpText="The database connection string" ResourceKey="ConnectionString">Connection String: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="connectionstring" class="form-control" @bind="@_connectionstring" rows="3" readonly></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@Localizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||
}
|
||||
|
||||
@code {
|
||||
private bool _initialized = false;
|
||||
private List<Theme> _themeList;
|
||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||
private Alias _alias;
|
||||
private string _name = string.Empty;
|
||||
private List<Alias> _aliasList;
|
||||
private string _urls = string.Empty;
|
||||
private string _themetype;
|
||||
private string _containertype = "-";
|
||||
private string _admincontainertype = "-";
|
||||
private string _createdby;
|
||||
private DateTime _createdon;
|
||||
private string _modifiedby;
|
||||
private DateTime _modifiedon;
|
||||
private string _deletedby;
|
||||
private DateTime? _deletedon;
|
||||
private string _isdeleted;
|
||||
private string _tenant = string.Empty;
|
||||
private string _connectionstring = string.Empty;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
_themeList = await ThemeService.GetThemesAsync();
|
||||
_aliasList = await AliasService.GetAliasesAsync();
|
||||
|
||||
_alias = _aliasList.Find(item => item.AliasId == Int32.Parse(PageState.QueryString["id"]));
|
||||
SiteService.SetAlias(_alias);
|
||||
var site = await SiteService.GetSiteAsync(_alias.SiteId);
|
||||
if (site != null)
|
||||
{
|
||||
_name = site.Name;
|
||||
|
||||
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
||||
{
|
||||
_urls += alias.Name + "\n";
|
||||
}
|
||||
|
||||
_themes = ThemeService.GetThemeControls(_themeList);
|
||||
_themetype = site.DefaultThemeType;
|
||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||
_containertype = site.DefaultContainerType;
|
||||
_admincontainertype = site.AdminContainerType;
|
||||
_createdby = site.CreatedBy;
|
||||
_createdon = site.CreatedOn;
|
||||
_modifiedby = site.ModifiedBy;
|
||||
_modifiedon = site.ModifiedOn;
|
||||
_deletedby = site.DeletedBy;
|
||||
_deletedon = site.DeletedOn;
|
||||
_isdeleted = site.IsDeleted.ToString();
|
||||
|
||||
List<Tenant> tenants = await TenantService.GetTenantsAsync();
|
||||
Tenant tenant = tenants.Find(item => item.TenantId == site.TenantId);
|
||||
if (tenant != null)
|
||||
{
|
||||
_tenant = tenant.Name;
|
||||
_connectionstring = tenant.DBConnectionString;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await Log(_alias, LogLevel.Error, string.Empty, ex, "Error Loading Site {SiteId} {Error}", _alias.SiteId, ex.Message);
|
||||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ThemeChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_themetype = (string)e.Value;
|
||||
if (_themetype != "-")
|
||||
{
|
||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||
}
|
||||
else
|
||||
{
|
||||
_containers = new List<ThemeControl>();
|
||||
}
|
||||
_containertype = "-";
|
||||
_admincontainertype = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", _themetype, ex.Message);
|
||||
AddModuleMessage(Localizer["Error Loading Pane Layouts For Theme"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveSite()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-")
|
||||
{
|
||||
var unique = true;
|
||||
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (_aliasList.Exists(item => item.Name == name && item.SiteId != _alias.SiteId && item.TenantId != _alias.TenantId))
|
||||
{
|
||||
unique = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (unique)
|
||||
{
|
||||
SiteService.SetAlias(_alias);
|
||||
var site = await SiteService.GetSiteAsync(_alias.SiteId);
|
||||
if (site != null)
|
||||
{
|
||||
site.Name = _name;
|
||||
site.LogoFileId = null;
|
||||
site.DefaultThemeType = _themetype;
|
||||
site.DefaultContainerType = _containertype;
|
||||
site.AdminContainerType = _admincontainertype;
|
||||
site.IsDeleted = (_isdeleted == null || Boolean.Parse(_isdeleted));
|
||||
|
||||
site = await SiteService.UpdateSiteAsync(site);
|
||||
|
||||
_urls = _urls.Replace("\n", ",");
|
||||
var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
||||
{
|
||||
if (!names.Contains(alias.Name))
|
||||
{
|
||||
await AliasService.DeleteAliasAsync(alias.AliasId);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string name in names)
|
||||
{
|
||||
if (!_aliasList.Exists(item => item.Name == name))
|
||||
{
|
||||
Alias alias = new Alias
|
||||
{
|
||||
Name = name,
|
||||
TenantId = site.TenantId,
|
||||
SiteId = site.SiteId
|
||||
};
|
||||
await AliasService.AddAliasAsync(alias);
|
||||
}
|
||||
}
|
||||
|
||||
await Log(_alias, LogLevel.Information, PermissionNames.Edit, null, "Site Saved {Site}", site);
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["An Alias Specified Has Already Been Used For Another Site"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["You Must Provide A Site Name, Alias, And Default Theme/Container"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await Log(_alias, LogLevel.Error, string.Empty, ex, "Error Saving Site {SiteId} {Error}", _alias.SiteId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error Saving Site"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,13 +15,11 @@ else
|
|||
|
||||
<Pager Items="@_sites">
|
||||
<Header>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th>@Localizer["Name"]</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.AliasId.ToString())" ResourceKey="EditSite" /></td>
|
||||
<td><ActionDialog Header="Delete Site" Message="@Localizer["Are You Sure You Wish To Delete The {0} Site?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteSite(context))" ResourceKey="DeleteSite" /></td>
|
||||
<td><NavLink class="btn btn-primary" href="@(_scheme + context.Name +"/admin/site")">@Localizer["Edit"]</NavLink></td>
|
||||
<td><a href="@(_scheme + context.Name +"?reload")">@context.Name</a></td>
|
||||
</Row>
|
||||
</Pager>
|
||||
|
@ -48,34 +46,4 @@ else
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteSite(Alias alias)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (alias.SiteId != PageState.Site.SiteId || alias.TenantId != PageState.Site.TenantId)
|
||||
{
|
||||
SiteService.SetAlias(alias);
|
||||
await SiteService.DeleteSiteAsync(alias.SiteId);
|
||||
await Log(alias, LogLevel.Information, "", null, "Site Deleted {SiteId}", alias.SiteId);
|
||||
|
||||
var aliases = await AliasService.GetAliasesAsync();
|
||||
foreach (Alias a in aliases.Where(item => item.SiteId == alias.SiteId && item.TenantId == alias.TenantId))
|
||||
{
|
||||
await AliasService.DeleteAliasAsync(a.AliasId);
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["You Can Not Delete The Current Site"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await Log(alias, LogLevel.Error, "", ex, "Error Deleting Site {SiteId} {Error}", alias.SiteId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error Deleting Site"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
if (htmltext != null)
|
||||
{
|
||||
_content = htmltext.Content;
|
||||
_content = _content.Replace(Constants.ContentUrl, "/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl);
|
||||
_content = _content.Replace(Constants.ContentUrl, "/" + PageState.Alias.Path + Constants.ContentUrl);
|
||||
_createdby = htmltext.CreatedBy;
|
||||
_createdon = htmltext.CreatedOn;
|
||||
_modifiedby = htmltext.ModifiedBy;
|
||||
|
@ -72,7 +72,7 @@
|
|||
private async Task SaveContent()
|
||||
{
|
||||
string content = await RichTextEditorHtml.GetHtml();
|
||||
content = content.Replace("/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl, Constants.ContentUrl);
|
||||
content = content.Replace("/" + PageState.Alias.Path + Constants.ContentUrl, Constants.ContentUrl);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
if (htmltext != null)
|
||||
{
|
||||
content = htmltext.Content;
|
||||
content = content.Replace(Constants.ContentUrl, "/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl);
|
||||
content = content.Replace(Constants.ContentUrl, "/" + PageState.Alias.Path + Constants.ContentUrl);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Oqtane.Modules.HtmlText.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string ApiUrl => CreateApiUrl(_siteState.Alias, "HtmlText");
|
||||
private string ApiUrl => CreateApiUrl("HtmlText", _siteState.Alias);
|
||||
|
||||
public async Task<Models.HtmlText> GetHtmlTextAsync(int moduleId)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Linq;
|
||||
|
@ -19,7 +19,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Alias");
|
||||
private string Apiurl => CreateApiUrl("Alias", _siteState.Alias);
|
||||
|
||||
public async Task<List<Alias>> GetAliasesAsync()
|
||||
{
|
||||
|
@ -32,10 +32,9 @@ namespace Oqtane.Services
|
|||
return await GetJsonAsync<Alias>($"{Apiurl}/{aliasId}");
|
||||
}
|
||||
|
||||
public async Task<Alias> GetAliasAsync(string name, DateTime lastSyncDate)
|
||||
public async Task<Alias> GetAliasAsync(string path, DateTime lastSyncDate)
|
||||
{
|
||||
name = (string.IsNullOrEmpty(name)) ? "~" : name;
|
||||
return await GetJsonAsync<Alias>($"{Apiurl}/name/{WebUtility.UrlEncode(name)}?sync={lastSyncDate.ToString("yyyyMMddHHmmssfff")}");
|
||||
return await GetJsonAsync<Alias>($"{Apiurl}/name/?path={WebUtility.UrlEncode(path)}&sync={lastSyncDate.ToString("yyyyMMddHHmmssfff")}");
|
||||
}
|
||||
|
||||
public async Task<Alias> AddAliasAsync(Alias alias)
|
||||
|
|
28
Oqtane.Client/Services/DatabaseService.cs
Normal file
28
Oqtane.Client/Services/DatabaseService.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public class DatabaseService : ServiceBase, IDatabaseService
|
||||
{
|
||||
|
||||
private readonly SiteState _siteState;
|
||||
|
||||
public DatabaseService(HttpClient http, SiteState siteState) : base(http)
|
||||
{
|
||||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl("Database", _siteState.Alias);
|
||||
|
||||
public async Task<List<Database>> GetDatabasesAsync()
|
||||
{
|
||||
List<Database> databases = await GetJsonAsync<List<Database>>(Apiurl);
|
||||
return databases.OrderBy(item => item.FriendlyName).ToList();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ namespace Oqtane.Services
|
|||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "File");
|
||||
private string Apiurl => CreateApiUrl("File", _siteState.Alias);
|
||||
|
||||
public async Task<List<File>> GetFilesAsync(int folderId)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string ApiUrl => CreateApiUrl(_siteState.Alias, "Folder");
|
||||
private string ApiUrl => CreateApiUrl("Folder", _siteState.Alias);
|
||||
|
||||
public async Task<List<Folder>> GetFoldersAsync(int siteId)
|
||||
{
|
||||
|
|
|
@ -7,9 +7,14 @@ namespace Oqtane.Services
|
|||
{
|
||||
public class InstallationService : ServiceBase, IInstallationService
|
||||
{
|
||||
public InstallationService(HttpClient http):base(http) { }
|
||||
private readonly SiteState _siteState;
|
||||
|
||||
private string ApiUrl => CreateApiUrl("Installation");
|
||||
public InstallationService(HttpClient http, SiteState siteState) : base(http)
|
||||
{
|
||||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string ApiUrl => CreateApiUrl("Installation", _siteState.Alias);
|
||||
|
||||
public async Task<Installation> IsInstalled()
|
||||
{
|
||||
|
|
11
Oqtane.Client/Services/Interfaces/IDatabaseService.cs
Normal file
11
Oqtane.Client/Services/Interfaces/IDatabaseService.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public interface IDatabaseService
|
||||
{
|
||||
Task<List<Database>> GetDatabasesAsync();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -8,5 +8,6 @@ namespace Oqtane.Services
|
|||
{
|
||||
Task<List<Package>> GetPackagesAsync(string tag);
|
||||
Task DownloadPackageAsync(string packageId, string version, string folder);
|
||||
Task InstallPackagesAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -6,8 +7,6 @@ namespace Oqtane.Services
|
|||
{
|
||||
public interface ISiteService
|
||||
{
|
||||
void SetAlias(Alias alias);
|
||||
|
||||
Task<List<Site>> GetSitesAsync();
|
||||
|
||||
Task<Site> GetSiteAsync(int siteId);
|
||||
|
@ -17,5 +16,8 @@ namespace Oqtane.Services
|
|||
Task<Site> UpdateSiteAsync(Site site);
|
||||
|
||||
Task DeleteSiteAsync(int siteId);
|
||||
|
||||
[Obsolete("This method is deprecated.", false)]
|
||||
void SetAlias(Alias alias);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Linq;
|
||||
|
@ -16,7 +16,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "JobLog");
|
||||
private string Apiurl => CreateApiUrl("JobLog", _siteState.Alias);
|
||||
|
||||
public async Task<List<JobLog>> GetJobLogsAsync()
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Linq;
|
||||
|
@ -16,7 +16,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Job");
|
||||
private string Apiurl => CreateApiUrl("Job", _siteState.Alias);
|
||||
|
||||
public async Task<List<Job>> GetJobsAsync()
|
||||
{
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Language");
|
||||
private string Apiurl => CreateApiUrl("Language", _siteState.Alias);
|
||||
|
||||
public async Task<List<Language>> GetLanguagesAsync(int siteId)
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Localization");
|
||||
private string Apiurl => CreateApiUrl("Localization", _siteState.Alias);
|
||||
|
||||
public async Task<IEnumerable<Culture>> GetCulturesAsync() => await GetJsonAsync<IEnumerable<Culture>>(Apiurl);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
|
@ -23,7 +23,7 @@ namespace Oqtane.Services
|
|||
_navigationManager = navigationManager;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Log");
|
||||
private string Apiurl => CreateApiUrl("Log", _siteState.Alias);
|
||||
|
||||
public async Task<List<Log>> GetLogsAsync(int siteId, string level, string function, int rows)
|
||||
{
|
||||
|
@ -49,7 +49,6 @@ namespace Oqtane.Services
|
|||
}
|
||||
else
|
||||
{
|
||||
base.Alias = alias;
|
||||
log.SiteId = alias.SiteId;
|
||||
}
|
||||
log.PageId = pageId;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "ModuleDefinition");
|
||||
private string Apiurl => CreateApiUrl("ModuleDefinition", _siteState.Alias);
|
||||
|
||||
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync(int siteId)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
@ -17,7 +17,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Module");
|
||||
private string Apiurl => CreateApiUrl("Module", _siteState.Alias);
|
||||
|
||||
public async Task<List<Module>> GetModulesAsync(int siteId)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using Oqtane.Shared;
|
||||
|
@ -16,7 +16,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Notification");
|
||||
private string Apiurl => CreateApiUrl("Notification", _siteState.Alias);
|
||||
|
||||
public async Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId)
|
||||
{
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public class PackageService : ServiceBase, IPackageService
|
||||
{
|
||||
public PackageService(HttpClient http) : base(http) { }
|
||||
{
|
||||
private readonly SiteState _siteState;
|
||||
|
||||
private string Apiurl => CreateApiUrl("Package");
|
||||
public PackageService(HttpClient http, SiteState siteState) : base(http)
|
||||
{
|
||||
_siteState = siteState;
|
||||
}
|
||||
private string Apiurl => CreateApiUrl("Package", _siteState.Alias);
|
||||
|
||||
public async Task<List<Package>> GetPackagesAsync(string tag)
|
||||
{
|
||||
|
@ -22,5 +27,10 @@ namespace Oqtane.Services
|
|||
{
|
||||
await PostAsync($"{Apiurl}?packageid={packageId}&version={version}&folder={folder}");
|
||||
}
|
||||
|
||||
public async Task InstallPackagesAsync()
|
||||
{
|
||||
await GetJsonAsync<List<string>>($"{Apiurl}/install");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Oqtane.Shared;
|
||||
|
@ -15,7 +15,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "PageModule");
|
||||
private string Apiurl => CreateApiUrl("PageModule", _siteState.Alias);
|
||||
|
||||
public async Task<PageModule> GetPageModuleAsync(int pageModuleId)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
@ -20,7 +20,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Page");
|
||||
private string Apiurl => CreateApiUrl("Page", _siteState.Alias);
|
||||
|
||||
public async Task<List<Page>> GetPagesAsync(int siteId)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Linq;
|
||||
|
@ -17,7 +17,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Profile");
|
||||
private string Apiurl => CreateApiUrl("Profile", _siteState.Alias);
|
||||
|
||||
public async Task<List<Profile>> GetProfilesAsync(int siteId)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Role");
|
||||
private string Apiurl => CreateApiUrl("Role", _siteState.Alias);
|
||||
|
||||
public async Task<List<Role>> GetRolesAsync(int siteId)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Net.Http.Json;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
|
@ -17,6 +18,55 @@ namespace Oqtane.Services
|
|||
_http = client;
|
||||
}
|
||||
|
||||
public string CreateApiUrl(string serviceName, Alias alias)
|
||||
{
|
||||
return CreateApiUrl(serviceName, alias, ControllerRoutes.ApiRoute);
|
||||
}
|
||||
|
||||
public string CreateApiUrl(string serviceName, Alias alias, string routeTemplate)
|
||||
{
|
||||
string apiurl = "/";
|
||||
if (routeTemplate == ControllerRoutes.ApiRoute)
|
||||
{
|
||||
if (alias != null && !string.IsNullOrEmpty(alias.Path))
|
||||
{
|
||||
// include the alias path for multi-tenant context
|
||||
apiurl += alias.Path + "/";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// legacy support for ControllerRoutes.Default
|
||||
if (alias != null)
|
||||
{
|
||||
// include the alias for multi-tenant context
|
||||
apiurl += $"{alias.AliasId}/";
|
||||
}
|
||||
else
|
||||
{
|
||||
// tenant agnostic
|
||||
apiurl += "~/";
|
||||
}
|
||||
}
|
||||
apiurl += $"api/{serviceName}";
|
||||
return apiurl;
|
||||
}
|
||||
|
||||
// add entityid parameter to url for custom authorization policy
|
||||
public string CreateAuthorizationPolicyUrl(string url, int entityId)
|
||||
{
|
||||
string qs = "entityid=" + entityId.ToString();
|
||||
|
||||
if (url.Contains("?"))
|
||||
{
|
||||
return url + "&" + qs;
|
||||
}
|
||||
else
|
||||
{
|
||||
return url + "?" + qs;
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task GetAsync(string uri)
|
||||
{
|
||||
var response = await _http.GetAsync(uri);
|
||||
|
@ -135,61 +185,26 @@ namespace Oqtane.Services
|
|||
//TODO Missing content JSON validation
|
||||
}
|
||||
|
||||
// create an API Url which is tenant agnostic ( for use during installation )
|
||||
public string CreateApiUrl(string serviceName)
|
||||
{
|
||||
return CreateApiUrl(null, serviceName);
|
||||
}
|
||||
|
||||
// create an API Url which is tenant aware ( for use with repositories )
|
||||
public string CreateApiUrl(Alias alias, string serviceName)
|
||||
{
|
||||
string apiurl = "/";
|
||||
|
||||
if (Alias != null)
|
||||
{
|
||||
alias = Alias; // override the default alias ( for cross-tenant service calls )
|
||||
}
|
||||
|
||||
if (alias != null)
|
||||
{
|
||||
// include the alias for multi-tenant context
|
||||
apiurl += $"{alias.AliasId}/";
|
||||
}
|
||||
else
|
||||
{
|
||||
// tenant agnostic
|
||||
apiurl += "~/";
|
||||
}
|
||||
|
||||
apiurl += $"api/{serviceName}";
|
||||
|
||||
return apiurl;
|
||||
}
|
||||
|
||||
// can be used to override the default alias
|
||||
public Alias Alias { get; set; }
|
||||
|
||||
// add entityid parameter to url for custom authorization policy
|
||||
public string CreateAuthorizationPolicyUrl(string url, int entityId)
|
||||
{
|
||||
string qs = "entityid=" + entityId.ToString();
|
||||
|
||||
if (url.Contains("?"))
|
||||
{
|
||||
return url + "&" + qs;
|
||||
}
|
||||
else
|
||||
{
|
||||
return url + "?" + qs;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("This method is obsolete. Use CreateApiUrl(Alias alias, string serviceName) instead.", false)]
|
||||
public string CreateApiUrl(Alias alias, string absoluteUri, string serviceName)
|
||||
{
|
||||
// only retained for short term backward compatibility
|
||||
return CreateApiUrl(alias, serviceName);
|
||||
}
|
||||
|
||||
[Obsolete("This method is obsolete. Use CreateApiUrl(string serviceName, Alias alias) instead.", false)]
|
||||
public string CreateApiUrl(string serviceName)
|
||||
{
|
||||
return CreateApiUrl(serviceName, null, ControllerRoutes.Default);
|
||||
}
|
||||
|
||||
[Obsolete("This method is deprecated.", false)]
|
||||
public Alias Alias { get; set; }
|
||||
|
||||
[Obsolete("This method is obsolete. Use CreateApiUrl(string serviceName, Alias alias) instead.", false)]
|
||||
public string CreateApiUrl(Alias alias, string serviceName)
|
||||
{
|
||||
return CreateApiUrl(serviceName, alias, ControllerRoutes.Default);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
|
@ -18,7 +18,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Setting");
|
||||
private string Apiurl => CreateApiUrl("Setting", _siteState.Alias);
|
||||
public async Task<Dictionary<string, string>> GetTenantSettingsAsync()
|
||||
{
|
||||
return await GetSettingsAsync(EntityNames.Tenant, -1);
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Shared;
|
||||
using System;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
|
@ -18,12 +19,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Site");
|
||||
|
||||
public void SetAlias(Alias alias)
|
||||
{
|
||||
base.Alias = alias;
|
||||
}
|
||||
private string Apiurl => CreateApiUrl("Site", _siteState.Alias);
|
||||
|
||||
public async Task<List<Site>> GetSitesAsync()
|
||||
{
|
||||
|
@ -50,5 +46,11 @@ namespace Oqtane.Services
|
|||
{
|
||||
await DeleteAsync($"{Apiurl}/{siteId}");
|
||||
}
|
||||
|
||||
[Obsolete("This method is deprecated.", false)]
|
||||
public void SetAlias(Alias alias)
|
||||
{
|
||||
base.Alias = alias;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
@ -8,9 +9,13 @@ namespace Oqtane.Services
|
|||
{
|
||||
public class SiteTemplateService : ServiceBase, ISiteTemplateService
|
||||
{
|
||||
public SiteTemplateService(HttpClient http) : base(http) { }
|
||||
private readonly SiteState _siteState;
|
||||
|
||||
private string Apiurl => CreateApiUrl("SiteTemplate");
|
||||
public SiteTemplateService(HttpClient http, SiteState siteState) : base(http)
|
||||
{
|
||||
_siteState = siteState;
|
||||
}
|
||||
private string Apiurl => CreateApiUrl("SiteTemplate", _siteState.Alias);
|
||||
|
||||
public async Task<List<SiteTemplate>> GetSiteTemplatesAsync()
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -14,7 +14,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Sql");
|
||||
private string Apiurl => CreateApiUrl("Sql", _siteState.Alias);
|
||||
|
||||
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
|
||||
{
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
using System.Net.Http;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public class SystemService : ServiceBase, ISystemService
|
||||
{
|
||||
public SystemService(HttpClient http) : base(http) { }
|
||||
private readonly SiteState _siteState;
|
||||
|
||||
private string Apiurl => CreateApiUrl("System");
|
||||
public SystemService(HttpClient http, SiteState siteState) : base(http)
|
||||
{
|
||||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl("System", _siteState.Alias);
|
||||
|
||||
public async Task<Dictionary<string, string>> GetSystemInfoAsync()
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
@ -16,7 +16,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Tenant");
|
||||
private string Apiurl => CreateApiUrl("Tenant", _siteState.Alias);
|
||||
|
||||
public async Task<List<Tenant>> GetTenantsAsync()
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string ApiUrl => CreateApiUrl(_siteState.Alias, "Theme");
|
||||
private string ApiUrl => CreateApiUrl("Theme", _siteState.Alias);
|
||||
|
||||
public async Task<List<Theme>> GetThemesAsync()
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -16,7 +16,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "UserRole");
|
||||
private string Apiurl => CreateApiUrl("UserRole", _siteState.Alias);
|
||||
|
||||
public async Task<List<UserRole>> GetUserRolesAsync(int siteId)
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Oqtane.Services
|
|||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "User");
|
||||
private string Apiurl => CreateApiUrl("User", _siteState.Alias);
|
||||
|
||||
public async Task<User> GetUserAsync(int userId, int siteId)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,9 @@ namespace Oqtane.Themes.Controls
|
|||
var interop = new Interop(jsRuntime);
|
||||
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
|
||||
var fields = new { __RequestVerificationToken = antiforgerytoken, returnurl = !authorizedtoviewpage ? PageState.Alias.Path : PageState.Alias.Path + "/" + PageState.Page.Path };
|
||||
await interop.SubmitForm($"/{PageState.Alias.AliasId}/pages/logout/", fields);
|
||||
string url = "/pages/logout/";
|
||||
if (!string.IsNullOrEmpty(PageState.Alias.Path)) url = "/" + PageState.Alias.Path + url;
|
||||
await interop.SubmitForm(url, fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Http;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class AliasController : Controller
|
||||
{
|
||||
private readonly IAliasRepository _aliases;
|
||||
|
@ -46,17 +46,16 @@ namespace Oqtane.Controllers
|
|||
return _aliases.GetAlias(id);
|
||||
}
|
||||
|
||||
// GET api/<controller>/name/xxx?sync=yyyyMMddHHmmssfff
|
||||
[HttpGet("name/{**name}")]
|
||||
public Alias Get(string name, string sync)
|
||||
// GET api/<controller>/name/?path=xxx&sync=yyyyMMddHHmmssfff
|
||||
[HttpGet("name")]
|
||||
public Alias Get(string path, string sync)
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (_accessor.HttpContext != null)
|
||||
{
|
||||
name = (name == "~") ? "" : name;
|
||||
name = _accessor.HttpContext.Request.Host.Value + "/" + WebUtility.UrlDecode(name);
|
||||
alias = _aliases.GetAlias(name);
|
||||
path = _accessor.HttpContext.Request.Host.Value + "/" + WebUtility.UrlDecode(path);
|
||||
alias = _aliases.GetAlias(path);
|
||||
}
|
||||
|
||||
// get sync events
|
||||
|
|
52
Oqtane.Server/Controllers/DatabaseController.cs
Normal file
52
Oqtane.Server/Controllers/DatabaseController.cs
Normal file
|
@ -0,0 +1,52 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class DatabaseController : Controller
|
||||
{
|
||||
public DatabaseController() { }
|
||||
|
||||
// GET: api/<controller>
|
||||
[HttpGet]
|
||||
public IEnumerable<Models.Database> Get()
|
||||
{
|
||||
var databases = new List<Models.Database>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Name = "LocalDB",
|
||||
FriendlyName = "Local Database",
|
||||
Type = "Oqtane.Installer.Controls.LocalDBConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "SqlServer",
|
||||
FriendlyName = "SQL Server",
|
||||
Type = "Oqtane.Installer.Controls.SqlServerConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "Sqlite",
|
||||
FriendlyName = "Sqlite",
|
||||
Type = "Oqtane.Installer.Controls.SqliteConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "MySQL",
|
||||
FriendlyName = "MySQL",
|
||||
Type = "Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "PostgreSQL",
|
||||
FriendlyName = "PostgreSQL",
|
||||
Type = "Oqtane.Installer.Controls.PostGreSQLConfig, Oqtane.Client"
|
||||
}
|
||||
};
|
||||
return databases;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,30 +16,27 @@ using System.Net;
|
|||
using Oqtane.Enums;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Repository;
|
||||
using Microsoft.AspNetCore.Routing.Constraints;
|
||||
using Oqtane.Extensions;
|
||||
|
||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class FileController : Controller
|
||||
{
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly IFileRepository _files;
|
||||
private readonly IFolderRepository _folders;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly ITenantResolver _tenants;
|
||||
private readonly ILogManager _logger;
|
||||
|
||||
public FileController(IWebHostEnvironment environment, IFileRepository files, IFolderRepository folders, IUserPermissions userPermissions, ITenantResolver tenants, ILogManager logger)
|
||||
public FileController(IWebHostEnvironment environment, IFileRepository files, IFolderRepository folders, IUserPermissions userPermissions, ILogManager logger)
|
||||
{
|
||||
_environment = environment;
|
||||
_files = files;
|
||||
_folders = folders;
|
||||
_userPermissions = userPermissions;
|
||||
_tenants = tenants;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,21 +15,21 @@ using Microsoft.AspNetCore.Hosting;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class FolderController : Controller
|
||||
{
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly IFolderRepository _folders;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly ITenantResolver _tenants;
|
||||
private readonly ITenantManager _tenantManager;
|
||||
private readonly ILogManager _logger;
|
||||
|
||||
public FolderController(IWebHostEnvironment environment, IFolderRepository folders, IUserPermissions userPermissions, ITenantResolver tenants, ILogManager logger)
|
||||
public FolderController(IWebHostEnvironment environment, IFolderRepository folders, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger)
|
||||
{
|
||||
_environment = environment;
|
||||
_folders = folders;
|
||||
_userPermissions = userPermissions;
|
||||
_tenants = tenants;
|
||||
_tenantManager = tenantManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ namespace Oqtane.Controllers
|
|||
|
||||
private string GetFolderPath(Folder folder)
|
||||
{
|
||||
return Utilities.PathCombine(_environment.ContentRootPath, "Content", "Tenants", _tenants.GetTenant().TenantId.ToString(), "Sites", folder.SiteId.ToString(), folder.Path);
|
||||
return Utilities.PathCombine(_environment.ContentRootPath, "Content", "Tenants", _tenantManager.GetTenant().TenantId.ToString(), "Sites", folder.SiteId.ToString(), folder.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,11 +12,10 @@ using Oqtane.Modules;
|
|||
using Oqtane.Shared;
|
||||
using Oqtane.Themes;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class InstallationController : Controller
|
||||
{
|
||||
private readonly IConfigurationRoot _config;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Models;
|
||||
|
@ -12,7 +12,7 @@ using Oqtane.Repository;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class JobController : Controller
|
||||
{
|
||||
private readonly IJobRepository _jobs;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Enums;
|
||||
|
@ -9,7 +9,7 @@ using Oqtane.Repository;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class JobLogController : Controller
|
||||
{
|
||||
private readonly IJobLogRepository _jobLogs;
|
||||
|
|
|
@ -9,7 +9,7 @@ using Oqtane.Shared;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class LanguageController : Controller
|
||||
{
|
||||
private readonly ILanguageRepository _languages;
|
||||
|
|
|
@ -9,7 +9,7 @@ using Oqtane.Shared;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class LocalizationController : Controller
|
||||
{
|
||||
private readonly ILocalizationManager _localizationManager;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
@ -9,7 +9,7 @@ using Oqtane.Shared;
|
|||
namespace Oqtane.Controllers
|
||||
{
|
||||
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class LogController : Controller
|
||||
{
|
||||
private readonly ILogManager _logger;
|
||||
|
|
|
@ -11,7 +11,7 @@ using Oqtane.Security;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class ModuleController : Controller
|
||||
{
|
||||
private readonly IModuleRepository _modules;
|
||||
|
@ -20,11 +20,11 @@ namespace Oqtane.Controllers
|
|||
private readonly IModuleDefinitionRepository _moduleDefinitions;
|
||||
private readonly ISettingRepository _settings;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly ITenantResolver _tenants;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public ModuleController(IModuleRepository modules, IPageModuleRepository pageModules, IPageRepository pages, IModuleDefinitionRepository moduleDefinitions, ISettingRepository settings, IUserPermissions userPermissions, ITenantResolver tenants, ISyncManager syncManager, ILogManager logger)
|
||||
public ModuleController(IModuleRepository modules, IPageModuleRepository pageModules, IPageRepository pages, IModuleDefinitionRepository moduleDefinitions, ISettingRepository settings, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
|
||||
{
|
||||
_modules = modules;
|
||||
_pageModules = pageModules;
|
||||
|
@ -32,9 +32,9 @@ namespace Oqtane.Controllers
|
|||
_moduleDefinitions = moduleDefinitions;
|
||||
_settings = settings;
|
||||
_userPermissions = userPermissions;
|
||||
_tenants = tenants;
|
||||
_syncManager = syncManager;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET: api/<controller>?siteid=x
|
||||
|
@ -108,7 +108,7 @@ namespace Oqtane.Controllers
|
|||
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Page, module.PageId, PermissionNames.Edit))
|
||||
{
|
||||
module = _modules.AddModule(module);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Module Added {Module}", module);
|
||||
}
|
||||
else
|
||||
|
@ -142,7 +142,7 @@ namespace Oqtane.Controllers
|
|||
}
|
||||
}
|
||||
}
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -161,7 +161,7 @@ namespace Oqtane.Controllers
|
|||
if (_userPermissions.IsAuthorized(User, EntityNames.Module, id, PermissionNames.Edit))
|
||||
{
|
||||
_modules.DeleteModule(id);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Deleted {ModuleId}", id);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -17,7 +17,7 @@ using System.Text.Json;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class ModuleDefinitionController : Controller
|
||||
{
|
||||
private readonly IModuleDefinitionRepository _moduleDefinitions;
|
||||
|
|
|
@ -10,7 +10,7 @@ using Oqtane.Security;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class NotificationController : Controller
|
||||
{
|
||||
private readonly INotificationRepository _notifications;
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Oqtane.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Enums;
|
||||
// ReSharper disable PartialTypeWithSinglePart
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class PackageController : Controller
|
||||
{
|
||||
private readonly IInstallationManager _installationManager;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly ILogManager _logger;
|
||||
|
||||
public PackageController(IWebHostEnvironment environment)
|
||||
public PackageController(IInstallationManager installationManager, IWebHostEnvironment environment, ILogManager logger)
|
||||
{
|
||||
_installationManager = installationManager;
|
||||
_environment = environment;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
// GET: api/<controller>?tag=x
|
||||
|
@ -86,6 +91,14 @@ namespace Oqtane.Controllers
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("install")]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public void InstallPackages()
|
||||
{
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Packages Installed");
|
||||
_installationManager.InstallPackages("Packages");
|
||||
}
|
||||
}
|
||||
|
||||
public partial class SearchResult
|
||||
|
|
|
@ -13,7 +13,7 @@ using Oqtane.Repository;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class PageController : Controller
|
||||
{
|
||||
private readonly IPageRepository _pages;
|
||||
|
@ -21,20 +21,20 @@ namespace Oqtane.Controllers
|
|||
private readonly IPageModuleRepository _pageModules;
|
||||
private readonly ISettingRepository _settings;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly ITenantResolver _tenants;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public PageController(IPageRepository pages, IModuleRepository modules, IPageModuleRepository pageModules, ISettingRepository settings, IUserPermissions userPermissions, ITenantResolver tenants, ISyncManager syncManager, ILogManager logger)
|
||||
public PageController(IPageRepository pages, IModuleRepository modules, IPageModuleRepository pageModules, ISettingRepository settings, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
|
||||
{
|
||||
_pages = pages;
|
||||
_modules = modules;
|
||||
_pageModules = pageModules;
|
||||
_settings = settings;
|
||||
_userPermissions = userPermissions;
|
||||
_tenants = tenants;
|
||||
_syncManager = syncManager;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET: api/<controller>?siteid=x
|
||||
|
@ -132,7 +132,7 @@ namespace Oqtane.Controllers
|
|||
if (_userPermissions.IsAuthorized(User,PermissionNames.Edit, permissions))
|
||||
{
|
||||
page = _pages.AddPage(page);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, page.SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, page.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Page Added {Page}", page);
|
||||
|
||||
if (!page.Path.StartsWith("admin/"))
|
||||
|
@ -183,7 +183,7 @@ namespace Oqtane.Controllers
|
|||
page.IsPersonalizable = false;
|
||||
page.UserId = int.Parse(userid);
|
||||
page = _pages.AddPage(page);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, page.SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, page.SiteId);
|
||||
|
||||
// copy modules
|
||||
List<PageModule> pagemodules = _pageModules.GetPageModules(page.SiteId).ToList();
|
||||
|
@ -228,7 +228,7 @@ namespace Oqtane.Controllers
|
|||
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Page, page.PageId, PermissionNames.Edit))
|
||||
{
|
||||
page = _pages.UpdatePage(page);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, page.SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, page.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Page Updated {Page}", page);
|
||||
}
|
||||
else
|
||||
|
@ -258,7 +258,7 @@ namespace Oqtane.Controllers
|
|||
}
|
||||
order += 2;
|
||||
}
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, siteid);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, siteid);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Page Order Updated {SiteId} {PageId} {ParentId}", siteid, pageid, parentid);
|
||||
}
|
||||
else
|
||||
|
@ -277,7 +277,7 @@ namespace Oqtane.Controllers
|
|||
if (_userPermissions.IsAuthorized(User, EntityNames.Page, page.PageId, PermissionNames.Edit))
|
||||
{
|
||||
_pages.DeletePage(page.PageId);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, page.SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, page.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Page Deleted {PageId}", page.PageId);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -11,22 +11,22 @@ using Oqtane.Security;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class PageModuleController : Controller
|
||||
{
|
||||
private readonly IPageModuleRepository _pageModules;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly ITenantResolver _tenants;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public PageModuleController(IPageModuleRepository pageModules, IUserPermissions userPermissions, ITenantResolver tenants, ISyncManager syncManager, ILogManager logger)
|
||||
public PageModuleController(IPageModuleRepository pageModules, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
|
||||
{
|
||||
_pageModules = pageModules;
|
||||
_userPermissions = userPermissions;
|
||||
_tenants = tenants;
|
||||
_syncManager = syncManager;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET api/<controller>/5
|
||||
|
@ -71,7 +71,7 @@ namespace Oqtane.Controllers
|
|||
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Page, pageModule.PageId, PermissionNames.Edit))
|
||||
{
|
||||
pageModule = _pageModules.AddPageModule(pageModule);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Page Module Added {PageModule}", pageModule);
|
||||
}
|
||||
else
|
||||
|
@ -91,7 +91,7 @@ namespace Oqtane.Controllers
|
|||
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Module, pageModule.ModuleId, PermissionNames.Edit))
|
||||
{
|
||||
pageModule = _pageModules.UpdatePageModule(pageModule);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Page Module Updated {PageModule}", pageModule);
|
||||
}
|
||||
else
|
||||
|
@ -121,7 +121,7 @@ namespace Oqtane.Controllers
|
|||
}
|
||||
order += 2;
|
||||
}
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Page Module Order Updated {PageId} {Pane}", pageid, pane);
|
||||
}
|
||||
else
|
||||
|
@ -140,7 +140,7 @@ namespace Oqtane.Controllers
|
|||
if (_userPermissions.IsAuthorized(User, EntityNames.Page, pagemodule.PageId, PermissionNames.Edit))
|
||||
{
|
||||
_pageModules.DeletePageModule(id);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Page Module Deleted {PageModuleId}", id);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Enums;
|
||||
|
@ -9,7 +9,7 @@ using Oqtane.Repository;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class ProfileController : Controller
|
||||
{
|
||||
private readonly IProfileRepository _profiles;
|
||||
|
|
|
@ -9,7 +9,7 @@ using Oqtane.Repository;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class RoleController : Controller
|
||||
{
|
||||
private readonly IRoleRepository _roles;
|
||||
|
|
|
@ -10,24 +10,24 @@ using Oqtane.Repository;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class SettingController : Controller
|
||||
{
|
||||
private readonly ISettingRepository _settings;
|
||||
private readonly IPageModuleRepository _pageModules;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly ITenantResolver _tenants;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public SettingController(ISettingRepository settings, IPageModuleRepository pageModules, IUserPermissions userPermissions, ITenantResolver tenants, ISyncManager syncManager, ILogManager logger)
|
||||
public SettingController(ISettingRepository settings, IPageModuleRepository pageModules, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
|
||||
{
|
||||
_settings = settings;
|
||||
_pageModules = pageModules;
|
||||
_userPermissions = userPermissions;
|
||||
_tenants = tenants;
|
||||
_syncManager = syncManager;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET: api/<controller>
|
||||
|
@ -73,7 +73,7 @@ namespace Oqtane.Controllers
|
|||
setting = _settings.AddSetting(setting);
|
||||
if (setting.EntityName == EntityNames.Module)
|
||||
{
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
}
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Setting Added {Setting}", setting);
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ namespace Oqtane.Controllers
|
|||
setting = _settings.UpdateSetting(setting);
|
||||
if (setting.EntityName == EntityNames.Module)
|
||||
{
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
}
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Setting Updated {Setting}", setting);
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ namespace Oqtane.Controllers
|
|||
_settings.DeleteSetting(id);
|
||||
if (setting.EntityName == EntityNames.Module)
|
||||
{
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, _tenants.GetAlias().SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
|
||||
}
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Setting Deleted {Setting}", setting);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Models;
|
||||
|
@ -10,20 +10,20 @@ using Oqtane.Repository;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class SiteController : Controller
|
||||
{
|
||||
private readonly ISiteRepository _sites;
|
||||
private readonly ITenantResolver _tenants;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public SiteController(ISiteRepository sites, ITenantResolver tenants, ISyncManager syncManager, ILogManager logger)
|
||||
public SiteController(ISiteRepository sites, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
|
||||
{
|
||||
_sites = sites;
|
||||
_tenants = tenants;
|
||||
_syncManager = syncManager;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET: api/<controller>
|
||||
|
@ -52,8 +52,7 @@ namespace Oqtane.Controllers
|
|||
{
|
||||
// provision initial site during installation
|
||||
authorized = true;
|
||||
Tenant tenant = _tenants.GetTenant();
|
||||
site.TenantId = tenant.TenantId;
|
||||
site.TenantId = _alias.TenantId;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -76,7 +75,7 @@ namespace Oqtane.Controllers
|
|||
if (ModelState.IsValid)
|
||||
{
|
||||
site = _sites.UpdateSite(site);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, site.SiteId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, site.SiteId);
|
||||
_logger.Log(site.SiteId, LogLevel.Information, this, LogFunction.Update, "Site Updated {Site}", site);
|
||||
}
|
||||
return site;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Oqtane.Models;
|
||||
|
@ -7,7 +7,7 @@ using Oqtane.Shared;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class SiteTemplateController : Controller
|
||||
{
|
||||
private readonly ISiteTemplateRepository _siteTemplates;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
|
@ -11,7 +11,7 @@ using Microsoft.Data.SqlClient;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class SqlController : Controller
|
||||
{
|
||||
private readonly ITenantRepository _tenants;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Shared;
|
||||
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Hosting;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class SystemController : Controller
|
||||
{
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
|
@ -9,7 +9,7 @@ using Oqtane.Repository;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class TenantController : Controller
|
||||
{
|
||||
private readonly ITenantRepository _tenants;
|
||||
|
|
|
@ -16,7 +16,7 @@ using System.Text.Json;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class ThemeController : Controller
|
||||
{
|
||||
private readonly IThemeRepository _themes;
|
||||
|
|
|
@ -18,7 +18,7 @@ using Oqtane.Extensions;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class UserController : Controller
|
||||
{
|
||||
private readonly IUserRepository _users;
|
||||
|
@ -26,26 +26,26 @@ namespace Oqtane.Controllers
|
|||
private readonly IUserRoleRepository _userRoles;
|
||||
private readonly UserManager<IdentityUser> _identityUserManager;
|
||||
private readonly SignInManager<IdentityUser> _identitySignInManager;
|
||||
private readonly ITenantResolver _tenants;
|
||||
private readonly INotificationRepository _notifications;
|
||||
private readonly IFolderRepository _folders;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ISiteRepository _sites;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public UserController(IUserRepository users, IRoleRepository roles, IUserRoleRepository userRoles, UserManager<IdentityUser> identityUserManager, SignInManager<IdentityUser> identitySignInManager, ITenantResolver tenants, INotificationRepository notifications, IFolderRepository folders, ISyncManager syncManager, ISiteRepository sites, ILogManager logger)
|
||||
public UserController(IUserRepository users, IRoleRepository roles, IUserRoleRepository userRoles, UserManager<IdentityUser> identityUserManager, SignInManager<IdentityUser> identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, ISyncManager syncManager, ISiteRepository sites, ILogManager logger)
|
||||
{
|
||||
_users = users;
|
||||
_roles = roles;
|
||||
_userRoles = userRoles;
|
||||
_identityUserManager = identityUserManager;
|
||||
_identitySignInManager = identitySignInManager;
|
||||
_tenants = tenants;
|
||||
_folders = folders;
|
||||
_notifications = notifications;
|
||||
_syncManager = syncManager;
|
||||
_sites = sites;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET api/<controller>/5?siteid=x
|
||||
|
@ -146,7 +146,7 @@ namespace Oqtane.Controllers
|
|||
if (!verified)
|
||||
{
|
||||
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
||||
string url = HttpContext.Request.Scheme + "://" + _tenants.GetAlias().Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||
string url = HttpContext.Request.Scheme + "://" + _alias.Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||
string body = "Dear " + user.DisplayName + ",\n\nIn Order To Complete The Registration Of Your User Account Please Click The Link Displayed Below:\n\n" + url + "\n\nThank You!";
|
||||
var notification = new Notification(user.SiteId, null, newUser, "User Account Verification", body, null);
|
||||
_notifications.AddNotification(notification);
|
||||
|
@ -243,7 +243,7 @@ namespace Oqtane.Controllers
|
|||
}
|
||||
}
|
||||
user = _users.UpdateUser(user);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.User, user.UserId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.User, user.UserId);
|
||||
user.Password = ""; // remove sensitive information
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "User Updated {User}", user);
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ namespace Oqtane.Controllers
|
|||
if (identityuser != null)
|
||||
{
|
||||
string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser);
|
||||
string url = HttpContext.Request.Scheme + "://" + _tenants.GetAlias().Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||
string url = HttpContext.Request.Scheme + "://" + _alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||
string body = "Dear " + user.DisplayName + ",\n\nPlease Click The Link Displayed Below To Reset Your Password:\n\n" + url + "\n\nThank You!";
|
||||
var notification = new Notification(user.SiteId, null, user, "User Password Reset", body, null);
|
||||
_notifications.AddNotification(notification);
|
||||
|
|
|
@ -10,22 +10,22 @@ using System.Linq;
|
|||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class UserRoleController : Controller
|
||||
{
|
||||
private readonly IUserRoleRepository _userRoles;
|
||||
private readonly IRoleRepository _roles;
|
||||
private readonly ITenantResolver _tenants;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public UserRoleController(IUserRoleRepository userRoles, IRoleRepository roles, ITenantResolver tenants, ISyncManager syncManager, ILogManager logger)
|
||||
public UserRoleController(IUserRoleRepository userRoles, IRoleRepository roles, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
|
||||
{
|
||||
_userRoles = userRoles;
|
||||
_roles = roles;
|
||||
_syncManager = syncManager;
|
||||
_tenants = tenants;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET: api/<controller>?siteid=x
|
||||
|
@ -62,7 +62,7 @@ namespace Oqtane.Controllers
|
|||
userRole = _userRoles.AddUserRole(userRole);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "User Role Added {UserRole}", userRole);
|
||||
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.User, userRole.UserId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.User, userRole.UserId);
|
||||
}
|
||||
return userRole;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ namespace Oqtane.Controllers
|
|||
if (ModelState.IsValid && (User.IsInRole(RoleNames.Host) || role.Name != RoleNames.Host))
|
||||
{
|
||||
userRole = _userRoles.UpdateUserRole(userRole);
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.User, userRole.UserId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.User, userRole.UserId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "User Role Updated {UserRole}", userRole);
|
||||
}
|
||||
return userRole;
|
||||
|
@ -96,15 +96,15 @@ namespace Oqtane.Controllers
|
|||
if (userRole.Role.Name == RoleNames.Host)
|
||||
{
|
||||
// add site specific user roles to preserve user access
|
||||
var role = _roles.GetRoles(_tenants.GetAlias().SiteId).FirstOrDefault(item => item.Name == RoleNames.Registered);
|
||||
var role = _roles.GetRoles(_alias.SiteId).FirstOrDefault(item => item.Name == RoleNames.Registered);
|
||||
userRole = _userRoles.AddUserRole(new UserRole { UserId = userRole.UserId, RoleId = role.RoleId, EffectiveDate = null, ExpiryDate = null });
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "User Role Added {UserRole}", userRole);
|
||||
role = _roles.GetRoles(_tenants.GetAlias().SiteId).FirstOrDefault(item => item.Name == RoleNames.Admin);
|
||||
role = _roles.GetRoles(_alias.SiteId).FirstOrDefault(item => item.Name == RoleNames.Admin);
|
||||
userRole = _userRoles.AddUserRole(new UserRole { UserId = userRole.UserId, RoleId = role.RoleId, EffectiveDate = null, ExpiryDate = null });
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "User Role Added {UserRole}", userRole);
|
||||
}
|
||||
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.User, userRole.UserId);
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.User, userRole.UserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,5 +38,8 @@ namespace Oqtane.Extensions
|
|||
|
||||
return app;
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UseTenantResolution(this IApplicationBuilder builder)
|
||||
=> builder.UseMiddleware<TenantMiddleware>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -464,12 +464,12 @@ namespace Oqtane.Infrastructure
|
|||
{
|
||||
using (var scope = _serviceScopeFactory.CreateScope())
|
||||
{
|
||||
// use the SiteState to set the Alias explicitly so the tenant can be resolved
|
||||
// set the alias explicitly so the tenant can be resolved
|
||||
var aliases = scope.ServiceProvider.GetRequiredService<IAliasRepository>();
|
||||
var firstAlias = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
|
||||
var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstAlias);
|
||||
var siteState = scope.ServiceProvider.GetRequiredService<SiteState>();
|
||||
siteState.Alias = alias;
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
|
||||
tenantManager.SetAlias(alias);
|
||||
|
||||
var sites = scope.ServiceProvider.GetRequiredService<ISiteRepository>();
|
||||
var site = sites.GetSites().FirstOrDefault(item => item.Name == install.SiteName);
|
||||
|
|
12
Oqtane.Server/Infrastructure/Interfaces/ITenantManager.cs
Normal file
12
Oqtane.Server/Infrastructure/Interfaces/ITenantManager.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public interface ITenantManager
|
||||
{
|
||||
Alias GetAlias();
|
||||
Tenant GetTenant();
|
||||
void SetAlias(Alias alias);
|
||||
void SetTenant(int tenantId);
|
||||
}
|
||||
}
|
|
@ -92,11 +92,12 @@ namespace Oqtane.Infrastructure
|
|||
try
|
||||
{
|
||||
var notes = "";
|
||||
var tenants = scope.ServiceProvider.GetRequiredService<ITenantRepository>();
|
||||
var siteState = scope.ServiceProvider.GetRequiredService<SiteState>();
|
||||
foreach (var tenant in tenants.GetTenants())
|
||||
var tenantRepository = scope.ServiceProvider.GetRequiredService<ITenantRepository>();
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
|
||||
foreach (var tenant in tenantRepository.GetTenants())
|
||||
{
|
||||
siteState.Alias = new Alias { TenantId = tenant.TenantId };
|
||||
// set tenant and execute job
|
||||
tenantManager.SetTenant(tenant.TenantId);
|
||||
notes += ExecuteJob(scope.ServiceProvider);
|
||||
}
|
||||
log.Notes = notes;
|
||||
|
|
|
@ -14,18 +14,18 @@ namespace Oqtane.Infrastructure
|
|||
public class LogManager : ILogManager
|
||||
{
|
||||
private readonly ILogRepository _logs;
|
||||
private readonly ITenantResolver _tenantResolver;
|
||||
private readonly IConfigurationRoot _config;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public LogManager(ILogRepository logs, ITenantResolver tenantResolver, IConfigurationRoot config, IUserPermissions userPermissions, IHttpContextAccessor accessor)
|
||||
public LogManager(ILogRepository logs, ITenantManager tenantManager, IConfigurationRoot config, IUserPermissions userPermissions, IHttpContextAccessor accessor)
|
||||
{
|
||||
_logs = logs;
|
||||
_tenantResolver = tenantResolver;
|
||||
_config = config;
|
||||
_userPermissions = userPermissions;
|
||||
_accessor = accessor;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
public void Log(LogLevel level, object @class, LogFunction function, string message, params object[] args)
|
||||
|
@ -49,10 +49,9 @@ namespace Oqtane.Infrastructure
|
|||
if (siteId == -1)
|
||||
{
|
||||
log.SiteId = null;
|
||||
Alias alias = _tenantResolver.GetAlias();
|
||||
if (alias != null)
|
||||
if (_alias != null)
|
||||
{
|
||||
log.SiteId = alias.SiteId;
|
||||
log.SiteId = _alias.SiteId;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
41
Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs
Normal file
41
Oqtane.Server/Infrastructure/Middleware/TenantMiddleware.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
internal class TenantMiddleware
|
||||
{
|
||||
private readonly RequestDelegate next;
|
||||
|
||||
public TenantMiddleware(RequestDelegate next)
|
||||
{
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
// check if framework is installed
|
||||
var config = context.RequestServices.GetService(typeof(IConfiguration)) as IConfiguration;
|
||||
if (!string.IsNullOrEmpty(config.GetConnectionString("DefaultConnection")))
|
||||
{
|
||||
// get alias
|
||||
var tenantManager = context.RequestServices.GetService(typeof(ITenantManager)) as ITenantManager;
|
||||
var alias = tenantManager.GetAlias();
|
||||
|
||||
// rewrite path by removing alias path prefix from api and pages requests
|
||||
if (alias != null && !string.IsNullOrEmpty(alias.Path))
|
||||
{
|
||||
string path = context.Request.Path.ToString();
|
||||
if (path.StartsWith("/" + alias.Path) && (path.Contains("/api/") || path.Contains("/pages/")))
|
||||
{
|
||||
context.Request.Path = path.Replace("/" + alias.Path, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// continue processing
|
||||
if (next != null) await next(context);
|
||||
}
|
||||
}
|
||||
}
|
87
Oqtane.Server/Infrastructure/TenantManager.cs
Normal file
87
Oqtane.Server/Infrastructure/TenantManager.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
public class TenantManager : ITenantManager
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IAliasRepository _aliasRepository;
|
||||
private readonly ITenantRepository _tenantRepository;
|
||||
private readonly SiteState _siteState;
|
||||
|
||||
public TenantManager(IHttpContextAccessor httpContextAccessor, IAliasRepository aliasRepository, ITenantRepository tenantRepository, SiteState siteState)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_aliasRepository = aliasRepository;
|
||||
_tenantRepository = tenantRepository;
|
||||
_siteState = siteState;
|
||||
}
|
||||
|
||||
public Alias GetAlias()
|
||||
{
|
||||
Alias alias = null;
|
||||
|
||||
if (_siteState != null && _siteState.Alias != null)
|
||||
{
|
||||
alias = _siteState.Alias;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there is http context
|
||||
if (_httpContextAccessor.HttpContext != null)
|
||||
{
|
||||
// legacy support for client api requests which would include the alias as a path prefix ( ie. {alias}/api/[controller] )
|
||||
int aliasId;
|
||||
string[] segments = _httpContextAccessor.HttpContext.Request.Path.Value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (segments.Length > 1 && (segments[1] == "api" || segments[1] == "pages") && int.TryParse(segments[0], out aliasId))
|
||||
{
|
||||
alias = _aliasRepository.GetAliases().ToList().FirstOrDefault(item => item.AliasId == aliasId);
|
||||
}
|
||||
|
||||
// resolve alias based on host name and path
|
||||
if (alias == null)
|
||||
{
|
||||
string name = _httpContextAccessor.HttpContext.Request.Host.Value + _httpContextAccessor.HttpContext.Request.Path;
|
||||
alias = _aliasRepository.GetAlias(name);
|
||||
}
|
||||
|
||||
// if there is a match save it
|
||||
if (alias != null)
|
||||
{
|
||||
_siteState.Alias = alias;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
public Tenant GetTenant()
|
||||
{
|
||||
var alias = GetAlias();
|
||||
if (alias != null)
|
||||
{
|
||||
// return tenant details
|
||||
return _tenantRepository.GetTenants().ToList().FirstOrDefault(item => item.TenantId == alias.TenantId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetAlias(Alias alias)
|
||||
{
|
||||
// background processes can set the alias using the SiteState service
|
||||
_siteState.Alias = alias;
|
||||
}
|
||||
|
||||
public void SetTenant(int tenantId)
|
||||
{
|
||||
// background processes can set the alias using the SiteState service
|
||||
_siteState.Alias = new Alias { TenantId = tenantId };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,9 +27,9 @@ namespace Oqtane.Infrastructure
|
|||
// core framework upgrade logic - executed for every tenant
|
||||
using (var scope = _serviceScopeFactory.CreateScope())
|
||||
{
|
||||
// set SiteState based on tenant
|
||||
var siteState = scope.ServiceProvider.GetRequiredService<SiteState>();
|
||||
siteState.Alias = new Alias { TenantId = tenant.TenantId };
|
||||
// set tenant
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
|
||||
tenantManager.SetTenant(tenant.TenantId);
|
||||
|
||||
switch (version)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Modules.HtmlText.Models;
|
||||
using Oqtane.Modules.HtmlText.Repository;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Shared;
|
||||
|
@ -12,7 +11,7 @@ using Oqtane.Controllers;
|
|||
|
||||
namespace Oqtane.Modules.HtmlText.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.Default)]
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class HtmlTextController : ModuleControllerBase
|
||||
{
|
||||
private readonly IHtmlTextRepository _htmlText;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oqtane.Modules.HtmlText.Models;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Interfaces;
|
||||
using Oqtane.Repository.Databases.Interfaces;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
@ -12,7 +10,7 @@ namespace Oqtane.Modules.HtmlText.Repository
|
|||
{
|
||||
public class HtmlTextContext : DBContextBase, IService, IMultiDatabase
|
||||
{
|
||||
public HtmlTextContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver)
|
||||
public HtmlTextContext(IDbConfig dbConfig, ITenantManager tenantManager) : base(dbConfig, tenantManager)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
@page "/{alias}/pages/login"
|
||||
@page "/pages/login"
|
||||
@namespace Oqtane.Pages
|
||||
@model Oqtane.Pages.LoginModel
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
@page "/{alias}/pages/logout"
|
||||
@page "/pages/logout"
|
||||
@namespace Oqtane.Pages
|
||||
@model Oqtane.Pages.LogoutModel
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<body>
|
||||
@(Html.AntiForgeryToken())
|
||||
<app>
|
||||
<component type="typeof(Oqtane.App)" render-mode="Server" />
|
||||
<component type="typeof(Oqtane.App)" render-mode="ServerPrerendered" />
|
||||
</app>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
|
|
|
@ -8,7 +8,6 @@ using System;
|
|||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Oqtane.Repository;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
@ -18,21 +17,18 @@ namespace Oqtane.Pages
|
|||
public class HostModel : PageModel
|
||||
{
|
||||
private IConfiguration _configuration;
|
||||
private readonly SiteState _state;
|
||||
private readonly IAliasRepository _aliases;
|
||||
private readonly ITenantManager _tenantManager;
|
||||
private readonly ILocalizationManager _localizationManager;
|
||||
private readonly ILanguageRepository _languages;
|
||||
|
||||
public HostModel(
|
||||
IConfiguration configuration,
|
||||
SiteState state,
|
||||
IAliasRepository aliases,
|
||||
ITenantManager tenantManager,
|
||||
ILocalizationManager localizationManager,
|
||||
ILanguageRepository languages)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_state = state;
|
||||
_aliases = aliases;
|
||||
_tenantManager = tenantManager;
|
||||
_localizationManager = localizationManager;
|
||||
_languages = languages;
|
||||
}
|
||||
|
@ -54,19 +50,14 @@ namespace Oqtane.Pages
|
|||
// if culture not specified and framework is installed
|
||||
if (HttpContext.Request.Cookies[CookieRequestCultureProvider.DefaultCookieName] == null && !string.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection")))
|
||||
{
|
||||
var uri = new Uri(Request.GetDisplayUrl());
|
||||
var hostname = uri.Authority + "/" + uri.LocalPath.Substring(1);
|
||||
var alias = _aliases.GetAlias(hostname);
|
||||
var alias = _tenantManager.GetAlias();
|
||||
if (alias != null)
|
||||
{
|
||||
_state.Alias = alias;
|
||||
|
||||
// set default language for site if the culture is not supported
|
||||
var languages = _languages.GetLanguages(alias.SiteId);
|
||||
if (languages.Any() && languages.All(l => l.Code != CultureInfo.CurrentUICulture.Name))
|
||||
{
|
||||
var defaultLanguage = languages.Where(l => l.IsDefault).SingleOrDefault() ?? languages.First();
|
||||
|
||||
SetLocalizationCookie(defaultLanguage.Code);
|
||||
}
|
||||
else
|
||||
|
@ -74,10 +65,6 @@ namespace Oqtane.Pages
|
|||
SetLocalizationCookie(_localizationManager.GetDefaultCulture());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = $"No Matching Alias For Host Name {hostname}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,17 +55,28 @@ namespace Oqtane.Repository
|
|||
List<Alias> aliases = GetAliases().ToList();
|
||||
var segments = name.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// iterate segments in reverse order
|
||||
for (int i = segments.Length; i > 0; i--)
|
||||
// iterate segments to find keywords
|
||||
int start = segments.Length;
|
||||
for (int i = 0; i < segments.Length; i++)
|
||||
{
|
||||
name = string.Join("/", segments, 0, i);
|
||||
alias = aliases.Find(item => item.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
if (segments[i] == "api" || segments[i] == "pages" || segments[i] == "*")
|
||||
{
|
||||
start = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// iterate segments in reverse order to find alias match
|
||||
for (int i = start; i > 0; i--)
|
||||
{
|
||||
alias = aliases.Find(item => item.Name.Equals(string.Join("/", segments, 0, i), StringComparison.OrdinalIgnoreCase));
|
||||
if (alias != null)
|
||||
{
|
||||
break; // found a matching alias
|
||||
}
|
||||
}
|
||||
// return fallback alias
|
||||
|
||||
// return fallback alias if none found
|
||||
return alias ?? aliases.Find(item => item.Name.Equals("*"));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,10 @@ using Microsoft.EntityFrameworkCore;
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Oqtane.Extensions;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Interfaces;
|
||||
using Oqtane.Migrations.Framework;
|
||||
using Oqtane.Repository.Databases.Interfaces;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
|
||||
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
||||
|
@ -20,26 +21,27 @@ namespace Oqtane.Repository
|
|||
public class DBContextBase : IdentityUserContext<IdentityUser>
|
||||
{
|
||||
private readonly ITenantResolver _tenantResolver;
|
||||
private readonly ITenantManager _tenantManager;
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly IConfiguration _configuration;
|
||||
private string _connectionString;
|
||||
private string _databaseType;
|
||||
|
||||
public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor httpContextAccessor)
|
||||
public DBContextBase(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_connectionString = String.Empty;
|
||||
_tenantResolver = tenantResolver;
|
||||
_tenantManager = tenantManager;
|
||||
_accessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public DBContextBase(IDbConfig dbConfig, ITenantResolver tenantResolver)
|
||||
public DBContextBase(IDbConfig dbConfig, ITenantManager tenantManager)
|
||||
{
|
||||
_accessor = dbConfig.Accessor;
|
||||
_configuration = dbConfig.Configuration;
|
||||
_connectionString = dbConfig.ConnectionString;
|
||||
_databaseType = dbConfig.DatabaseType;
|
||||
Databases = dbConfig.Databases;
|
||||
_tenantResolver = tenantResolver;
|
||||
_tenantManager = tenantManager;
|
||||
}
|
||||
|
||||
public IEnumerable<IOqtaneDatabase> Databases { get; }
|
||||
|
@ -48,9 +50,18 @@ namespace Oqtane.Repository
|
|||
{
|
||||
optionsBuilder.ReplaceService<IMigrationsAssembly, MultiDatabaseMigrationsAssembly>();
|
||||
|
||||
if (string.IsNullOrEmpty(_connectionString) && _tenantResolver != null)
|
||||
if (string.IsNullOrEmpty(_connectionString))
|
||||
{
|
||||
var tenant = _tenantResolver.GetTenant();
|
||||
|
||||
Tenant tenant;
|
||||
if (_tenantResolver != null)
|
||||
{
|
||||
tenant = _tenantResolver.GetTenant();
|
||||
}
|
||||
else
|
||||
{
|
||||
tenant = _tenantManager.GetTenant();
|
||||
}
|
||||
|
||||
if (tenant != null)
|
||||
{
|
||||
|
@ -103,5 +114,25 @@ namespace Oqtane.Repository
|
|||
|
||||
return base.SaveChanges();
|
||||
}
|
||||
|
||||
[Obsolete("This constructor is obsolete. Use DBContextBase(ITenantManager tenantManager, IHttpContextAccessor httpContextAccessor) instead.", false)]
|
||||
public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_connectionString = String.Empty;
|
||||
_tenantResolver = tenantResolver;
|
||||
_accessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
[Obsolete("This constructor is obsolete. Use DBContextBase(IDbConfig dbConfig, ITenantManager tenantManager) instead.", false)]
|
||||
public DBContextBase(IDbConfig dbConfig, ITenantResolver tenantResolver)
|
||||
{
|
||||
_accessor = dbConfig.Accessor;
|
||||
_configuration = dbConfig.Configuration;
|
||||
_connectionString = dbConfig.ConnectionString;
|
||||
_databaseType = dbConfig.DatabaseType;
|
||||
Databases = dbConfig.Databases;
|
||||
_tenantResolver = tenantResolver;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oqtane.Interfaces;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Repository.Databases.Interfaces;
|
||||
|
||||
|
@ -12,7 +11,7 @@ namespace Oqtane.Repository
|
|||
{
|
||||
public class TenantDBContext : DBContextBase, IMultiDatabase
|
||||
{
|
||||
public TenantDBContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver) { }
|
||||
public TenantDBContext(IDbConfig dbConfig, ITenantManager tenantManager) : base(dbConfig, tenantManager) { }
|
||||
|
||||
public virtual DbSet<Site> Site { get; set; }
|
||||
public virtual DbSet<Page> Page { get; set; }
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
// class deprecated and replaced by ITenantManager
|
||||
public interface ITenantResolver
|
||||
{
|
||||
Alias GetAlias();
|
||||
|
|
|
@ -1,78 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
// class deprecated and replaced by ITenantManager
|
||||
public class TenantResolver : ITenantResolver
|
||||
{
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly IAliasRepository _aliasRepository;
|
||||
private readonly ITenantRepository _tenantRepository;
|
||||
private readonly SiteState _siteState;
|
||||
private readonly ITenantManager _tenantManager;
|
||||
|
||||
private Alias _alias;
|
||||
private Tenant _tenant;
|
||||
|
||||
public TenantResolver(IHttpContextAccessor accessor, IAliasRepository aliasRepository, ITenantRepository tenantRepository, SiteState siteState)
|
||||
public TenantResolver(ITenantManager tenantManager)
|
||||
{
|
||||
_accessor = accessor;
|
||||
_aliasRepository = aliasRepository;
|
||||
_tenantRepository = tenantRepository;
|
||||
_siteState = siteState;
|
||||
_tenantManager = tenantManager;
|
||||
}
|
||||
|
||||
public Alias GetAlias()
|
||||
{
|
||||
if (_alias == null) ResolveTenant();
|
||||
return _alias;
|
||||
return _tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
public Tenant GetTenant()
|
||||
{
|
||||
if (_tenant == null) ResolveTenant();
|
||||
return _tenant;
|
||||
}
|
||||
|
||||
private void ResolveTenant()
|
||||
{
|
||||
if (_siteState != null && _siteState.Alias != null)
|
||||
{
|
||||
// background processes can pass in an alias using the SiteState service
|
||||
_alias = _siteState.Alias;
|
||||
}
|
||||
else
|
||||
{
|
||||
int aliasId = -1;
|
||||
|
||||
// get aliasid identifier based on request
|
||||
if (_accessor.HttpContext != null)
|
||||
{
|
||||
string[] segments = _accessor.HttpContext.Request.Path.Value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (segments.Length > 1 && (segments[1] == "api" || segments[1] == "pages") && segments[0] != "~")
|
||||
{
|
||||
aliasId = int.Parse(segments[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// get the alias
|
||||
IEnumerable<Alias> aliases = _aliasRepository.GetAliases().ToList(); // cached
|
||||
if (aliasId != -1)
|
||||
{
|
||||
_alias = aliases.FirstOrDefault(item => item.AliasId == aliasId);
|
||||
}
|
||||
}
|
||||
|
||||
if (_alias != null)
|
||||
{
|
||||
// get the tenant
|
||||
IEnumerable<Tenant> tenants = _tenantRepository.GetTenants(); // cached
|
||||
_tenant = tenants.FirstOrDefault(item => item.TenantId == _alias.TenantId);
|
||||
}
|
||||
|
||||
return _tenantManager.GetTenant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
@ -10,7 +9,6 @@ using Microsoft.AspNetCore.Components;
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
@ -126,6 +124,7 @@ namespace Oqtane
|
|||
services.AddScoped<ISystemService, SystemService>();
|
||||
services.AddScoped<ILocalizationService, LocalizationService>();
|
||||
services.AddScoped<ILanguageService, LanguageService>();
|
||||
services.AddScoped<IDatabaseService, DatabaseService>();
|
||||
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
|
||||
|
@ -175,13 +174,13 @@ namespace Oqtane
|
|||
services.AddSingleton<IDatabaseManager, DatabaseManager>();
|
||||
|
||||
// install any modules or themes ( this needs to occur BEFORE the assemblies are loaded into the app domain )
|
||||
InstallationManager.InstallPackages("Modules,Themes", _env.WebRootPath, _env.ContentRootPath);
|
||||
InstallationManager.InstallPackages("Modules,Themes,Packages", _env.WebRootPath, _env.ContentRootPath);
|
||||
|
||||
// register transient scoped core services
|
||||
services.AddTransient<ITenantManager, TenantManager>();
|
||||
services.AddTransient<IModuleDefinitionRepository, ModuleDefinitionRepository>();
|
||||
services.AddTransient<IThemeRepository, ThemeRepository>();
|
||||
services.AddTransient<IUserPermissions, UserPermissions>();
|
||||
services.AddTransient<ITenantResolver, TenantResolver>();
|
||||
services.AddTransient<IAliasRepository, AliasRepository>();
|
||||
services.AddTransient<ITenantRepository, TenantRepository>();
|
||||
services.AddTransient<ISiteRepository, SiteRepository>();
|
||||
|
@ -206,6 +205,8 @@ namespace Oqtane
|
|||
services.AddTransient<ISqlRepository, SqlRepository>();
|
||||
services.AddTransient<IUpgradeManager, UpgradeManager>();
|
||||
services.AddTransient<ILanguageRepository, LanguageRepository>();
|
||||
// obsolete - replaced by ITenantManager
|
||||
services.AddTransient<ITenantResolver, TenantResolver>();
|
||||
|
||||
// load the external assemblies into the app domain, install services
|
||||
services.AddOqtane(_runtime, _supportedCultures);
|
||||
|
@ -240,7 +241,8 @@ namespace Oqtane
|
|||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
// to allow install middleware it should be moved up
|
||||
|
||||
// execute any IServerStartup logic
|
||||
app.ConfigureOqtaneAssemblies(env);
|
||||
|
||||
// Allow oqtane localization middleware
|
||||
|
@ -248,6 +250,7 @@ namespace Oqtane
|
|||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
app.UseTenantResolution(); // must be declared directly after static files
|
||||
app.UseBlazorFrameworkFiles();
|
||||
app.UseRouting();
|
||||
app.UseAuthentication();
|
||||
|
@ -255,7 +258,7 @@ namespace Oqtane
|
|||
if (_useSwagger)
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Oqtane V1"); });
|
||||
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Oqtane " + Constants.Version); });
|
||||
}
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/* Module Custom Styles */
|
|
@ -1 +0,0 @@
|
|||
/* Module Script */
|
|
@ -1 +0,0 @@
|
|||
["\\bin\\Debug\\net5.0\\Oqtane.Blogs.Client.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Client.Oqtane.pdb","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Server.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Server.Oqtane.pdb","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Shared.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Shared.Oqtane.pdb","\\wwwroot\\Modules\\Oqtane.Blogs\\Module.css","\\wwwroot\\Modules\\Oqtane.Blogs\\Module.js"]
|
|
@ -1,9 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Oqtane.Shared {
|
||||
namespace Oqtane.Shared {
|
||||
public class ControllerRoutes {
|
||||
public const string Default = "{alias}/api/[controller]";
|
||||
public const string ApiRoute = "api/[controller]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
@ -102,7 +102,7 @@ namespace Oqtane.Shared
|
|||
|
||||
public static string ContentUrl(Alias alias, int fileId, bool asAttachment)
|
||||
{
|
||||
var aliasUrl = (alias == null) ? "/~" : "/" + alias.AliasId;
|
||||
var aliasUrl = (alias != null && !string.IsNullOrEmpty(alias.Path)) ? "/" + alias.Path : "";
|
||||
var method = asAttachment ? "/attach":"";
|
||||
|
||||
return $"{aliasUrl}{Constants.ContentUrl}{fileId}{method}";
|
||||
|
|
11
README.md
11
README.md
|
@ -49,9 +49,16 @@ There is a separate [Documentation repository](https://github.com/oqtane/oqtane.
|
|||
# Roadmap
|
||||
This project is a work in progress and the schedule for implementing enhancements is dependent upon the availability of community members who are willing/able to assist.
|
||||
|
||||
V.3.0.0 ( Nov 2021 )
|
||||
- [ ] Migration to .NET 6
|
||||
|
||||
V.2.2.0 ( Aug 2021 )
|
||||
- [ ] Alternate Authentication Providers ( ie. Azure B2C, Social logins, etc... )
|
||||
- [ ] Configurable password complexity for local authentication
|
||||
|
||||
V.2.1.0 ( May 2021 )
|
||||
- [ ] Cross Platform Database Support ( ie. SQLite ) - see [#964](https://github.com/oqtane/oqtane.framework/discussions/964)
|
||||
- [ ] EF Core Migrations for Database Installation/Upgrade - see [#964](https://github.com/oqtane/oqtane.framework/discussions/964)
|
||||
- [ ] Cross Platform Database Support ( ie. SQLite, MySQL, PostreSQL ) - see [#964](https://github.com/oqtane/oqtane.framework/discussions/964)
|
||||
- [ ] EF Core Migrations - see [#964](https://github.com/oqtane/oqtane.framework/discussions/964)
|
||||
|
||||
V.2.0.2 ( Apr 19, 2021 )
|
||||
- [x] Assorted fixes and user experience improvements
|
||||
|
|
Loading…
Reference in New Issue
Block a user