Compare commits

..

67 Commits

Author SHA1 Message Date
ec0a5377b3 Merge pull request #2784 from oqtane/master
Merge pull request #2783 from oqtane/dev
2023-05-03 14:59:27 -04:00
b876da069d Merge pull request #2783 from oqtane/dev
3.4.3 release
2023-05-03 14:59:09 -04:00
f06063d7eb Merge pull request #2782 from sbwalker/dev
fix #2763 - prevent module definitions from having duplicate names
2023-05-03 12:46:44 -04:00
c6ba4f4bee fix #2763 - prevent module definitions from having duplicate names 2023-05-03 12:46:29 -04:00
89da4ab2a1 Merge pull request #2781 from sbwalker/dev
add defensive logic in case list of pages is empty
2023-05-03 12:32:44 -04:00
99ac0a3cab add defensive logic in case list of pages is empty 2023-05-03 12:32:28 -04:00
a964c30705 Merge pull request #2776 from thabaum/patch-24
Updated Dashboard Index
2023-05-03 12:27:32 -04:00
2334d0297d Merge pull request #2780 from sbwalker/dev
fix #2777 - module rendering order within pane - moved default module ordering logic to server API for consistency and better performance
2023-05-03 12:26:17 -04:00
e444c6bcf0 fix #2777 - module rendering order within pane - moved default module ordering logic to server API for consistency and better performance 2023-05-03 12:25:52 -04:00
601582fc98 Update Index.razor 2023-05-03 08:19:24 -07:00
e939dbe24e Updated SecurityAccessLevel.Admin 2023-05-02 17:14:46 -07:00
143ad85fd5 Update README.md 2023-05-02 16:00:23 -04:00
20377e9789 Merge pull request #2775 from sbwalker/dev
prepare for 3.4.3 release
2023-05-02 15:54:49 -04:00
e4a24df7b4 prepare for 3.4.3 release 2023-05-02 15:54:36 -04:00
e88ca00658 Merge pull request #2770 from thabaum/patch-23
Remove Admin Page/Module Registered User View
2023-05-02 15:41:27 -04:00
2312c612d7 Merge pull request #2774 from sbwalker/dev
remove message items as these are handled by MessageType enum and UX styles
2023-05-02 15:14:34 -04:00
3aee52482d remove message items as these are handled by MessageType enum and UX styles 2023-05-02 15:14:17 -04:00
32248e0be6 Merge pull request #2745 from thabaum/patch-18
Add support for new language translation values for #2732.
2023-05-02 15:05:36 -04:00
6c18c320bd Merge pull request #2773 from sbwalker/dev
fixed compilation error and improved UTF8 support
2023-05-02 15:03:43 -04:00
e31f32e5aa fixed compilation error and improved UTF8 support 2023-05-02 15:03:26 -04:00
a856390566 Merge pull request #2772 from sbwalker/dev
improve module/theme/translation upload user experience to be consistent with download
2023-05-02 14:22:56 -04:00
64b8291487 improve module/theme/translation upload user experience to be consistent with download 2023-05-02 14:22:34 -04:00
2ebd1310c9 Merge pull request #2747 from thabaum/patch-19
Add content-type to sitemap: Fixes issues 2749 2764
2023-05-02 14:20:39 -04:00
09118fcb42 Updates lastmod date 2023-05-02 07:15:22 -07:00
5d5167abbc Merge pull request #2771 from vnetonline/dev
Invalid template when I try and use the Deploy to Azure button
2023-05-02 09:01:41 -04:00
bf43dea060 Merge branch 'oqtane:dev' into dev 2023-05-02 15:53:56 +10:00
6ebab830c5 Invalid template when I try and use the Deploy to Azure button
1. removed depends on connection strings
2. Moved sku outside properties for type Microsoft.Web/serverfarms and added various app plans
3. Removed worker size and replaced with instance capacity
4. Replaced database and sqlserver to use various editions
5. Updated ApiVersions for various types
2023-05-02 15:47:31 +10:00
9a9a78e0bd Remove Admin Page/Module Registered User View 2023-05-01 20:01:49 -07:00
418eff7d21 Merge pull request #2754 from pepsinio/dev
Add ability to use environment variables in order to set them as app settings in Azure
2023-05-01 16:14:47 -04:00
d39869ca8e Merge pull request #2759 from leigh-pointer/MenuHorizontal#2757
Fix for MenuHorizontal #2757
2023-05-01 16:14:16 -04:00
7829168ea7 Merge pull request #2768 from sbwalker/dev
fix #2761 - updating Module Definition name, description, category not invalidating cache
2023-05-01 15:38:46 -04:00
dd83e3ee67 fix #2761 - updating Module Definition name, description, category not invalidating cache 2023-05-01 15:38:18 -04:00
c3ac0e365d Removed PR comments 2023-04-27 16:32:48 -07:00
2986625605 Update content type to XML and include UTF-8 2023-04-27 16:22:35 -07:00
8beaeabf09 Include utf-8 encoding. 2023-04-27 16:21:14 -07:00
fa9b4b6112 Fix for MenuHorizontal #2757
Add the css class to MenuHorizontal to handle scrolling when hamburger Menu is in use.
2023-04-26 09:43:11 +02:00
d81fbe4585 Fixed missing logic from PR 2023-04-19 10:18:27 -07:00
536c044139 Add environment settings needed for Azure deployment 2023-04-19 19:18:19 +02:00
376531195e Add environment settings needed for Azure deployment 2023-04-19 19:17:33 +02:00
abf4ff71d7 re-add missing settings 2023-04-19 10:13:31 -07:00
d25debcea3 cleanup using 2023-04-19 10:11:16 -07:00
948c186cb5 fixed formatting 2023-04-19 10:09:00 -07:00
ba27e70fe3 Removed unnecessary cache comments. 2023-04-19 10:05:43 -07:00
c93d2576af Updates content-type to "application/xml"
removes sitemap cache from previous commits.
2023-04-19 10:00:33 -07:00
e0b0156640 allow module and theme dependencies setting to include .dll file extension, added testmode config setting for validating list of assemblies sent to client 2023-04-19 08:48:52 -07:00
a3ca6a3071 Merge pull request #2753 from sbwalker/dev
allow module and theme dependencies setting to include .dll file extension, added testmode config setting for validating list of assemblies sent to client
2023-04-19 08:46:12 -07:00
b20157450b Add caching and content-type 2023-04-14 18:08:39 -07:00
7e4f0923d7 Add support for new language translation values. 2023-04-13 07:42:04 -07:00
e0c2b2982f improvements to #2736 to support scenarios where module is not explicitly assigned to a page 2023-04-11 13:01:34 -04:00
9a231c28af Merge pull request #2742 from sbwalker/dev
improvements to #2736 to support scenarios where module is not explicitly assigned to a page
2023-04-11 12:59:33 -04:00
94a02b7bf9 add filter to exclude orphaned permissions 2023-04-11 10:35:23 -04:00
22c8fb411a Merge pull request #2741 from sbwalker/dev
add filter to exclude orphaned permissions
2023-04-11 10:33:09 -04:00
cf46210ff8 Merge pull request #2725 from thabaum/patch-17
Fixes null reference permissions issue: Fixes #2724
2023-04-11 10:22:08 -04:00
f32d988297 Merge pull request #2740 from sbwalker/dev
Routes with Module ID and no Action can be displayed on any page regardless of whether a PageModule record exists (ie. Admin Dashboard)
2023-04-11 10:19:28 -04:00
7fe4577158 Routes with Module ID and no Action can be displayed on any page regardless of whether a PageModule record exists (ie. Admin Dashboard) 2023-04-11 10:21:37 -04:00
8985dcb4c0 fix #2736 - UI not loading correct module instance in scenarios where a module exists on multiple pages 2023-04-10 08:37:35 -04:00
d346444c51 Merge pull request #2739 from sbwalker/dev
fix #2736 - UI not loading correct module instance in scenarios where a module exists on multiple pages
2023-04-10 08:35:42 -04:00
ef27a0d6b0 Merge pull request #2727 from leigh-pointer/ModulePassSettings
Fix for #2718 SiteMap functionality missing Settings
2023-04-05 10:53:09 -04:00
627158cb5d Merge pull request #2729 from leigh-pointer/PwdControlCancelFocus
Fix for #2728 Toggle Password button focus
2023-04-05 10:51:27 -04:00
648edcabba Merge pull request #2731 from sbwalker/dev
fix #2720 - module definition permissions not being created properly for new sites
2023-04-05 10:27:44 -04:00
0f34c6efc5 fix #2720 - module definition permissions not being created properly for new sites 2023-04-05 10:29:51 -04:00
cc3cc55269 consolidated package installation so that it always occurs during startup and added logging in case of errors 2023-04-05 10:26:21 -04:00
a503a9d5bc Merge pull request #2730 from sbwalker/dev
consolidated package installation so that it always occurs during startup and added logging in case of errors
2023-04-05 10:24:15 -04:00
789baf99ff Fix for #2728 Toggle Password button focus
Added  tabindex="-1" to the Button control so that focus is not received and passed the the following control.
2023-04-05 07:51:32 +02:00
036279a54c Fix for #2718 SiteMap functionality missing Settings
Added the Module Settings to the Module parameter passed in the GetUrls interface call,
2023-04-05 07:31:57 +02:00
481f18cf1c Fixes null reference permissions issue 2023-04-04 11:19:25 -07:00
2f1e386554 Update README.md 2023-03-29 14:13:27 -04:00
71 changed files with 870 additions and 838 deletions

View File

@ -77,7 +77,7 @@
<div class="col-sm-9">
<div class="input-group">
<input id="password" type="@_passwordType" class="form-control" @bind="@_hostPassword" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglePassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglePassword</button>
</div>
</div>
</div>
@ -86,7 +86,7 @@
<div class="col-sm-9">
<div class="input-group">
<input id="confirm" type="@_confirmPasswordType" class="form-control" @bind="@_confirmPassword" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@ToggleConfirmPassword">@_toggleConfirmPassword</button>
<button type="button" class="btn btn-secondary" @onclick="@ToggleConfirmPassword" tabindex="-1">@_toggleConfirmPassword</button>
</div>
</div>
</div>

View File

@ -4,32 +4,35 @@
@inject IUserService UserService
@inject IStringLocalizer<SharedResources> SharedLocalizer
<div class="row">
@foreach (var p in _pages)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
@if (_pages != null)
{
<div class="row">
@foreach (var p in _pages)
{
string url = NavigateUrl(p.Path);
<div class="col-md-2 mx-auto text-center mb-3">
<NavLink class="nav-link text-primary" href="@url" Match="NavLinkMatch.All">
<h2><span class="@p.Icon" aria-hidden="true"></span></h2>@SharedLocalizer[p.Name]
</NavLink>
</div>
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
{
string url = NavigateUrl(p.Path);
<div class="col-md-2 mx-auto text-center mb-3">
<NavLink class="nav-link text-primary" href="@url" Match="NavLinkMatch.All">
<h2><span class="@p.Icon" aria-hidden="true"></span></h2>@SharedLocalizer[p.Name]
</NavLink>
</div>
}
}
}
</div>
</div>
}
@code {
private List<Page> _pages;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
protected override void OnInitialized()
{
var admin = PageState.Pages.FirstOrDefault(item => item.Path == "admin");
if (admin != null)
{
_pages = PageState.Pages.Where(item => item.ParentId == admin?.PageId).ToList();
_pages = PageState.Pages.Where(item => item.ParentId == admin.PageId).ToList();
}
}
}

View File

@ -48,13 +48,12 @@ else
<TabPanel Name="Upload" ResourceKey="Upload" Security="SecurityAccessLevel.Host">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" HelpText="Upload one or more translations. Once they are uploaded click Install to complete the installation." ResourceKey="LanguageUpload">Translation: </Label>
<Label Class="col-sm-3" HelpText="Upload one or more translations. Once they are uploaded click Install." ResourceKey="LanguageUpload">Translation: </Label>
<div class="col-sm-9">
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" />
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" OnUpload="OnUpload" />
</div>
</div>
</div>
<button type="button" class="btn btn-success" @onclick="InstallTranslations">@SharedLocalizer["Install"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
</TabPanel>
</TabStrip>
@ -119,24 +118,11 @@ else
AddModuleMessage(Localizer["Error.Language.Add"], MessageType.Error);
}
}
else
{
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
}
}
private async Task InstallTranslations()
{
try
{
await PackageService.InstallPackagesAsync();
AddModuleMessage(string.Format(Localizer["Success.Language.Install"], NavigateUrl("admin/system")), MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Installing Translations");
}
}
else
{
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
}
}
private async Task SetCultureAsync(string culture)
{
@ -149,4 +135,9 @@ else
NavigationManager.NavigateTo(NavigationManager.Uri, true);
}
}
private void OnUpload()
{
AddModuleMessage(string.Format(Localizer["Success.Language.Download"], NavigateUrl("admin/system")), MessageType.Success);
}
}

View File

@ -56,10 +56,6 @@ else
}
</Row>
</Pager>
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && _install)
{
<button type="button" class="btn btn-success" @onclick="InstallTranslations">@SharedLocalizer["Install"]</button>
}
}
@if (_package != null)
@ -106,7 +102,6 @@ else
private List<Language> _languages;
private List<Package> _packages;
private Package _package;
private bool _install = false;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
@ -167,9 +162,8 @@ else
{
await PackageService.DownloadPackageAsync(_package.PackageId, _package.Version, Constants.PackagesFolder);
await logger.LogInformation("Language Package {Name} {Version} Downloaded Successfully", _package.PackageId, _package.Version);
AddModuleMessage(Localizer["Success.Language.Download"], MessageType.Success);
AddModuleMessage(string.Format(Localizer["Success.Language.Download"], NavigateUrl("admin/system")), MessageType.Success);
_package = null;
_install = true;
StateHasChanged();
}
catch (Exception ex)
@ -184,19 +178,4 @@ else
_package = null;
StateHasChanged();
}
private async Task InstallTranslations()
{
try
{
await PackageService.InstallPackagesAsync();
AddModuleMessage(string.Format(Localizer["Success.Language.Install"], NavigateUrl("admin/system")), MessageType.Success);
_install = false;
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Installing Translations");
}
}
}

View File

@ -34,7 +34,7 @@
<Label Class="control-label" For="password" HelpText="Please enter your Password" ResourceKey="Password">Password:</Label>
<div class="input-group">
<input id="password" type="@_passwordtype" name="Password" class="form-control" placeholder="@Localizer["Password.Placeholder"]" @bind="@_password" required />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
<div class="form-group mt-2">

View File

@ -65,13 +65,15 @@
</div>
}
}
<br />
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
</TabPanel>
<TabPanel Name="Upload" ResourceKey="Upload">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Module: </Label>
<div class="col-sm-9">
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" />
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" OnUpload="OnUpload" />
</div>
</div>
</div>
@ -111,153 +113,140 @@
</div>
}
<button type="button" class="btn btn-success" @onclick="InstallModules">@SharedLocalizer["Install"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
<br />
<br />
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
@code {
private List<Package> _packages;
private string _price = "free";
private string _search = "";
private string _productname = "";
private string _packageid = "";
private string _packagelicense = "";
private string _packageversion = "";
private List<Package> _packages;
private string _price = "free";
private string _search = "";
private string _productname = "";
private string _packageid = "";
private string _packagelicense = "";
private string _packageversion = "";
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnInitializedAsync()
{
try
{
await LoadModuleDefinitions();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Packages {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Package.Load"], MessageType.Error);
}
}
protected override async Task OnInitializedAsync()
{
try
{
await LoadModuleDefinitions();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Packages {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Package.Load"], MessageType.Error);
}
}
private async Task LoadModuleDefinitions()
{
var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
_packages = await PackageService.GetPackagesAsync("module", _search, _price, "");
private async Task LoadModuleDefinitions()
{
var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
_packages = await PackageService.GetPackagesAsync("module", _search, _price, "");
if (_packages != null)
{
foreach (Package package in _packages.ToArray())
{
if (moduledefinitions.Exists(item => item.PackageName == package.PackageId))
{
_packages.Remove(package);
}
}
}
}
if (_packages != null)
{
foreach (Package package in _packages.ToArray())
{
if (moduledefinitions.Exists(item => item.PackageName == package.PackageId))
{
_packages.Remove(package);
}
}
}
}
private async void PriceChanged(ChangeEventArgs e)
{
try
{
_price = (string)e.Value;
_search = "";
await LoadModuleDefinitions();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On PriceChanged");
}
}
private async void PriceChanged(ChangeEventArgs e)
{
try
{
_price = (string)e.Value;
_search = "";
await LoadModuleDefinitions();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On PriceChanged");
}
}
private async Task Search()
{
try
{
await LoadModuleDefinitions();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On Search");
}
}
private async Task Search()
{
try
{
await LoadModuleDefinitions();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On Search");
}
}
private async Task Reset()
{
try
{
_search = "";
await LoadModuleDefinitions();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On Reset");
}
}
private async Task Reset()
{
try
{
_search = "";
await LoadModuleDefinitions();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On Reset");
}
}
private void HideModal()
{
_productname = "";
_packagelicense = "";
StateHasChanged();
}
private void HideModal()
{
_productname = "";
_packagelicense = "";
StateHasChanged();
}
private async Task GetPackage(string packageid, string version)
{
try
{
var package = await PackageService.GetPackageAsync(packageid, version);
if (package != null)
{
_productname = package.Name;
_packageid = package.PackageId;
if (!string.IsNullOrEmpty(package.License))
{
_packagelicense = package.License.Replace("\n", "<br />");
}
_packageversion = package.Version;
}
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
}
}
private async Task GetPackage(string packageid, string version)
{
try
{
var package = await PackageService.GetPackageAsync(packageid, version);
if (package != null)
{
_productname = package.Name;
_packageid = package.PackageId;
if (!string.IsNullOrEmpty(package.License))
{
_packagelicense = package.License.Replace("\n", "<br />");
}
_packageversion = package.Version;
}
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
}
}
private async Task DownloadPackage()
{
try
{
await PackageService.DownloadPackageAsync(_packageid, _packageversion, Constants.PackagesFolder);
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _packageversion);
AddModuleMessage(Localizer["Success.Module.Download"], MessageType.Success);
_productname = "";
_packagelicense = "";
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _packageversion);
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
}
}
private async Task DownloadPackage()
{
try
{
await PackageService.DownloadPackageAsync(_packageid, _packageversion, Constants.PackagesFolder);
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _packageversion);
AddModuleMessage(string.Format(Localizer["Success.Module.Download"], NavigateUrl("admin/system")), MessageType.Success);
_productname = "";
_packagelicense = "";
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _packageversion);
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
}
}
private async Task InstallModules()
{
try
{
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Installing Modules");
}
}
private void OnUpload()
{
AddModuleMessage(string.Format(Localizer["Success.Module.Download"], NavigateUrl("admin/system")), MessageType.Success);
}
}

View File

@ -131,10 +131,6 @@
</td>
</Row>
</Pager>
@if (_install)
{
<button type="button" class="btn btn-success" @onclick="InstallTranslations">@SharedLocalizer["Install"]</button>
}
}
else
{
@ -196,114 +192,121 @@
}
@code {
private bool _initialized = false;
private ElementReference form;
private bool validated = false;
private int _moduleDefinitionId;
private string _name;
private string _description = "";
private string _categories;
private string _moduledefinitionname = "";
private string _version;
private string _packagename = "";
private string _owner = "";
private string _url = "";
private string _contact = "";
private string _license = "";
private string _runtimes = "";
private List<Permission> _permissions = null;
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
private bool _initialized = false;
private ElementReference form;
private bool validated = false;
private int _moduleDefinitionId;
private string _name;
private string _description = "";
private string _categories;
private string _moduledefinitionname = "";
private string _version;
private string _packagename = "";
private string _owner = "";
private string _url = "";
private string _contact = "";
private string _license = "";
private string _runtimes = "";
private List<Permission> _permissions = null;
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
#pragma warning disable 649
private PermissionGrid _permissionGrid;
private PermissionGrid _permissionGrid;
#pragma warning restore 649
private List<Package> _packages;
private List<Language> _languages;
private Package _package;
private bool _install = false;
private List<Package> _packages;
private List<Language> _languages;
private Package _package;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
protected override async Task OnInitializedAsync()
{
try
{
_moduleDefinitionId = Int32.Parse(PageState.QueryString["id"]);
var moduleDefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
if (moduleDefinition != null)
{
_name = moduleDefinition.Name;
_description = moduleDefinition.Description;
_categories = moduleDefinition.Categories;
_moduledefinitionname = moduleDefinition.ModuleDefinitionName;
_version = moduleDefinition.Version;
_packagename = moduleDefinition.PackageName;
_owner = moduleDefinition.Owner;
_url = moduleDefinition.Url;
_contact = moduleDefinition.Contact;
_license = moduleDefinition.License;
_runtimes = moduleDefinition.Runtimes;
_permissions = moduleDefinition.PermissionList;
_createdby = moduleDefinition.CreatedBy;
_createdon = moduleDefinition.CreatedOn;
_modifiedby = moduleDefinition.ModifiedBy;
_modifiedon = moduleDefinition.ModifiedOn;
protected override async Task OnInitializedAsync()
{
try
{
_moduleDefinitionId = Int32.Parse(PageState.QueryString["id"]);
var moduleDefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
if (moduleDefinition != null)
{
_name = moduleDefinition.Name;
_description = moduleDefinition.Description;
_categories = moduleDefinition.Categories;
_moduledefinitionname = moduleDefinition.ModuleDefinitionName;
_version = moduleDefinition.Version;
_packagename = moduleDefinition.PackageName;
_owner = moduleDefinition.Owner;
_url = moduleDefinition.Url;
_contact = moduleDefinition.Contact;
_license = moduleDefinition.License;
_runtimes = moduleDefinition.Runtimes;
_permissions = moduleDefinition.PermissionList;
_createdby = moduleDefinition.CreatedBy;
_createdon = moduleDefinition.CreatedOn;
_modifiedby = moduleDefinition.ModifiedBy;
_modifiedon = moduleDefinition.ModifiedOn;
if (!string.IsNullOrEmpty(_packagename))
{
_packages = await PackageService.GetPackagesAsync("translation", "", "", _packagename);
_languages = await LanguageService.GetLanguagesAsync(-1, _packagename);
foreach (var package in _packages)
{
var code = package.PackageId.Split('.').Last();
if (!_languages.Any(item => item.Code == code))
{
_languages.Add(new Language { Code = code, Name = CultureInfo.GetCultureInfo(code).DisplayName, Version = package.Version, IsDefault = true });
}
}
_languages = _languages.OrderBy(item => item.Name).ToList();
}
if (!string.IsNullOrEmpty(_packagename))
{
_packages = await PackageService.GetPackagesAsync("translation", "", "", _packagename);
_languages = await LanguageService.GetLanguagesAsync(-1, _packagename);
foreach (var package in _packages)
{
var code = package.PackageId.Split('.').Last();
if (!_languages.Any(item => item.Code == code))
{
_languages.Add(new Language { Code = code, Name = CultureInfo.GetCultureInfo(code).DisplayName, Version = package.Version, IsDefault = true });
}
}
_languages = _languages.OrderBy(item => item.Name).ToList();
}
_initialized = true;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error);
}
}
_initialized = true;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error);
}
}
private async Task SaveModuleDefinition()
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{
try
{
var moduledefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
if (moduledefinition.Name != _name)
{
moduledefinition.Name = _name;
}
if (moduledefinition.Description != _description)
{
moduledefinition.Description = _description;
}
if (moduledefinition.Categories != _categories)
{
moduledefinition.Categories = _categories;
}
moduledefinition.PermissionList = _permissionGrid.GetPermissionList();
await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition);
await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition);
NavigationManager.NavigateTo(NavigateUrl());
}
private async Task SaveModuleDefinition()
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{
try
{
var moduleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
if (!moduleDefinitions.Any(item => item.Name.ToLower() == _name.ToLower() && item.ModuleDefinitionId != _moduleDefinitionId))
{
var moduledefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
if (moduledefinition.Name != _name)
{
moduledefinition.Name = _name;
}
if (moduledefinition.Description != _description)
{
moduledefinition.Description = _description;
}
if (moduledefinition.Categories != _categories)
{
moduledefinition.Categories = _categories;
}
moduledefinition.PermissionList = _permissionGrid.GetPermissionList();
await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition);
await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition);
NavigationManager.NavigateTo(NavigateUrl());
}
else
{
AddModuleMessage(Localizer["Message.DuplicateName"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
@ -366,9 +369,8 @@
{
await PackageService.DownloadPackageAsync(_package.PackageId, _package.Version, Constants.PackagesFolder);
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _package.PackageId, _package.Version);
AddModuleMessage(Localizer["Success.Translation.Download"], MessageType.Success);
AddModuleMessage(string.Format(Localizer["Success.Translation.Download"], NavigateUrl("admin/system")), MessageType.Success);
_package = null;
_install = true;
StateHasChanged();
}
catch (Exception ex)
@ -377,19 +379,4 @@
AddModuleMessage(Localizer["Error.Translation.Download"], MessageType.Error);
}
}
private async Task InstallTranslations()
{
try
{
await PackageService.InstallPackagesAsync();
AddModuleMessage(string.Format(Localizer["Success.Translation.Install"], NavigateUrl("admin/system")), MessageType.Success);
_install = false;
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Installing Translations");
}
}
}

View File

@ -149,7 +149,6 @@ else
{
await PackageService.DownloadPackageAsync(packagename, version, Constants.PackagesFolder);
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", packagename, version);
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
}
catch (Exception ex)

View File

@ -30,7 +30,7 @@
<div class="col-sm-9">
<div class="input-group">
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>
@ -39,7 +39,7 @@
<div class="col-sm-9">
<div class="input-group">
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>

View File

@ -18,7 +18,7 @@
<div class="col-sm-9">
<div class="input-group">
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>
@ -27,7 +27,7 @@
<div class="col-sm-9">
<div class="input-group">
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>

View File

@ -143,7 +143,7 @@
<div class="col-sm-9">
<div class="input-group">
<input id="password" type="@_smtppasswordtype" class="form-control" @bind="@_smtppassword" />
<button type="button" class="btn btn-secondary" @onclick="@ToggleSMTPPassword">@_togglesmtppassword</button>
<button type="button" class="btn btn-secondary" @onclick="@ToggleSMTPPassword" tabindex="-1">@_togglesmtppassword</button>
</div>
</div>
</div>

View File

@ -65,13 +65,15 @@
</div>
}
}
<br />
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
</TabPanel>
<TabPanel Name="Upload" ResourceKey="Upload">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation." ResourceKey="Theme">Theme: </Label>
<div class="col-sm-9">
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" />
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" OnUpload="OnUpload" />
</div>
</div>
</div>
@ -111,13 +113,8 @@
</div>
}
<button type="button" class="btn btn-success" @onclick="InstallThemes">@SharedLocalizer["Install"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
<br />
<br />
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
@code {
private List<Package> _packages;
private string _price = "free";
@ -236,7 +233,7 @@
{
await PackageService.DownloadPackageAsync(_packageid, _version, Constants.PackagesFolder);
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _version);
AddModuleMessage(Localizer["Success.Theme.Download"], MessageType.Success);
AddModuleMessage(string.Format(Localizer["Success.Theme.Download"], NavigateUrl("admin/system")), MessageType.Success);
_productname = "";
_license = "";
StateHasChanged();
@ -248,16 +245,8 @@
}
}
private async Task InstallThemes()
private void OnUpload()
{
try
{
await ThemeService.InstallThemesAsync();
AddModuleMessage(string.Format(Localizer["Success.Theme.Install"], NavigateUrl("admin/system")), MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Installing Theme");
}
AddModuleMessage(string.Format(Localizer["Success.Theme.Download"], NavigateUrl("admin/system")), MessageType.Success);
}
}

View File

@ -116,7 +116,6 @@ else
{
await PackageService.DownloadPackageAsync(packagename, version, Constants.PackagesFolder);
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", packagename, version);
await ThemeService.InstallThemesAsync();
AddModuleMessage(string.Format(Localizer["Success.Theme.Install"], NavigateUrl("admin/system")), MessageType.Success);
}
catch (Exception ex)

View File

@ -34,7 +34,7 @@ else
<div class="col-sm-9">
<div class="input-group">
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>
@ -43,7 +43,7 @@ else
<div class="col-sm-9">
<div class="input-group">
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>

View File

@ -23,7 +23,7 @@
<div class="col-sm-9">
<div class="input-group">
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>
@ -32,7 +32,7 @@
<div class="col-sm-9">
<div class="input-group">
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" required />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>

View File

@ -32,7 +32,7 @@ else
<div class="col-sm-9">
<div class="input-group">
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>
@ -41,7 +41,7 @@ else
<div class="col-sm-9">
<div class="input-group">
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
</div>

View File

@ -87,299 +87,306 @@
}
@code {
private bool _initialized = false;
private List<Folder> _folders;
private List<File> _files = new List<File>();
private string _fileinputid = string.Empty;
private string _progressinfoid = string.Empty;
private string _progressbarid = string.Empty;
private string _filter = "*";
private bool _haseditpermission = false;
private string _image = string.Empty;
private File _file = null;
private string _guid;
private string _message = string.Empty;
private MessageType _messagetype;
private bool _initialized = false;
private List<Folder> _folders;
private List<File> _files = new List<File>();
private string _fileinputid = string.Empty;
private string _progressinfoid = string.Empty;
private string _progressbarid = string.Empty;
private string _filter = "*";
private bool _haseditpermission = false;
private string _image = string.Empty;
private File _file = null;
private string _guid;
private string _message = string.Empty;
private MessageType _messagetype;
[Parameter]
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
[Parameter]
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
[Parameter]
public int FolderId { get; set; } = -1; // optional - for setting a specific default folder by folderid
[Parameter]
public int FolderId { get; set; } = -1; // optional - for setting a specific default folder by folderid
[Parameter]
public string Folder { get; set; } = ""; // optional - for setting a specific default folder by folder path
[Parameter]
public string Folder { get; set; } = ""; // optional - for setting a specific default folder by folder path
[Parameter]
public int FileId { get; set; } = -1; // optional - for selecting a specific file by default
[Parameter]
public int FileId { get; set; } = -1; // optional - for selecting a specific file by default
[Parameter]
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
[Parameter]
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
[Parameter]
public bool ShowFiles { get; set; } = true; // optional - for indicating whether a list of files should be displayed - default is true
[Parameter]
public bool ShowFiles { get; set; } = true; // optional - for indicating whether a list of files should be displayed - default is true
[Parameter]
public bool ShowUpload { get; set; } = true; // optional - for indicating whether a Upload controls should be displayed - default is true
[Parameter]
public bool ShowUpload { get; set; } = true; // optional - for indicating whether a Upload controls should be displayed - default is true
[Parameter]
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
[Parameter]
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
[Parameter]
public bool ShowImage { get; set; } = true; // optional - for indicating whether an image thumbnail should be displayed - default is true
[Parameter]
public bool ShowImage { get; set; } = true; // optional - for indicating whether an image thumbnail should be displayed - default is true
[Parameter]
public bool ShowSuccess { get; set; } = false; // optional - for indicating whether a success message should be displayed upon successful upload - default is false
[Parameter]
public bool ShowSuccess { get; set; } = false; // optional - for indicating whether a success message should be displayed upon successful upload - default is false
[Parameter]
public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
[Parameter]
public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
[Parameter]
public EventCallback<int> OnUpload { get; set; } // optional - executes a method in the calling component when a file is uploaded
[Parameter]
public EventCallback<int> OnUpload { get; set; } // optional - executes a method in the calling component when a file is uploaded
[Parameter]
public EventCallback<int> OnSelect { get; set; } // optional - executes a method in the calling component when a file is selected
[Parameter]
public EventCallback<int> OnSelect { get; set; } // optional - executes a method in the calling component when a file is selected
[Parameter]
public EventCallback<int> OnDelete { get; set; } // optional - executes a method in the calling component when a file is deleted
[Parameter]
public EventCallback<int> OnDelete { get; set; } // optional - executes a method in the calling component when a file is deleted
protected override async Task OnInitializedAsync()
{
// packages folder is a framework folder for uploading installable nuget packages
if (Folder == Constants.PackagesFolder)
{
ShowFiles = false;
ShowFolders = false;
Filter = "nupkg";
ShowSuccess = true;
}
protected override async Task OnInitializedAsync()
{
// packages folder is a framework folder for uploading installable nuget packages
if (Folder == Constants.PackagesFolder)
{
ShowFiles = false;
ShowFolders = false;
Filter = "nupkg";
ShowSuccess = true;
}
if (!ShowFiles)
{
ShowImage = false;
}
if (!ShowFiles)
{
ShowImage = false;
}
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
if (!string.IsNullOrEmpty(Folder) && Folder != Constants.PackagesFolder)
{
Folder folder = await FolderService.GetFolderAsync(ModuleState.SiteId, Folder);
if (folder != null)
{
FolderId = folder.FolderId;
}
else
{
FolderId = -1;
_message = "Folder Path " + Folder + "Does Not Exist";
_messagetype = MessageType.Error;
}
}
if (!string.IsNullOrEmpty(Folder) && Folder != Constants.PackagesFolder)
{
Folder folder = await FolderService.GetFolderAsync(ModuleState.SiteId, Folder);
if (folder != null)
{
FolderId = folder.FolderId;
}
else
{
FolderId = -1;
_message = "Folder Path " + Folder + "Does Not Exist";
_messagetype = MessageType.Error;
}
}
if (FileId != -1)
{
File file = await FileService.GetFileAsync(FileId);
if (file != null)
{
FolderId = file.FolderId;
await OnSelect.InvokeAsync(FileId);
}
else
{
FileId = -1; // file does not exist
_message = "FileId " + FileId.ToString() + "Does Not Exist";
_messagetype = MessageType.Error;
}
}
if (FileId != -1)
{
File file = await FileService.GetFileAsync(FileId);
if (file != null)
{
FolderId = file.FolderId;
await OnSelect.InvokeAsync(FileId);
}
else
{
FileId = -1; // file does not exist
_message = "FileId " + FileId.ToString() + "Does Not Exist";
_messagetype = MessageType.Error;
}
}
await SetImage();
await SetImage();
if (!string.IsNullOrEmpty(Filter))
{
_filter = "." + Filter.Replace(",", ",.");
}
if (!string.IsNullOrEmpty(Filter))
{
_filter = "." + Filter.Replace(",", ",.");
}
await GetFiles();
await GetFiles();
// create unique id for component
_guid = Guid.NewGuid().ToString("N");
_fileinputid = "FileInput_" + _guid;
_progressinfoid = "ProgressInfo_" + _guid;
_progressbarid = "ProgressBar_" + _guid;
// create unique id for component
_guid = Guid.NewGuid().ToString("N");
_fileinputid = "FileInput_" + _guid;
_progressinfoid = "ProgressInfo_" + _guid;
_progressbarid = "ProgressBar_" + _guid;
_initialized = true;
}
_initialized = true;
}
private async Task GetFiles()
{
_haseditpermission = false;
if (Folder == Constants.PackagesFolder)
{
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
_files = new List<File>();
}
else
{
Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
if (folder != null)
{
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.PermissionList);
_files = await FileService.GetFilesAsync(FolderId);
}
else
{
_haseditpermission = false;
_files = new List<File>();
}
}
if (_filter != "*")
{
List<File> filtered = new List<File>();
foreach (File file in _files)
{
if (_filter.ToUpper().IndexOf("." + file.Extension.ToUpper()) != -1)
{
filtered.Add(file);
}
}
_files = filtered;
}
}
private async Task GetFiles()
{
_haseditpermission = false;
if (Folder == Constants.PackagesFolder)
{
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
_files = new List<File>();
}
else
{
Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
if (folder != null)
{
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.PermissionList);
_files = await FileService.GetFilesAsync(FolderId);
}
else
{
_haseditpermission = false;
_files = new List<File>();
}
if (_filter != "*")
{
List<File> filtered = new List<File>();
foreach (File file in _files)
{
if (_filter.ToUpper().IndexOf("." + file.Extension.ToUpper()) != -1)
{
filtered.Add(file);
}
}
_files = filtered;
}
}
}
private async Task FolderChanged(ChangeEventArgs e)
{
_message = string.Empty;
try
{
FolderId = int.Parse((string)e.Value);
await GetFiles();
FileId = -1;
_file = null;
_image = string.Empty;
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Files {Error}", ex.Message);
_message = Localizer["Error.File.Load"];
_messagetype = MessageType.Error;
}
}
private async Task FolderChanged(ChangeEventArgs e)
{
_message = string.Empty;
try
{
FolderId = int.Parse((string)e.Value);
await GetFiles();
FileId = -1;
_file = null;
_image = string.Empty;
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Files {Error}", ex.Message);
_message = Localizer["Error.File.Load"];
_messagetype = MessageType.Error;
}
}
private async Task FileChanged(ChangeEventArgs e)
{
_message = string.Empty;
FileId = int.Parse((string)e.Value);
if (FileId != -1)
{
await OnSelect.InvokeAsync(FileId);
}
private async Task FileChanged(ChangeEventArgs e)
{
_message = string.Empty;
FileId = int.Parse((string)e.Value);
if (FileId != -1)
{
await OnSelect.InvokeAsync(FileId);
}
await SetImage();
StateHasChanged();
}
await SetImage();
StateHasChanged();
}
private async Task SetImage()
{
_image = string.Empty;
_file = null;
if (FileId != -1)
{
_file = await FileService.GetFileAsync(FileId);
if (_file != null && ShowImage && _file.ImageHeight != 0 && _file.ImageWidth != 0)
{
var maxwidth = 200;
var maxheight = 200;
private async Task SetImage()
{
_image = string.Empty;
_file = null;
if (FileId != -1)
{
_file = await FileService.GetFileAsync(FileId);
if (_file != null && ShowImage && _file.ImageHeight != 0 && _file.ImageWidth != 0)
{
var maxwidth = 200;
var maxheight = 200;
var ratioX = (double)maxwidth / (double)_file.ImageWidth;
var ratioY = (double)maxheight / (double)_file.ImageHeight;
var ratio = ratioX < ratioY ? ratioX : ratioY;
var ratioX = (double)maxwidth / (double)_file.ImageWidth;
var ratioY = (double)maxheight / (double)_file.ImageHeight;
var ratio = ratioX < ratioY ? ratioX : ratioY;
_image = "<img src=\"" + _file.Url + "\" alt=\"" + _file.Name +
"\" width=\"" + Convert.ToInt32(_file.ImageWidth * ratio).ToString() +
"\" height=\"" + Convert.ToInt32(_file.ImageHeight * ratio).ToString() + "\" />";
}
}
}
_image = "<img src=\"" + _file.Url + "\" alt=\"" + _file.Name +
"\" width=\"" + Convert.ToInt32(_file.ImageWidth * ratio).ToString() +
"\" height=\"" + Convert.ToInt32(_file.ImageHeight * ratio).ToString() + "\" />";
}
}
}
private async Task UploadFiles()
{
_message = string.Empty;
var interop = new Interop(JSRuntime);
var uploads = await interop.GetFiles(_fileinputid);
if (uploads.Length > 0)
{
string restricted = "";
foreach (var upload in uploads)
{
var extension = (upload.LastIndexOf(".") != -1) ? upload.Substring(upload.LastIndexOf(".") + 1) : "";
if (!Constants.UploadableFiles.Split(',').Contains(extension.ToLower()))
{
restricted += (restricted == "" ? "" : ",") + extension;
}
}
if (restricted == "")
{
try
{
// upload the files
var posturl = Utilities.TenantUrl(PageState.Alias, "/api/file/upload");
var folder = (Folder == Constants.PackagesFolder) ? Folder : FolderId.ToString();
await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken);
private async Task UploadFiles()
{
_message = string.Empty;
var interop = new Interop(JSRuntime);
var uploads = await interop.GetFiles(_fileinputid);
if (uploads.Length > 0)
{
string restricted = "";
foreach (var upload in uploads)
{
var extension = (upload.LastIndexOf(".") != -1) ? upload.Substring(upload.LastIndexOf(".") + 1) : "";
if (!Constants.UploadableFiles.Split(',').Contains(extension.ToLower()))
{
restricted += (restricted == "" ? "" : ",") + extension;
}
}
if (restricted == "")
{
try
{
// upload the files
var posturl = Utilities.TenantUrl(PageState.Alias, "/api/file/upload");
var folder = (Folder == Constants.PackagesFolder) ? Folder : FolderId.ToString();
await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken);
// uploading is asynchronous so we need to wait for the uploads to complete
// note that this will only wait a maximum of 15 seconds which may not be long enough for very large file uploads
bool success = false;
int attempts = 0;
while (attempts < 5 && !success)
{
attempts += 1;
Thread.Sleep(1000 * attempts); // progressive retry
// uploading is asynchronous so we need to wait for the uploads to complete
// note that this will only wait a maximum of 15 seconds which may not be long enough for very large file uploads
bool success = false;
int attempts = 0;
while (attempts < 5 && !success)
{
attempts += 1;
Thread.Sleep(1000 * attempts); // progressive retry
success = true;
List<File> files = await FileService.GetFilesAsync(folder);
if (files.Count > 0)
{
foreach (string upload in uploads)
{
if (!files.Exists(item => item.Name == upload))
{
success = false;
}
}
}
}
success = true;
List<File> files = await FileService.GetFilesAsync(folder);
if (files.Count > 0)
{
foreach (string upload in uploads)
{
if (!files.Exists(item => item.Name == upload))
{
success = false;
}
}
}
}
// reset progress indicators
await interop.SetElementAttribute(_guid + "ProgressInfo", "style", "display: none;");
await interop.SetElementAttribute(_guid + "ProgressBar", "style", "display: none;");
// reset progress indicators
await interop.SetElementAttribute(_guid + "ProgressInfo", "style", "display: none;");
await interop.SetElementAttribute(_guid + "ProgressBar", "style", "display: none;");
if (success)
{
await logger.LogInformation("File Upload Succeeded {Files}", uploads);
if (ShowSuccess)
{
_message = Localizer["Success.File.Upload"];
_messagetype = MessageType.Success;
}
}
else
{
await logger.LogInformation("File Upload Failed Or Is Still In Progress {Files}", uploads);
_message = Localizer["Error.File.Upload"];
_messagetype = MessageType.Error;
}
if (success)
{
await logger.LogInformation("File Upload Succeeded {Files}", uploads);
if (ShowSuccess)
{
_message = Localizer["Success.File.Upload"];
_messagetype = MessageType.Success;
}
}
else
{
await logger.LogInformation("File Upload Failed Or Is Still In Progress {Files}", uploads);
_message = Localizer["Error.File.Upload"];
_messagetype = MessageType.Error;
}
// set FileId to first file in upload collection
await GetFiles();
var file = _files.Where(item => item.Name == uploads[0]).FirstOrDefault();
if (file != null)
{
FileId = file.FileId;
await SetImage();
await OnUpload.InvokeAsync(FileId);
}
StateHasChanged();
if (Folder == Constants.PackagesFolder)
{
await OnUpload.InvokeAsync(-1);
}
else
{
// set FileId to first file in upload collection
await GetFiles();
var file = _files.Where(item => item.Name == uploads[0]).FirstOrDefault();
if (file != null)
{
FileId = file.FileId;
await SetImage();
await OnUpload.InvokeAsync(FileId);
}
StateHasChanged();
}
}
catch (Exception ex)
{

View File

@ -5,7 +5,7 @@
<OutputType>Exe</OutputType>
<RazorLangVersion>3.0</RazorLangVersion>
<Configurations>Debug;Release</Configurations>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -13,7 +13,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane</RootNamespace>

View File

@ -132,11 +132,11 @@
<data name="IsDefault.Text" xml:space="preserve">
<value>Default?</value>
</data>
<data name="Success.Language.Install" xml:space="preserve">
<value>Translations Installed Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
<data name="Success.Language.Download" xml:space="preserve">
<value>Translation Package Saved Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; To Complete The Installation.</value>
</data>
<data name="LanguageUpload.HelpText" xml:space="preserve">
<value>Upload one or more translation packages. Once they are uploaded click Install to complete the installation.</value>
<value>Upload one or more translation packages.</value>
</data>
<data name="LanguageUpload.Text" xml:space="preserve">
<value>Translation</value>

View File

@ -133,14 +133,11 @@
<value>Delete Language</value>
</data>
<data name="Success.Language.Download" xml:space="preserve">
<value>Translation Downloaded Successfully. Click Install To Complete Installation.</value>
<value>Translation Package Saved Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; Your Application To Complete The Installation.</value>
</data>
<data name="Error.Language.Download" xml:space="preserve">
<value>Error Downloading Translation</value>
</data>
<data name="Success.Language.Install" xml:space="preserve">
<value>Translation Installed Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
</data>
<data name="Default" xml:space="preserve">
<value>Default</value>
</data>

View File

@ -123,17 +123,14 @@
<data name="Error.Package.Load" xml:space="preserve">
<value>Error Loading Packages</value>
</data>
<data name="Success.Module.Install" xml:space="preserve">
<value>Module Installed Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
</data>
<data name="Success.Module.Download" xml:space="preserve">
<value>Module Downloaded Successfully. Click Install To Complete Installation.</value>
<value>Module Package Saved Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; Your Application To Complete The Installation.</value>
</data>
<data name="Error.Module.Download" xml:space="preserve">
<value>Error Downloading Module</value>
</data>
<data name="Module.HelpText" xml:space="preserve">
<value>Upload one or more module packages. Once they are uploaded click Install to complete the installation.</value>
<value>Upload one or more module packages.</value>
</data>
<data name="Search.NoResults" xml:space="preserve">
<value>No Modules Match The Criteria Provided Or Package Service Is Disabled</value>

View File

@ -211,12 +211,12 @@
<value>No Translations Exist For This Module Or Package Service Is Disabled</value>
</data>
<data name="Success.Translation.Download" xml:space="preserve">
<value>Translation Downloaded Successfully. Click Install To Complete Installation.</value>
</data>
<data name="Success.Translation.Install" xml:space="preserve">
<value>Translation Installed Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
<value>Translation Package Saved Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; Your Application To Complete The Installation.</value>
</data>
<data name="Translations.Heading" xml:space="preserve">
<value>Translations</value>
</data>
<data name="Message.DuplicateName" xml:space="preserve">
<value>A Module With The Name Specified Already Exists</value>
</data>
</root>

View File

@ -123,17 +123,14 @@
<data name="Theme.Text" xml:space="preserve">
<value>Theme: </value>
</data>
<data name="Success.Theme.Install" xml:space="preserve">
<value>Theme Installed Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; Your Application To Apply These Changes.</value>
</data>
<data name="Success.Theme.Download" xml:space="preserve">
<value>Theme Downloaded Successfully. Click Install To Complete Installation.</value>
<value>Theme Package Saved Successfully. You Must &lt;a href={0}&gt;Restart&lt;/a&gt; Your Application To Complete The Installation.</value>
</data>
<data name="Error.Theme.Download" xml:space="preserve">
<value>Error Downloading Theme</value>
</data>
<data name="Theme.HelpText" xml:space="preserve">
<value>Upload one or more theme packages. Once they are uploaded click Install to complete the installation.</value>
<value>Upload one or more theme packages.</value>
</data>
<data name="Search.NoResults" xml:space="preserve">
<value>No Themes Match The Criteria Provided Or Package Service Is Disabled</value>

View File

@ -340,6 +340,48 @@
<value>Visitor Management</value>
</data>
<data name="Oqtane.Marketplace" xml:space="preserve">
<value>Please note that the third party extensions displayed above have been registered in the &lt;a href="https://www.oqtane.net" target="_new"&gt;Oqtane Marketplace&lt;/a&gt; which enables them to be seamlessly downloaded and installed into the framework.</value>
<value>Please note that third party extensions are registered in the &lt;a href="https://www.oqtane.net" target="_new"&gt;Oqtane Marketplace&lt;/a&gt; which enables them to be seamlessly downloaded and installed into the framework.</value>
</data>
<data name="Home" xml:space="preserve">
<value>Home</value>
</data>
<data name="Close" xml:space="preserve">
<value>Close</value>
</data>
<data name="OK" xml:space="preserve">
<value>OK</value>
</data>
<data name="Apply" xml:space="preserve">
<value>Apply</value>
</data>
<data name="Select" xml:space="preserve">
<value>Select</value>
</data>
<data name="Next" xml:space="preserve">
<value>Next</value>
</data>
<data name="Previous" xml:space="preserve">
<value>Previous</value>
</data>
<data name="Submit" xml:space="preserve">
<value>Submit</value>
</data>
<data name="Refresh" xml:space="preserve">
<value>Refresh</value>
</data>
<data name="Back" xml:space="preserve">
<value>Back</value>
</data>
<data name="Return" xml:space="preserve">
<value>Return</value>
</data>
<data name="New" xml:space="preserve">
<value>New</value>
</data>
<data name="View" xml:space="preserve">
<value>View</value>
</data>
<data name="Confirm" xml:space="preserve">
<value>Confirm</value>
</data>
</root>

View File

@ -33,13 +33,6 @@ namespace Oqtane.Services
/// <returns></returns>
Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
/// <summary>
/// Installs all module definitions located in //TODO: 2dm where?
/// </summary>
/// <returns></returns>
Task InstallModuleDefinitionsAsync();
/// <summary>
/// Deletes a module definition
/// </summary>

View File

@ -39,12 +39,6 @@ namespace Oqtane.Services
/// <returns></returns>
List<ThemeControl> GetContainerControls(List<Theme> themes, string themeName);
/// <summary>
/// Installs all themes located in //TODO: 2dm where?
/// </summary>
/// <returns></returns>
Task InstallThemesAsync();
/// <summary>
/// Deletes a theme
/// </summary>

View File

@ -34,11 +34,6 @@ namespace Oqtane.Services
await PutJsonAsync($"{Apiurl}/{moduleDefinition.ModuleDefinitionId}", moduleDefinition);
}
public async Task InstallModuleDefinitionsAsync()
{
await GetJsonAsync<List<string>>($"{Apiurl}/install");
}
public async Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId)
{
await DeleteAsync($"{Apiurl}/{moduleDefinitionId}?siteid={siteId}");

View File

@ -18,11 +18,7 @@ namespace Oqtane.Services
public async Task<List<Module>> GetModulesAsync(int siteId)
{
List<Module> modules = await GetJsonAsync<List<Module>>($"{Apiurl}?siteid={siteId}");
modules = modules
.OrderBy(item => item.Order)
.ToList();
return modules;
return await GetJsonAsync<List<Module>>($"{Apiurl}?siteid={siteId}");
}
public async Task<Module> GetModuleAsync(int moduleId)

View File

@ -38,11 +38,6 @@ namespace Oqtane.Services
.SelectMany(item => item.Containers).ToList();
}
public async Task InstallThemesAsync()
{
await GetJsonAsync<List<string>>($"{ApiUrl}/install");
}
public async Task DeleteThemeAsync(string themeName)
{
await DeleteAsync($"{ApiUrl}/{themeName}");

View File

@ -10,7 +10,7 @@
</button>
</span>
<div class="app-menu navbar-expand-md">
<div class="collapse navbar-collapse" id="Menu">
<div class="collapse navbar-collapse navbar-nav-scroll" id="Menu">
<MenuItemsHorizontal ParentPage="null" Pages="MenuPages" />
</div>
</div>

View File

@ -58,7 +58,11 @@ else
}
if (Name.ToLower() == pane.ToLower())
{
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
Module module = PageState.Modules.FirstOrDefault(item => item.PageId == PageState.Page.PageId && item.ModuleId == PageState.ModuleId);
if (module == null)
{
module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
}
if (module != null)
{
var moduleType = Type.GetType(module.ModuleType);
@ -107,8 +111,12 @@ else
{
if (PageState.ModuleId != -1)
{
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
if (module != null && module.Pane.ToLower() == Name.ToLower())
Module module = PageState.Modules.FirstOrDefault(item => item.PageId == PageState.Page.PageId && item.ModuleId == PageState.ModuleId);
if (module == null)
{
module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
}
if (module != null && module.Pane.ToLower() == Name.ToLower())
{
// check if user is authorized to view module
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))
@ -119,7 +127,7 @@ else
}
else
{
foreach (Module module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId && item.Pane.ToLower() == Name.ToLower()).OrderBy(x => x.Order).ToArray())
foreach (Module module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId && item.Pane.ToLower() == Name.ToLower()))
{
// check if user is authorized to view module
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -10,7 +10,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Database.MySQL</id>
<version>3.4.2</version>
<version>3.4.3</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane MySQL Provider</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -10,7 +10,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Database.PostgreSQL</id>
<version>3.4.2</version>
<version>3.4.3</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane PostgreSQL Provider</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -10,7 +10,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Database.SqlServer</id>
<version>3.4.2</version>
<version>3.4.3</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane SQL Server Provider</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -10,7 +10,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Database.Sqlite</id>
<version>3.4.2</version>
<version>3.4.3</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane SQLite Provider</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -6,7 +6,7 @@
<!-- <TargetFrameworks>net6.0-android;net6.0-ios;net6.0-maccatalyst</TargetFrameworks> -->
<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->
<OutputType>Exe</OutputType>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -14,7 +14,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane.Maui</RootNamespace>
@ -31,7 +31,7 @@
<ApplicationIdGuid>0E29FC31-1B83-48ED-B6E0-9F3C67B775D4</ApplicationIdGuid>
<!-- Versions -->
<ApplicationDisplayVersion>3.4.2</ApplicationDisplayVersion>
<ApplicationDisplayVersion>3.4.3</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
@ -71,8 +71,8 @@
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.3" />
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
<PackageReference Include="Oqtane.Client" Version="3.4.2" />
<PackageReference Include="Oqtane.Shared" Version="3.4.2" />
<PackageReference Include="Oqtane.Client" Version="3.4.3" />
<PackageReference Include="Oqtane.Shared" Version="3.4.3" />
</ItemGroup>
</Project>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Client</id>
<version>3.4.2</version>
<version>3.4.3</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Framework</id>
<version>3.4.2</version>
<version>3.4.3</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -11,8 +11,8 @@
<copyright>.NET Foundation</copyright>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v3.4.2/Oqtane.Framework.3.4.2.Upgrade.zip</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</releaseNotes>
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v3.4.3/Oqtane.Framework.3.4.3.Upgrade.zip</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane framework</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Server</id>
<version>3.4.2</version>
<version>3.4.3</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Shared</id>
<version>3.4.2</version>
<version>3.4.3</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Updater</id>
<version>3.4.2</version>
<version>3.4.3</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -1 +1 @@
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.4.2.Install.zip" -Force
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.4.3.Install.zip" -Force

View File

@ -1 +1 @@
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.4.2.Upgrade.zip" -Force
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.4.3.Upgrade.zip" -Force

View File

@ -120,6 +120,13 @@ namespace Oqtane.Controllers
var binFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var assemblyList = new List<ClientAssembly>();
// testmode setting is used for validating that the API is downloading the appropriate assemblies to the client
bool hashfilename = true;
if (_configManager.GetSetting($"{SettingKeys.TestModeKey}", "false") == "true")
{
hashfilename = false;
}
// get list of assemblies which should be downloaded to client
var assemblies = AppDomain.CurrentDomain.GetOqtaneClientAssemblies();
var list = assemblies.Select(a => a.GetName().Name).ToList();
@ -127,7 +134,7 @@ namespace Oqtane.Controllers
// populate assemblies
for (int i = 0; i < list.Count; i++)
{
assemblyList.Add(new ClientAssembly(Path.Combine(binFolder, list[i] + ".dll")));
assemblyList.Add(new ClientAssembly(Path.Combine(binFolder, list[i] + ".dll"), hashfilename));
}
// insert satellite assemblies at beginning of list
@ -143,7 +150,7 @@ namespace Oqtane.Controllers
{
foreach (var resourceFile in Directory.EnumerateFiles(assembliesFolderPath))
{
assemblyList.Insert(0, new ClientAssembly(resourceFile));
assemblyList.Insert(0, new ClientAssembly(resourceFile, hashfilename));
}
}
else
@ -160,12 +167,12 @@ namespace Oqtane.Controllers
var instance = Activator.CreateInstance(type) as IModule;
foreach (string name in instance.ModuleDefinition.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
{
var filepath = Path.Combine(binFolder, name + ".dll");
var filepath = Path.Combine(binFolder, name.ToLower().EndsWith(".dll") ? name : name + ".dll");
if (System.IO.File.Exists(filepath))
{
if (!assemblyList.Exists(item => item.FilePath == filepath))
{
assemblyList.Insert(0, new ClientAssembly(filepath));
assemblyList.Insert(0, new ClientAssembly(filepath, hashfilename));
}
}
else
@ -179,12 +186,12 @@ namespace Oqtane.Controllers
var instance = Activator.CreateInstance(type) as ITheme;
foreach (string name in instance.Theme.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
{
var filepath = Path.Combine(binFolder, name + ".dll");
var filepath = Path.Combine(binFolder, name.ToLower().EndsWith(".dll") ? name : name + ".dll");
if (System.IO.File.Exists(filepath))
{
if (!assemblyList.Exists(item => item.FilePath == filepath))
{
assemblyList.Insert(0, new ClientAssembly(filepath));
assemblyList.Insert(0, new ClientAssembly(filepath, hashfilename));
}
}
else
@ -285,11 +292,18 @@ namespace Oqtane.Controllers
public struct ClientAssembly
{
public ClientAssembly(string filepath)
public ClientAssembly(string filepath, bool hashfilename)
{
FilePath = filepath;
DateTime lastwritetime = System.IO.File.GetLastWriteTime(filepath);
HashedName = GetDeterministicHashCode(filepath).ToString("X8") + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
if (hashfilename)
{
HashedName = GetDeterministicHashCode(filepath).ToString("X8") + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
}
else
{
HashedName = Path.GetFileNameWithoutExtension(filepath) + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
}
}
public string FilePath { get; private set; }

View File

@ -9,6 +9,7 @@ using Oqtane.Infrastructure;
using Oqtane.Repository;
using Oqtane.Security;
using System.Net;
using System.Security.Policy;
namespace Oqtane.Controllers
{
@ -83,6 +84,7 @@ namespace Oqtane.Controllers
modules.Add(module);
}
modules = modules.OrderBy(item => item.PageId).ThenBy(item => item.Pane).ThenBy(item => item.Order).ToList();
}
}
else

View File

@ -268,14 +268,6 @@ namespace Oqtane.Controllers
}
}
[HttpGet("install")]
[Authorize(Roles = RoleNames.Host)]
public void InstallModules()
{
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Modules Installed");
_installationManager.InstallPackages();
}
// GET: api/<controller>/templates
[HttpGet("templates")]
[Authorize(Roles = RoleNames.Host)]

View File

@ -137,6 +137,7 @@ namespace Oqtane.Controllers
site.Modules.Add(module);
}
}
site.Modules = site.Modules.OrderBy(item => item.PageId).ThenBy(item => item.Pane).ThenBy(item => item.Order).ToList();
// languages
site.Languages = _languages.GetLanguages(site.SiteId).ToList();

View File

@ -41,14 +41,6 @@ namespace Oqtane.Controllers
return _themes.GetThemes();
}
[HttpGet("install")]
[Authorize(Roles = RoleNames.Host)]
public void InstallThemes()
{
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Themes Installed");
_installationManager.InstallPackages();
}
// DELETE api/<controller>/xxx
[HttpDelete("{themename}")]
[Authorize(Roles = RoleNames.Host)]

View File

@ -12,6 +12,8 @@ using System.Threading.Tasks;
using System.Xml;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Oqtane.Controllers;
using Oqtane.Shared;
// ReSharper disable AssignNullToNotNullAttribute
@ -21,21 +23,27 @@ namespace Oqtane.Infrastructure
{
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private readonly IWebHostEnvironment _environment;
private readonly ILogger<InstallationManager> _filelogger;
public InstallationManager(IHostApplicationLifetime hostApplicationLifetime, IWebHostEnvironment environment)
public InstallationManager(IHostApplicationLifetime hostApplicationLifetime, IWebHostEnvironment environment, ILogger<InstallationManager> filelogger)
{
_hostApplicationLifetime = hostApplicationLifetime;
_environment = environment;
_filelogger = filelogger;
}
public void InstallPackages()
{
InstallPackages(_environment.WebRootPath, _environment.ContentRootPath);
var errors = InstallPackages(_environment.WebRootPath, _environment.ContentRootPath);
if (!string.IsNullOrEmpty(errors))
{
_filelogger.LogError(errors);
}
}
public static bool InstallPackages(string webRootPath, string contentRootPath)
public static string InstallPackages(string webRootPath, string contentRootPath)
{
bool install = true;
string errors = "";
string binPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
string sourceFolder = Path.Combine(contentRootPath, "Packages");
@ -172,16 +180,14 @@ namespace Oqtane.Infrastructure
}
catch (Exception ex)
{
// problem installing package - logging is not possible as this is a static method
Debug.WriteLine($"Oqtane Error: Installing Package {packagename} - {ex}");
install = false;
errors += $"Error Installing Package {packagename} - {ex.Message}. ";
}
// remove package
File.Delete(packagename);
}
return install;
return errors;
}
private static string ExtractFile(ZipArchiveEntry entry, string folder, int ignoreLeadingSegments)
@ -300,7 +306,7 @@ namespace Oqtane.Infrastructure
if (packageversion != "" && Version.Parse(Constants.Version).CompareTo(Version.Parse(packageversion)) <= 0 && packageurl != "")
{
// install Oqtane.Framework and Oqtane.Updater nuget packages
InstallPackages();
InstallPackages(_environment.WebRootPath, _environment.ContentRootPath);
// download upgrade zip package
Uri uri = new Uri(packageurl);
string upgradepackage = Path.Combine(folder, uri.Segments[uri.Segments.Length - 1]);

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Configurations>Debug;Release</Configurations>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -11,7 +11,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane</RootNamespace>

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
@ -24,16 +25,18 @@ namespace Oqtane.Pages
private readonly IPageRepository _pages;
private readonly IPageModuleRepository _pageModules;
private readonly IModuleDefinitionRepository _moduleDefinitions;
private readonly ISettingRepository _settings;
private readonly IUserPermissions _userPermissions;
private readonly ILogManager _logger;
private readonly Alias _alias;
public SitemapModel(IServiceProvider serviceProvider, IPageRepository pages, IPageModuleRepository pageModules, IModuleDefinitionRepository moduleDefinitions, IUserPermissions userPermissions, IUrlMappingRepository urlMappings, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
public SitemapModel(IServiceProvider serviceProvider, IPageRepository pages, IPageModuleRepository pageModules, IModuleDefinitionRepository moduleDefinitions, ISettingRepository settings, IUserPermissions userPermissions, IUrlMappingRepository urlMappings, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
{
_serviceProvider = serviceProvider;
_pages = pages;
_pageModules = pageModules;
_moduleDefinitions = moduleDefinitions;
_settings = settings;
_userPermissions = userPermissions;
_logger = logger;
_alias = tenantManager.GetAlias();
@ -50,7 +53,7 @@ namespace Oqtane.Pages
{
if (_userPermissions.IsAuthorized(null, PermissionNames.View, page.PermissionList) && page.IsNavigation)
{
sitemap.Add(new Sitemap { Url = _alias.Protocol + _alias.Name + Utilities.NavigateUrl(_alias.Path, page.Path, ""), ModifiedOn = page.ModifiedOn });
sitemap.Add(new Sitemap { Url = _alias.Protocol + _alias.Name + Utilities.NavigateUrl(_alias.Path, page.Path, ""), ModifiedOn = DateTime.UtcNow });
foreach (var pageModule in pageModules.Where(item => item.PageId == page.PageId))
{
@ -68,7 +71,7 @@ namespace Oqtane.Pages
var urls = ((ISitemap)moduleobject).GetUrls(_alias.Path, page.Path, pageModule.Module);
foreach (var url in urls)
{
sitemap.Add(new Sitemap { Url = _alias.Protocol + _alias.Name + url.Url, ModifiedOn = url.ModifiedOn });
sitemap.Add(new Sitemap { Url = _alias.Protocol + _alias.Name + url.Url, ModifiedOn = DateTime.UtcNow });
}
}
catch (Exception ex)
@ -83,19 +86,21 @@ namespace Oqtane.Pages
}
// write XML
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = (" ");
settings.CloseOutput = true;
settings.OmitXmlDeclaration = true;
settings.WriteEndDocumentOnClose = true;
var builder = new StringBuilder();
var stringWriter = new StringWriterWithEncoding(builder, Encoding.UTF8);
StringBuilder builder = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(builder, settings))
var settings = new XmlWriterSettings
{
writer.WriteStartDocument();
writer.WriteStartElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9");
Indent = true,
IndentChars = " ",
NewLineChars = Environment.NewLine,
CloseOutput = true,
WriteEndDocumentOnClose = true
};
using (var writer = XmlWriter.Create(stringWriter, settings))
{
writer.WriteStartElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9");
foreach (var url in sitemap)
{
writer.WriteStartElement("url");
@ -103,10 +108,29 @@ namespace Oqtane.Pages
writer.WriteElementString("lastmod", url.ModifiedOn.ToString("yyyy-MM-dd"));
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.Close();
}
return Content(builder.ToString());
return Content(builder.ToString(), "application/xml");
}
}
public class StringWriterWithEncoding : StringWriter
{
private readonly Encoding _encoding;
public StringWriterWithEncoding(StringBuilder builder, Encoding encoding) : base(builder)
{
this._encoding = encoding;
}
public override Encoding Encoding
{
get
{
return this._encoding;
}
}
}
}

View File

@ -34,6 +34,7 @@ namespace Oqtane.Server
WebHost.CreateDefaultBuilder(args)
.UseConfiguration(new ConfigurationBuilder()
.AddCommandLine(args)
.AddEnvironmentVariables()
.Build())
.UseStartup<Startup>()
.ConfigureLocalizationSettings()

View File

@ -48,6 +48,7 @@ namespace Oqtane.Repository
_db.Entry(moduleDefinition).State = EntityState.Modified;
_db.SaveChanges();
_permissions.UpdatePermissions(moduleDefinition.SiteId, EntityNames.ModuleDefinition, moduleDefinition.ModuleDefinitionId, moduleDefinition.PermissionList);
_cache.Remove("moduledefinitions");
}
public void DeleteModuleDefinition(int moduleDefinitionId)
@ -322,7 +323,7 @@ namespace Oqtane.Repository
permission.EntityName = p.EntityName;
permission.EntityId = p.EntityId;
permission.PermissionName = p.PermissionName;
permission.RoleId = p.RoleId;
permission.RoleId = null;
permission.RoleName = p.RoleName;
permission.UserId = p.UserId;
permission.IsAuthorized = p.IsAuthorized;

View File

@ -36,9 +36,10 @@ namespace Oqtane.Repository
{
if (permission.RoleId != null && string.IsNullOrEmpty(permission.RoleName))
{
permission.RoleName = roles.Find(item => item.RoleId == permission.RoleId).Name;
permission.RoleName = roles.Find(item => item.RoleId == permission.RoleId)?.Name;
}
}
permissions = permissions.Where(item => item.UserId != null || item.RoleName != null).ToList();
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
return permissions;
});
@ -93,11 +94,7 @@ namespace Oqtane.Repository
permission.EntityId = (permission.EntityName == entityName) ? entityId : -1;
if (permission.UserId == null && permission.RoleId == null && !string.IsNullOrEmpty(permission.RoleName))
{
var role = roles.FirstOrDefault(item => item.Name == permission.RoleName);
if (role != null)
{
permission.RoleId = role.RoleId;
}
permission.RoleId = roles.FirstOrDefault(item => item.Name == permission.RoleName)?.RoleId;
}
}
// add or update permissions

View File

@ -431,7 +431,6 @@ namespace Oqtane.Repository
PermissionList = new List<Permission>
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
new Permission(PermissionNames.View, RoleNames.Registered, true),
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
},
PageTemplateModules = new List<PageTemplateModule>
@ -442,7 +441,6 @@ namespace Oqtane.Repository
PermissionList = new List<Permission>
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
new Permission(PermissionNames.View, RoleNames.Registered, true),
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
},
Content = ""

View File

@ -16,6 +16,7 @@ using Oqtane.Repository;
using Oqtane.Security;
using Oqtane.Shared;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.Logging;
namespace Oqtane
{
@ -24,6 +25,7 @@ namespace Oqtane
private readonly bool _useSwagger;
private readonly IWebHostEnvironment _env;
private readonly string[] _installedCultures;
private string _configureServicesErrors;
public IConfigurationRoot Configuration { get; }
@ -32,7 +34,8 @@ namespace Oqtane
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true)
.AddEnvironmentVariables();
Configuration = builder.Build();
_installedCultures = localizationManager.GetInstalledCultures();
@ -85,7 +88,7 @@ namespace Oqtane
.AddOqtaneSingletonServices();
// install any modules or themes ( this needs to occur BEFORE the assemblies are loaded into the app domain )
InstallationManager.InstallPackages(_env.WebRootPath, _env.ContentRootPath);
_configureServicesErrors += InstallationManager.InstallPackages(_env.WebRootPath, _env.ContentRootPath);
// register transient scoped core services
services.AddOqtaneTransientServices();
@ -142,8 +145,13 @@ namespace Oqtane
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISyncManager sync)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISyncManager sync, ILogger<Startup> logger)
{
if (!string.IsNullOrEmpty(_configureServicesErrors))
{
logger.LogError(_configureServicesErrors);
}
ServiceActivator.Configure(app.ApplicationServices);
if (env.IsDevelopment())

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Configurations>Debug;Release</Configurations>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -11,7 +11,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane</RootNamespace>

View File

@ -4,8 +4,8 @@ namespace Oqtane.Shared
{
public class Constants
{
public static readonly string Version = "3.4.2";
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2";
public static readonly string Version = "3.4.3";
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3";
public const string PackageId = "Oqtane.Framework";
public const string ClientId = "Oqtane.Client";
public const string UpdaterPackageId = "Oqtane.Updater";

View File

@ -19,5 +19,7 @@ namespace Oqtane.Shared
public const string DefaultContainerKey = "DefaultContainer";
public const string AvailableDatabasesSection = "AvailableDatabases";
public const string TestModeKey = "TestMode"; // optional - used for testing run-time characteristics
}
}

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Configurations>Debug;Release</Configurations>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -11,7 +11,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane</RootNamespace>

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<OutputType>Exe</OutputType>
<Version>3.4.2</Version>
<Version>3.4.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -11,7 +11,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane</RootNamespace>

View File

@ -1,11 +1,11 @@
# Latest Release
[3.4.1](https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.1) was released on Mar 13, 2023 and is primarily focused on performance, as the permissions system has been overhauled to avoid unnecessary encoding and parsing of custom access control strings. This release also includes enhancements to connection string management, numerous stabilization and user experience improvements, and the ability to dynamically generate an XML sitemap for seach engine indexing. This release includes 62 pull requests by 6 different contributors, pushing the total number of project commits all-time over 3300. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
# Oqtane Framework
[3.4.2](https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2) was released on Mar 29, 2023 and is primarily focused on performance, as the permissions system has been overhauled to avoid unnecessary encoding and parsing of custom access control strings. This release also includes enhancements to connection string management, numerous stabilization and user experience improvements, and the ability to dynamically generate an XML sitemap for seach engine indexing. This release includes 62 pull requests by 6 different contributors, pushing the total number of project commits all-time over 3300. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Foqtane%2Foqtane.framework%2Fmaster%2Fazuredeploy.json)
# Oqtane Framework
![Oqtane](https://github.com/oqtane/framework/blob/master/oqtane.png?raw=true "Oqtane")
Oqtane is a Modular Application Framework. It leverages Blazor, an open source and cross-platform web UI framework for building single-page apps using .NET and C# instead of JavaScript. Blazor apps are composed of reusable web UI components implemented using C#, HTML, and CSS. Both client and server code is written in C#, allowing you to share code and libraries.
@ -50,6 +50,9 @@ This project is open source, and therefore is a work in progress...
- [ ] File / New Project experience
- [ ] Folder Providers
[3.4.2](https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2) ( Mar 29, 2023 )
- [x] Stabilization improvements
[3.4.1](https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.1) ( Mar 13, 2023 )
- [x] Stabilization improvements

View File

@ -2,13 +2,40 @@
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.1",
"parameters": {
"sqlDatabaseEditionTierDtuCapacity": {
"type": "string",
"defaultValue": "Standard-S1-20-250",
"allowedValues": [
"Basic-Basic-5-2",
"Standard-S0-10-250",
"Standard-S1-20-250",
"Standard-S2-50-250",
"Standard-S3-100-250",
"Standard-S4-200-250",
"Standard-S6-400-250",
"Standard-S7-800-250",
"Standard-S9-1600-250",
"Standard-S12-3000-250",
"Premium-P1-125-500",
"Premium-P2-250-500",
"Premium-P4-500-500" ,
"Premium-P6-1000-500",
"Premium-P11-1750-500-1024",
"Premium-P15-4000-1024",
"GeneralPurpose-GP_Gen5_2-2-250",
"GeneralPurpose-GP_S_Gen5_2-2-250"
],
"metadata": {
"description": "Describes the database Edition, Tier, Dtu, Gigabytes (Edition-Tier-Dtu-Gigabytes)"
}
},
"sqlServerName": {
"type": "string",
"metadata": {
"description": "The name of the sql server. It has to be unique."
}
},
"databaseName": {
"sqlDatabaseName": {
"type": "string",
"metadata": {
"description": "The name of the sql databaseName. It has to be unique."
@ -35,21 +62,29 @@
"BlazorSKU": {
"type": "string",
"allowedValues": [
"Free",
"Shared",
"Basic",
"Standard"
"F1",
"D1",
"B1",
"B2",
"B3",
"S1",
"S2",
"S3",
"P1",
"P2",
"P3",
"P4"
],
"defaultValue": "Standard"
"defaultValue": "B1"
},
"BlazorWorkerSize": {
"type": "string",
"allowedValues": [
"0",
"1",
"2"
],
"defaultValue": "0"
"BlazorSKUCapacity": {
"type": "int",
"defaultValue": 1,
"maxValue": 3,
"minValue": 1,
"metadata": {
"description": "Describes plan's instance count"
}
},
"location": {
"type": "string",
@ -61,84 +96,83 @@
},
"variables": {
"hostingPlanName": "[concat('Oqtane-hostingplan-', uniqueString(resourceGroup().id))]",
"databaseEdition": "Standard",
"databaseCollation": "SQL_Latin1_General_CP1_CI_AS",
"databaseServiceObjectiveName": "Standard"
"databaseEditionTierDtuCapacity": "[split(parameters('sqlDatabaseEditionTierDtuCapacity'),'-')]",
"databaseEdition": "[variables('databaseEditionTierDtuCapacity')[0]]",
"databaseTier": "[variables('databaseEditionTierDtuCapacity')[1]]",
"databaseDtu": "[if(greater(length(variables('databaseEditionTierDtuCapacity')), 2), variables('databaseEditionTierDtuCapacity')[2], '')]",
"databaseMaxSizeGigaBytes":"[if(greater(length(variables('databaseEditionTierDtuCapacity')), 3), variables('databaseEditionTierDtuCapacity')[3], '')]",
"databaseServerlessTiers": [
"GP_S_Gen5_2"
]
},
"resources": [
{
"name": "[parameters('sqlServerName')]",
"type": "Microsoft.Sql/servers",
"apiVersion": "2014-04-01",
"location": "[resourceGroup().location]",
"apiVersion": "2021-11-01",
"name": "[parameters('sqlServerName')]",
"location": "[parameters('location')]",
"tags": {
"displayName": "SqlServer"
"displayName": "SQL Server"
},
"properties": {
"administratorLogin": "[parameters('sqlAdministratorLogin')]",
"administratorLoginPassword": "[parameters('sqlAdministratorLoginPassword')]",
"version": "12.0"
}
},
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2021-11-01",
"name": "[format('{0}/{1}', parameters('sqlServerName'), parameters('sqlDatabaseName'))]",
"location": "[parameters('location')]",
"tags": {
"displayName": "Database"
},
"resources": [
{
"name": "[parameters('databaseName')]",
"type": "databases",
"apiVersion": "2015-01-01",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "Database"
},
"properties": {
"edition": "[variables('databaseEdition')]",
"collation": "[variables('databaseCollation')]",
"requestedServiceObjectiveName": "[variables('databaseServiceObjectiveName')]"
},
"dependsOn": [
"[parameters('sqlServerName')]"
],
"resources": [
{
"comments": "Transparent Data Encryption",
"name": "current",
"type": "transparentDataEncryption",
"apiVersion": "2014-04-01-preview",
"properties": {
"status": "Enabled"
},
"dependsOn": [
"[parameters('databaseName')]"
]
}
]
},
{
"name": "AllowAllMicrosoftAzureIps",
"type": "firewallrules",
"apiVersion": "2014-04-01",
"location": "[resourceGroup().location]",
"properties": {
"endIpAddress": "0.0.0.0",
"startIpAddress": "0.0.0.0"
},
"dependsOn": [
"[parameters('sqlServerName')]"
]
}
"sku": {
"name": "[if(equals(variables('databaseEdition'), 'GeneralPurpose'), variables('databaseTier'), variables('databaseEdition'))]",
"tier": "[variables('databaseEdition')]",
"capacity": "[if(equals(variables('databaseDtu'), ''), json('null'), int(variables('databaseDtu')))]"
},
"kind": "[concat('v12.0,user,vcore',if(contains(variables('databaseServerlessTiers'),variables('databaseTier')),',serverless',''))]",
"properties": {
"edition": "[variables('databaseEdition')]",
"collation": "[variables('databaseCollation')]",
"maxSizeBytes": "[if(equals(variables('databaseMaxSizeGigaBytes'), ''), json('null'), mul(mul(mul(int(variables('databaseMaxSizeGigaBytes')),1024),1024),1024))]",
"requestedServiceObjectiveName": "[variables('databaseTier')]"
},
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('sqlserverName'))]"
]
},
{
"type": "Microsoft.Sql/servers/firewallRules",
"apiVersion": "2021-11-01",
"name": "[format('{0}/{1}', parameters('sqlServerName'), 'AllowAllWindowsAzureIps')]",
"properties": {
"endIpAddress": "0.0.0.0",
"startIpAddress": "0.0.0.0"
},
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]"
]
},
{
"name": "[variables('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"apiVersion": "2014-06-01",
"apiVersion": "2022-09-01",
"dependsOn": [],
"tags": {
"displayName": "Blazor"
},
"sku": {
"name": "[parameters('BlazorSKU')]",
"capacity": "[parameters('BlazorSKUCapacity')]"
},
"properties": {
"name": "[variables('hostingPlanName')]",
"sku": "[parameters('BlazorSKU')]",
"workerSize": "[parameters('BlazorWorkerSize')]",
"numberOfWorkers": 1
}
},
@ -169,8 +203,8 @@
"name": "web",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('BlazorWebsiteName'))]",
"[resourceId('Microsoft.Web/Sites/config', parameters('BlazorWebsiteName'), 'connectionstrings')]"
"[resourceId('Microsoft.Web/sites', parameters('BlazorWebsiteName'))]"
//"[resourceId('Microsoft.Web/Sites/config', parameters('BlazorWebsiteName'), 'connectionstrings')]"
],
"properties": {
"RepoUrl": "https://github.com/oqtane/oqtane.framework.git",