Compare commits

..

100 Commits

Author SHA1 Message Date
6bcb769fe5 Merge pull request #675 from sbwalker/master
prepare for 1.0.3 release
2020-08-07 10:40:00 -07:00
90110a653c prepare for 1.0.3 release 2020-08-07 13:39:19 -04:00
3c561cc413 Merge pull request #48 from oqtane/master
sync
2020-08-07 10:25:15 -07:00
73f9622ba2 Merge pull request #674 from sbwalker/master
prepare for 1.0.3 release
2020-08-07 10:24:31 -07:00
cf198ff781 prepare for 1.0.3 release 2020-08-07 13:23:58 -04:00
648fc56495 Merge pull request #673 from sbwalker/master
fixed very large file upload
2020-08-07 08:46:57 -07:00
ea6dc6b983 fixed very large file upload 2020-08-07 11:46:11 -04:00
c0e8d09ce1 Merge pull request #672 from sbwalker/master
allow user to reinstall current version
2020-08-06 13:48:07 -07:00
a471784cf3 allow user to reinstall current version 2020-08-06 16:46:22 -04:00
1d2a4bf484 Merge pull request #671 from sbwalker/master
include logging during module and theme installation
2020-08-06 13:37:55 -07:00
3fa620f3bc include logging during module and theme installation 2020-08-06 16:37:27 -04:00
35f186b532 Merge pull request #670 from sbwalker/master
fix regression bug caused by #649 related to installing nupkg packages
2020-08-06 13:10:51 -07:00
5cf35fd70a fix regression bug caused by #649 related to installing nupkg packages 2020-08-06 16:10:19 -04:00
1eef08eaeb Merge pull request #669 from sbwalker/master
modifications for System Update
2020-08-06 10:30:40 -07:00
1750f28a9f modifications for System Update 2020-08-06 13:30:06 -04:00
41edbc5e22 Merge pull request #668 from sbwalker/master
modifications for System Update feature
2020-08-04 10:07:35 -07:00
04257f75e7 modifications for System Update feature 2020-08-04 13:06:54 -04:00
5fb602f733 Merge pull request #667 from sbwalker/master
Improvements to System Update
2020-08-04 05:48:19 -07:00
94f0bdcce9 Improvements to System Update 2020-08-04 08:47:39 -04:00
0ba24f9a3a Update README.md 2020-08-04 08:42:28 -04:00
aac7d6b97a Merge pull request #664 from sbwalker/master
create 1.0.2 packages
2020-07-23 15:32:17 -04:00
bcc33af52b create 1.0.2 packages 2020-07-23 15:31:28 -04:00
24fd42636a Merge pull request #663 from sbwalker/master
preparing for 1.0.2 release
2020-07-23 15:08:27 -04:00
8d539d058c preparing for 1.0.2 release 2020-07-23 15:07:18 -04:00
abda377f6f Merge pull request #662 from sbwalker/master
fix regression bug caused by #648  - the entries within a nupkg (zip) package use the '/' separator - the fix in #648 was causing a wwwroot\wwwroot\... folder to be created on Windows
2020-07-23 14:59:25 -04:00
51bf822392 fix regression bug caused by #648 - the entries within a nupkg (zip) package use the '/' separator - the fix in #648 was causing a wwwroot\wwwroot\... folder to be created on Windows 2020-07-23 14:58:33 -04:00
d3f135a9c7 Merge pull request #47 from oqtane/master
sync
2020-07-23 14:41:29 -04:00
07ba99cc41 Merge pull request #661 from sbwalker/master
increase wait time for browser redirects during app restarts
2020-07-23 14:40:46 -04:00
336550c571 increase wait time for browser redirects during app restarts 2020-07-23 14:39:53 -04:00
679cc04178 Merge pull request #660 from sbwalker/master
optimize NotificationJob so that it only processes the sites for each tenant once.
2020-07-23 14:15:24 -04:00
75fe4e7c89 optimize NotificationJob so that it only processes the sites for each tenant once. 2020-07-23 14:14:29 -04:00
410f8c74e5 Merge pull request #649 from JoergH66/feature/LoadDependDlls_InstallManager
Fixes 2 external module installation problems
2020-07-23 11:39:35 -04:00
05f67d6a2a Merge pull request #659 from sbwalker/master
fixed scheduler so that it does not set NextExecution until after the job has finished executing
2020-07-23 11:39:19 -04:00
3a6cde0e24 fixed scheduler so that it does not set NextExecution until after the job has finished executing 2020-07-23 11:38:20 -04:00
fe1de2b243 Merge pull request #658 from sbwalker/master
Allow scheduled jobs to set next execution date, fix issue in site settings where logo field was not being populated, fixed compositing issue where deleted modules were being rendered.
2020-07-22 16:10:23 -04:00
62a6b5f28a Allow scheduled jobs to set next execution date, fix issue in site settings where logo field was not being populated, fixed compositing issue where deleted modules were being rendered. 2020-07-22 16:09:39 -04:00
d648fa0f02 Merge pull request #657 from ADefWebserver/master
Make a Deploy to Azure Button #168
2020-07-21 11:07:36 -04:00
e706e8cf1f Update README.md
Points the button to the Oqtane repository
2020-07-18 09:55:27 -07:00
9eb8a7e65c Update azuredeploy.json 2020-07-18 09:40:40 -07:00
11c610edf0 Update .deployment 2020-07-18 09:18:02 -07:00
a65cdbd7ad Rename azure.deployment to .deployment 2020-07-18 08:12:18 -07:00
97c56ba142 Create azure.deployment 2020-07-18 08:02:03 -07:00
9fe72a1c98 Update azuredeploy.json 2020-07-17 18:45:57 -07:00
7b40725534 Update README.md 2020-07-17 18:15:08 -07:00
5e1671afe3 Create azuredeploy.json 2020-07-17 18:10:22 -07:00
50d74cbcee Merge pull request #656 from sbwalker/master
modifications to ActionLink and ActionDialog controls, added logic to prevent IHostedService from blocking startup, made controller route prefix consistent in module template
2020-07-17 15:11:32 -04:00
bc73e5e3d0 modifications to ActionLink and ActionDialog controls, added logic to prevent IHostedService from blocking startup, made controller route prefix consistent in module template 2020-07-17 15:09:05 -04:00
b02bdee8cb Merge pull request #46 from oqtane/master
sync
2020-07-17 10:10:23 -04:00
9db4985b14 Merge pull request #655 from alexhendel/fix-path-handling
Fix directory separator for path operations
2020-07-16 10:27:34 -04:00
6f281c256b Merge pull request #654 from mikecasas/upstream-local
Should be moduleid as the entity id is added in the CreateAuthPolicyU…
2020-07-16 10:27:19 -04:00
807252c9e5 Fix directory separator for path operations 2020-07-15 16:09:19 +02:00
23e7f66188 Delete module id as it is getting added in CreateAuthPolicyUrl method. 2020-07-14 11:47:59 -04:00
57c500f4bc Merge remote-tracking branch 'github-mike/upstream-local' into upstream-local 2020-07-14 11:42:55 -04:00
fe302aa9e4 Should be moduleid as the entity id is added in the CreateAuthPolicyUrl method. 2020-07-12 18:59:20 -04:00
f14f927df7 Update README.md 2020-07-09 10:19:20 -04:00
c3f74a5217 Update README.md 2020-07-09 10:18:06 -04:00
457d1bb563 Update README.md 2020-07-09 10:17:34 -04:00
25918056cb Update README.md 2020-07-09 10:14:53 -04:00
86517dd793 Update README.md 2020-07-09 10:13:07 -04:00
00ce083a2c Update README.md 2020-07-09 10:11:28 -04:00
bce262cd8e Merge pull request #652 from sbwalker/master
remove line feeds from content during import
2020-07-09 08:46:50 -04:00
b5db62ef6a remove line feeds from content during import 2020-07-09 08:45:23 -04:00
3703d87d50 Merge pull request #651 from sbwalker/master
Html encode job log messages, add new IModule property to allow modules to specify Runtime support, provide feedback during module content import, remove default EditMode option at the Page level (should be implemented at Module level) - resolves issue where Admin modules could not be deleted, include link to Event Log in AddModuleMessage for Error message type, fixed fallback support for themes in siterouter, integrated auth policy into site templates for Module Creator
2020-07-08 19:57:13 -04:00
f515def414 Html encode job log messages, add new IModule property to allow modules to specify Runtime support, provide feedback during module content import, remove default EditMode option at the Page level (should be implemented at Module level) - resolves issue where Admin modules could not be deleted, include link to Event Log in AddModuleMessage for Error message type, fixed fallback support for themes in siterouter, integrated auth policy into site templates for Module Creator 2020-07-08 19:56:02 -04:00
4bdf20822f check whether the file is in use, dependent runtime-dlls will distribute 2020-07-08 14:06:41 +02:00
49f4e64cb4 Merge pull request #45 from oqtane/master
sync
2020-07-07 08:44:51 -04:00
e615263706 Merge pull request #647 from chlupac/Notifications
Notification changes UNDO
2020-07-07 08:43:52 -04:00
2a7e256116 Merge pull request #648 from alexhendel/fix-linux-theme-installation
Fix directory separator in InstallationManager
2020-07-07 08:43:37 -04:00
a083405b48 Fix directory seperator in InstallationManager 2020-07-07 09:56:24 +02:00
3ea280c82a Motification changes UNDO 2020-07-06 15:27:35 +02:00
192433f02d Merge pull request #44 from oqtane/master
sync
2020-07-05 11:32:20 -04:00
56a2e9dcea Merge pull request #644 from chlupac/ActionIcons
Icons in module actions menu
2020-07-03 15:16:47 -04:00
921cced1c8 Merge pull request #643 from chlupac/Notifications
Notification job optimalization
2020-07-03 15:16:14 -04:00
b17f679f38 Notification job optimalization 2020-07-03 10:19:12 +02:00
8e43fcab21 Icons in module actions menu 2020-07-03 10:15:45 +02:00
73c5092e46 Merge pull request #43 from oqtane/master
sync
2020-07-02 08:56:55 -04:00
56537e4785 Merge pull request #642 from svreic/bugfix/page-path-validation
Page path validation
2020-07-02 08:13:39 -04:00
3bd7d7196d Merge pull request #640 from PoisnFang/routing
Url parameter helper enhancements
2020-07-02 08:11:14 -04:00
7b5a192b82 Added double page path validation 2020-07-02 09:47:42 +02:00
d4be058d07 Can get parameters without template
clear urlParameters dictionary if template fails. Removed UrlParametersTemplate property and UrlParamerters auto dictionary
2020-07-01 15:15:39 -07:00
6c20fea46a Merge pull request #641 from chlupac/NotifyRepo
Notification Repository Breaking change fix
2020-07-01 14:22:26 -04:00
2e7cfefb2e Notification Repository Breaking change fix 2020-07-01 14:23:55 +02:00
038894cf64 Enhancement to url parameters helper in modulebase 2020-07-01 01:35:06 -07:00
954e30d89f Save url parameter action segments 2020-06-30 16:01:16 -07:00
93d9c4534d Merge pull request #42 from oqtane/master
sync
2020-06-30 16:56:08 -04:00
468ca8c6a9 Merge pull request #639 from PoisnFang/routing
Hot fix for homepage routing
2020-06-30 16:54:54 -04:00
e7a4c08dea Now also properly routes in admin modules 2020-06-30 13:51:48 -07:00
69d639ee42 Hot fix for homepage routing 2020-06-30 13:42:35 -07:00
a780569a6f Merge pull request #41 from oqtane/master
sync
2020-06-30 16:16:11 -04:00
568c283efd Merge pull request #638 from PoisnFang/routing
Module Router Enhancement
2020-06-30 16:15:27 -04:00
fccdd07a08 Replaced token identifiers for { } 2020-06-30 12:59:19 -07:00
5e816ea912 Removed anchor property and hash is only set if there is anchor 2020-06-30 12:49:56 -07:00
cb2d529689 added in GetUrlParameters route to Module Index action 2020-06-30 04:16:08 -07:00
c5037e7084 Url parameters working on any page, plus queries and anchors 2020-06-30 03:41:35 -07:00
fdc39d57fb Module Router Enhancement
Allows for PageVariables through the URL
2020-06-27 11:49:24 -07:00
4960e2c668 Update README.md 2020-06-26 08:45:13 -04:00
66cc3a1392 Merge pull request #637 from sbwalker/master
improvements for custom authorization policy usage
2020-06-25 10:24:54 -04:00
6e7c8e7b05 improvements for custom authorization policy usage 2020-06-25 10:23:27 -04:00
727b943fa3 Merge pull request #636 from sbwalker/master
added ModuleControlBase
2020-06-25 09:32:56 -04:00
a4a0334ec0 added ModuleControlBase 2020-06-25 09:31:21 -04:00
99 changed files with 1114 additions and 510 deletions

2
.deployment Normal file
View File

@ -0,0 +1,2 @@
[config]
project = Oqtane.Server/Oqtane.Server.csproj

View File

@ -63,10 +63,18 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<Label For="retention-log" HelpText="What items do you want in the retention log">Retention Log (Items): </Label> <Label For="retention" HelpText="Number of log entries to retain for this job">Retention Log (Items): </Label>
</td> </td>
<td> <td>
<input id="retention-log" class="form-control" @bind="@_retentionHistory" /> <input id="retention" class="form-control" @bind="@_retentionHistory" />
</td>
</tr>
<tr>
<td>
<Label For="next" HelpText="Next execution for this job.">Next Execution: </Label>
</td>
<td>
<input id="next" class="form-control" @bind="@_nextExecution" />
</td> </td>
</tr> </tr>
</table> </table>
@ -83,6 +91,7 @@
private string _startDate = string.Empty; private string _startDate = string.Empty;
private string _endDate = string.Empty; private string _endDate = string.Empty;
private string _retentionHistory = string.Empty; private string _retentionHistory = string.Empty;
private string _nextExecution = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
@ -102,6 +111,7 @@
_startDate = (job.StartDate != null) ? job.StartDate.ToString() : string.Empty; _startDate = (job.StartDate != null) ? job.StartDate.ToString() : string.Empty;
_endDate = (job.EndDate != null) ? job.EndDate.ToString() : string.Empty; _endDate = (job.EndDate != null) ? job.EndDate.ToString() : string.Empty;
_retentionHistory = job.RetentionHistory.ToString(); _retentionHistory = job.RetentionHistory.ToString();
_nextExecution = job.NextExecution.ToString();
} }
} }
catch (Exception ex) catch (Exception ex)
@ -140,6 +150,15 @@
job.EndDate = DateTime.Parse(_endDate); job.EndDate = DateTime.Parse(_endDate);
} }
if (_nextExecution == string.Empty)
{
job.NextExecution = null;
}
else
{
job.NextExecution = DateTime.Parse(_nextExecution);
}
job.RetentionHistory = int.Parse(_retentionHistory); job.RetentionHistory = int.Parse(_retentionHistory);
try try

View File

@ -22,7 +22,7 @@ else
<td>@context.FinishDate</td> <td>@context.FinishDate</td>
</Row> </Row>
<Detail> <Detail>
<td colspan="4">@context.Notes</td> <td colspan="4">@((MarkupString)context.Notes)</td>
</Detail> </Detail>
</Pager> </Pager>
} }

View File

@ -79,7 +79,7 @@
{ {
ShowProgressIndicator(); ShowProgressIndicator();
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
await interop.RedirectBrowser(NavigateUrl(), 3); await interop.RedirectBrowser(NavigateUrl(), 10);
await ModuleDefinitionService.InstallModuleDefinitionsAsync(); await ModuleDefinitionService.InstallModuleDefinitionsAsync();
} }
catch (Exception ex) catch (Exception ex)

View File

@ -75,12 +75,20 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<Label For="license" HelpText="The license of the module">License: </Label> <Label For="license" HelpText="The module license terms">License: </Label>
</td> </td>
<td> <td>
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea> <textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
</td> </td>
</tr> </tr>
<tr>
<td>
<Label For="runtimes" HelpText="The Blazor runtimes which this module supports">Runtimes: </Label>
</td>
<td>
<input id="runtimes" class="form-control" @bind="@_runtimes" disabled />
</td>
</tr>
</table> </table>
</Section> </Section>
</TabPanel> </TabPanel>
@ -110,6 +118,7 @@
private string _url = ""; private string _url = "";
private string _contact = ""; private string _contact = "";
private string _license = ""; private string _license = "";
private string _runtimes = "";
private string _permissions; private string _permissions;
private string _createdby; private string _createdby;
private DateTime _createdon; private DateTime _createdon;
@ -139,6 +148,7 @@
_url = moduleDefinition.Url; _url = moduleDefinition.Url;
_contact = moduleDefinition.Contact; _contact = moduleDefinition.Contact;
_license = moduleDefinition.License; _license = moduleDefinition.License;
_runtimes = moduleDefinition.Runtimes;
_permissions = moduleDefinition.Permissions; _permissions = moduleDefinition.Permissions;
_createdby = moduleDefinition.CreatedBy; _createdby = moduleDefinition.CreatedBy;
_createdon = moduleDefinition.CreatedOn; _createdon = moduleDefinition.CreatedOn;

View File

@ -86,7 +86,7 @@ else
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", moduledefinitionname, version); await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", moduledefinitionname, version);
ShowProgressIndicator(); ShowProgressIndicator();
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
await interop.RedirectBrowser(NavigateUrl(), 3); await interop.RedirectBrowser(NavigateUrl(), 10);
await ModuleDefinitionService.InstallModuleDefinitionsAsync(); await ModuleDefinitionService.InstallModuleDefinitionsAsync();
} }
catch (Exception ex) catch (Exception ex)
@ -102,7 +102,7 @@ else
{ {
ShowProgressIndicator(); ShowProgressIndicator();
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
await interop.RedirectBrowser(NavigateUrl(), 3); await interop.RedirectBrowser(NavigateUrl(), 10);
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId); await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
} }
catch (Exception ex) catch (Exception ex)

View File

@ -31,9 +31,15 @@
{ {
try try
{ {
await ModuleService.ImportModuleAsync(ModuleState.ModuleId, _content); bool success = await ModuleService.ImportModuleAsync(ModuleState.ModuleId, _content);
StateHasChanged(); if (success)
NavigationManager.NavigateTo(NavigateUrl()); {
AddModuleMessage("Content Imported Successfully", MessageType.Success);
}
else
{
AddModuleMessage("A Problem Was Encountered Importing Content. Please Ensure The Content Is Formatted Correctly For The Module.", MessageType.Warning);
}
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -162,17 +162,6 @@
<input id="Icon" class="form-control" @bind="@_icon" /> <input id="Icon" class="form-control" @bind="@_icon" />
</td> </td>
</tr> </tr>
<tr>
<td>
<Label For="Default-Mode" HelpText="Select the default administration mode you want for this page">Default Mode? </Label>
</td>
<td>
<select id="Default-Mode" class="form-control" @bind="@_mode">
<option value="view">View Mode</option>
<option value="edit">Edit Mode</option>
</select>
</td>
</tr>
<tr> <tr>
<td> <td>
<Label For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content">Personalizable? </Label> <Label For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content">Personalizable? </Label>
@ -217,7 +206,6 @@
private string _isnavigation = "True"; private string _isnavigation = "True";
private string _url; private string _url;
private string _ispersonalizable = "False"; private string _ispersonalizable = "False";
private string _mode = "view";
private string _themetype = "-"; private string _themetype = "-";
private string _layouttype = "-"; private string _layouttype = "-";
private string _containertype = "-"; private string _containertype = "-";
@ -346,6 +334,12 @@
} }
} }
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
{
AddModuleMessage($"A page with path {_path} already exists for the selected parent page. The page path needs to be unique for the selected parent.", MessageType.Warning);
return;
}
Page child; Page child;
switch (_insert) switch (_insert)
{ {
@ -367,7 +361,6 @@
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation)); page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
page.Url = _url; page.Url = _url;
page.EditMode = (_mode == "edit" ? true : false);
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType) if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
{ {
@ -407,4 +400,8 @@
} }
} }
private static bool PagePathIsUnique(string pagePath, int siteId, List<Page> existingPages)
{
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath);
}
} }

View File

@ -173,17 +173,6 @@
<input id="Icon" class="form-control" @bind="@_icon" /> <input id="Icon" class="form-control" @bind="@_icon" />
</td> </td>
</tr> </tr>
<tr>
<td>
<Label For="Default-Mode" HelpText="Select the default administration mode you want for this page">Default Mode? </Label>
</td>
<td>
<select id="Default-Mode" class="form-control" @bind="@_mode">
<option value="view">View Mode</option>
<option value="edit">Edit Mode</option>
</select>
</td>
</tr>
<tr> <tr>
<td> <td>
<Label For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content">Personalizable? </Label> <Label For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content">Personalizable? </Label>
@ -235,7 +224,6 @@
private string _isnavigation; private string _isnavigation;
private string _url; private string _url;
private string _ispersonalizable; private string _ispersonalizable;
private string _mode;
private string _themetype = "-"; private string _themetype = "-";
private string _layouttype = "-"; private string _layouttype = "-";
private string _containertype = "-"; private string _containertype = "-";
@ -290,7 +278,6 @@
_isnavigation = page.IsNavigation.ToString(); _isnavigation = page.IsNavigation.ToString();
_url = page.Url; _url = page.Url;
_ispersonalizable = page.IsPersonalizable.ToString(); _ispersonalizable = page.IsPersonalizable.ToString();
_mode = (page.EditMode) ? "edit" : "view";
_themetype = page.ThemeType; _themetype = page.ThemeType;
if (_themetype == PageState.Site.DefaultThemeType) if (_themetype == PageState.Site.DefaultThemeType)
{ {
@ -433,6 +420,13 @@
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path); page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
} }
} }
if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList))
{
AddModuleMessage($"A page with path {_path} already exists for the selected parent page. The page path needs to be unique for the selected parent.", MessageType.Warning);
return;
}
if (_insert != "=") if (_insert != "=")
{ {
Page child; Page child;
@ -456,7 +450,6 @@
} }
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation)); page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
page.Url = _url; page.Url = _url;
page.EditMode = (_mode == "edit");
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType) if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
{ {
@ -512,4 +505,9 @@
AddModuleMessage("Error Saving Page", MessageType.Error); AddModuleMessage("Error Saving Page", MessageType.Error);
} }
} }
private static bool PagePathIsUnique(string pagePath, int siteId, int pageId, List<Page> existingPages)
{
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath && page.PageId != pageId);
}
} }

View File

@ -7,7 +7,7 @@
@inject IThemeService ThemeService @inject IThemeService ThemeService
@inject ISettingService SettingService @inject ISettingService SettingService
@if (_themes != null) @if (_initialized)
{ {
<table class="table table-borderless"> <table class="table table-borderless">
<tr> <tr>
@ -211,6 +211,7 @@
} }
@code { @code {
private bool _initialized = false;
private List<Theme> _themeList; private List<Theme> _themeList;
private List<ThemeControl> _themes = new List<ThemeControl>(); private List<ThemeControl> _themes = new List<ThemeControl>();
private List<ThemeControl> _layouts = new List<ThemeControl>(); private List<ThemeControl> _layouts = new List<ThemeControl>();
@ -318,6 +319,8 @@
_deletedby = site.DeletedBy; _deletedby = site.DeletedBy;
_deletedon = site.DeletedOn; _deletedon = site.DeletedOn;
_isdeleted = site.IsDeleted.ToString(); _isdeleted = site.IsDeleted.ToString();
_initialized = true;
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@ -6,7 +6,7 @@
@inject IAliasService AliasService @inject IAliasService AliasService
@inject IThemeService ThemeService @inject IThemeService ThemeService
@if (_themes != null) @if (_initialized)
{ {
<table class="table table-borderless"> <table class="table table-borderless">
<tr> <tr>
@ -106,6 +106,7 @@
} }
@code { @code {
private bool _initialized = false;
private List<Theme> _themeList; private List<Theme> _themeList;
private List<ThemeControl> _themes = new List<ThemeControl>(); private List<ThemeControl> _themes = new List<ThemeControl>();
private List<ThemeControl> _layouts = new List<ThemeControl>(); private List<ThemeControl> _layouts = new List<ThemeControl>();
@ -163,6 +164,8 @@
_deletedby = site.DeletedBy; _deletedby = site.DeletedBy;
_deletedon = site.DeletedOn; _deletedon = site.DeletedOn;
_isdeleted = site.IsDeleted.ToString(); _isdeleted = site.IsDeleted.ToString();
_initialized = true;
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@ -79,7 +79,7 @@
{ {
ShowProgressIndicator(); ShowProgressIndicator();
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
await interop.RedirectBrowser(NavigateUrl(), 3); await interop.RedirectBrowser(NavigateUrl(), 10);
await ThemeService.InstallThemesAsync(); await ThemeService.InstallThemesAsync();
} }
catch (Exception ex) catch (Exception ex)

View File

@ -87,7 +87,7 @@ else
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", themename, version); await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", themename, version);
ShowProgressIndicator(); ShowProgressIndicator();
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
await interop.RedirectBrowser(NavigateUrl(), 3); await interop.RedirectBrowser(NavigateUrl(), 10);
await ThemeService.InstallThemesAsync(); await ThemeService.InstallThemesAsync();
} }
catch (Exception ex) catch (Exception ex)
@ -103,7 +103,7 @@ else
{ {
ShowProgressIndicator(); ShowProgressIndicator();
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
await interop.RedirectBrowser(NavigateUrl(), 3); await interop.RedirectBrowser(NavigateUrl(), 10);
await ThemeService.DeleteThemeAsync(Theme.ThemeName); await ThemeService.DeleteThemeAsync(Theme.ThemeName);
} }
catch (Exception ex) catch (Exception ex)

View File

@ -12,7 +12,7 @@
@if (_upgradeavailable) @if (_upgradeavailable)
{ {
<ModuleMessage Type="MessageType.Info" Message="Select The Upgrade Button To Install a New Framework Version"></ModuleMessage> <ModuleMessage Type="MessageType.Info" Message="Select The Upgrade Button To Install a New Framework Version"></ModuleMessage>
@("Framework") @_package.Version <button type="button" class="btn btn-success" @onclick=@(async () => await Download(Constants.PackageId, Constants.Version))>Upgrade</button> <button type="button" class="btn btn-success" @onclick=@(async () => await Download(Constants.PackageId, @_package.Version))>Upgrade To @_package.Version</button>
} }
else else
{ {
@ -26,7 +26,7 @@
<Label HelpText="Upload a framework package and select Install to complete the installation">Framework: </Label> <Label HelpText="Upload a framework package and select Install to complete the installation">Framework: </Label>
</td> </td>
<td> <td>
<FileManager Filter="nupkg" Folder="Framework" /> <FileManager Filter="nupkg" ShowFiles="false" Folder="Framework" />
</td> </td>
</tr> </tr>
</table> </table>
@ -71,7 +71,7 @@
{ {
ShowProgressIndicator(); ShowProgressIndicator();
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
await interop.RedirectBrowser(NavigateUrl(), 3); await interop.RedirectBrowser(NavigateUrl(), 10);
await InstallationService.Upgrade(); await InstallationService.Upgrade();
} }
catch (Exception ex) catch (Exception ex)
@ -88,7 +88,7 @@
await PackageService.DownloadPackageAsync(packageid, version, "Framework"); await PackageService.DownloadPackageAsync(packageid, version, "Framework");
ShowProgressIndicator(); ShowProgressIndicator();
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
await interop.RedirectBrowser(NavigateUrl(), 3); await interop.RedirectBrowser(NavigateUrl(), 10);
await InstallationService.Upgrade(); await InstallationService.Upgrade();
} }
catch (Exception ex) catch (Exception ex)

View File

@ -1,6 +1,6 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
@if (_visible) @if (_visible)
{ {
<div class="app-admin-modal"> <div class="app-admin-modal">
@ -40,7 +40,7 @@
@code { @code {
private bool _visible = false; private bool _visible = false;
private bool _editmode = true; private bool _editmode = false;
private bool _authorized = false; private bool _authorized = false;
private string _iconSpan = string.Empty; private string _iconSpan = string.Empty;
@ -66,7 +66,7 @@
public bool Disabled { get; set; } // optional public bool Disabled { get; set; } // optional
[Parameter] [Parameter]
public string EditMode { get; set; } // optional - specifies if a user must be in edit mode to see the action - default is true public string EditMode { get; set; } // optional - specifies if an authorized user must be in edit mode to see the action - default is false
[Parameter] [Parameter]
public Action OnClick { get; set; } // required if an Action is specified - executes a method in the calling component public Action OnClick { get; set; } // required if an Action is specified - executes a method in the calling component
@ -84,6 +84,7 @@
{ {
Class = "btn btn-success"; Class = "btn btn-success";
} }
if (!string.IsNullOrEmpty(EditMode)) if (!string.IsNullOrEmpty(EditMode))
{ {
_editmode = bool.Parse(EditMode); _editmode = bool.Parse(EditMode);

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
@inject IUserService UserService @inject IUserService UserService
@if (_authorized) @if (_authorized)
@ -21,7 +20,7 @@
private string _parameters = string.Empty; private string _parameters = string.Empty;
private string _classname = "btn btn-primary"; private string _classname = "btn btn-primary";
private string _style = string.Empty; private string _style = string.Empty;
private bool _editmode = true; private bool _editmode = false;
private bool _authorized = false; private bool _authorized = false;
private string _iconSpan = string.Empty; private string _iconSpan = string.Empty;
@ -47,7 +46,7 @@
public bool Disabled { get; set; } // optional public bool Disabled { get; set; } // optional
[Parameter] [Parameter]
public string EditMode { get; set; } // optional - specifies if a user must be in edit mode to see the action - default is true public string EditMode { get; set; } // optional - specifies if an authorized user must be in edit mode to see the action - default is false.
[Parameter] [Parameter]
public string IconName { get; set; } // optional - specifies an icon for the link - default is no icon public string IconName { get; set; } // optional - specifies an icon for the link - default is no icon

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
@if (_text != string.Empty) @if (_text != string.Empty)
{ {

View File

@ -1,7 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
@inject IFolderService FolderService @inject IFolderService FolderService
@inject IFileService FileService @inject IFileService FileService
@ -65,7 +63,7 @@
<span id="@_progressinfoid"></span><progress id="@_progressbarid" style="width: 150px; visibility: hidden;"></progress> <span id="@_progressinfoid"></span><progress id="@_progressbarid" style="width: 150px; visibility: hidden;"></progress>
<span class="float-right"> <span class="float-right">
<button type="button" class="btn btn-success" @onclick="UploadFile">Upload</button> <button type="button" class="btn btn-success" @onclick="UploadFile">Upload</button>
@if (_showfiles && GetFileId() != -1) @if (ShowFiles && GetFileId() != -1)
{ {
<button type="button" class="btn btn-danger" @onclick="DeleteFile">Delete</button> <button type="button" class="btn btn-danger" @onclick="DeleteFile">Delete</button>
} }
@ -88,7 +86,6 @@
private string _id; private string _id;
private List<Folder> _folders; private List<Folder> _folders;
private List<File> _files = new List<File>(); private List<File> _files = new List<File>();
private bool _showfiles = true;
private string _fileinputid = string.Empty; private string _fileinputid = string.Empty;
private string _progressinfoid = string.Empty; private string _progressinfoid = string.Empty;
private string _progressbarid = string.Empty; private string _progressbarid = string.Empty;

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
@if (!string.IsNullOrEmpty(HelpText)) @if (!string.IsNullOrEmpty(HelpText))
{ {

View File

@ -1,10 +1,16 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore] @inject NavigationManager NavigationManager
@if (!string.IsNullOrEmpty(_message)) @if (!string.IsNullOrEmpty(_message))
{ {
<div class="@_classname" role="alert">@_message</div> <div class="@_classname" role="alert">
@_message
@if (Type == MessageType.Error && UserSecurity.IsAuthorized(PageState.User, Constants.HostRole))
{
@((MarkupString)"&nbsp;&nbsp;")<NavLink href="@NavigateUrl("admin/log")">View Details</NavLink>
}
</div>
<br /> <br />
} }

View File

@ -1,9 +1,7 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
@typeparam TableItem @typeparam TableItem
<p> <p>
@if (Format == "Table") @if (Format == "Table")
{ {

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
@inject IRoleService RoleService @inject IRoleService RoleService
@inject IUserService UserService @inject IUserService UserService

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
<div class="row" style="margin-bottom: 50px;"> <div class="row" style="margin-bottom: 50px;">
<div class="col"> <div class="col">

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
<div class="d-flex"> <div class="d-flex">
<div> <div>

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
@if (Name == Parent.ActiveTab) @if (Name == Parent.ActiveTab)
{ {

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleControlBase
@attribute [OqtaneIgnore]
<CascadingValue Value="this"> <CascadingValue Value="this">
<div class="container-fluid"> <div class="container-fluid">

View File

@ -1,4 +1,5 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleControlBase
<img src="@_src" title="@_title" @onclick="SetValue" /> <img src="@_src" title="@_title" @onclick="SetValue" />

View File

@ -7,7 +7,7 @@
@if (PageState.EditMode) @if (PageState.EditMode)
{ {
<br /><ActionLink Action="Edit" /><br /><br /> <br /><ActionLink Action="Edit" EditMode="true" /><br /><br />
} }
@code { @code {

View File

@ -21,23 +21,23 @@ namespace Oqtane.Modules.HtmlText.Services
public async Task<HtmlTextInfo> GetHtmlTextAsync(int moduleId) public async Task<HtmlTextInfo> GetHtmlTextAsync(int moduleId)
{ {
var htmltext = await GetJsonAsync<List<HtmlTextInfo>>($"{ApiUrl}/{moduleId}?entityid={moduleId}"); var htmltext = await GetJsonAsync<List<HtmlTextInfo>>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
return htmltext.FirstOrDefault(); return htmltext.FirstOrDefault();
} }
public async Task AddHtmlTextAsync(HtmlTextInfo htmlText) public async Task AddHtmlTextAsync(HtmlTextInfo htmlText)
{ {
await PostJsonAsync($"{ApiUrl}?entityid={htmlText.ModuleId}", htmlText); await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", htmlText.ModuleId), htmlText);
} }
public async Task UpdateHtmlTextAsync(HtmlTextInfo htmlText) public async Task UpdateHtmlTextAsync(HtmlTextInfo htmlText)
{ {
await PutJsonAsync($"{ApiUrl}/{htmlText.HtmlTextId}?entityid={htmlText.ModuleId}", htmlText); await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", htmlText.ModuleId), htmlText);
} }
public async Task DeleteHtmlTextAsync(int moduleId) public async Task DeleteHtmlTextAsync(int moduleId)
{ {
await DeleteAsync($"{ApiUrl}/{moduleId}?entityid={moduleId}"); await DeleteAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
} }
} }
} }

View File

@ -116,6 +116,54 @@ namespace Oqtane.Modules
return Utilities.ContentUrl(PageState.Alias, fileid); return Utilities.ContentUrl(PageState.Alias, fileid);
} }
public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "")
{
var urlParameters = new Dictionary<string, string>();
string[] templateSegments;
var parameters = PageState.UrlParameters.Split('/', StringSplitOptions.RemoveEmptyEntries);
var parameterId = 0;
if (string.IsNullOrEmpty(parametersTemplate))
{
for (int i = 0; i < parameters.Length; i++)
{
urlParameters.TryAdd("parameter" + i, parameters[i]);
}
}
else
{
templateSegments = parametersTemplate.Split('/', StringSplitOptions.RemoveEmptyEntries);
if (parameters.Length == templateSegments.Length)
{
for (int i = 0; i < parameters.Length; i++)
{
if (parameters.Length > i)
{
if (templateSegments[i] == parameters[i])
{
urlParameters.TryAdd("parameter" + parameterId, parameters[i]);
parameterId++;
}
else if (templateSegments[i].StartsWith("{") && templateSegments[i].EndsWith("}"))
{
var key = templateSegments[i].Replace("{", "");
key = key.Replace("}", "");
urlParameters.TryAdd(key, parameters[i]);
}
else
{
i = parameters.Length;
urlParameters.Clear();
}
}
}
}
}
return urlParameters;
}
// user feedback methods // user feedback methods
public void AddModuleMessage(string message, MessageType type) public void AddModuleMessage(string message, MessageType type)
{ {
@ -154,12 +202,15 @@ namespace Oqtane.Modules
case "add": case "add":
logFunction = LogFunction.Create; logFunction = LogFunction.Create;
break; break;
case "edit": case "edit":
logFunction = LogFunction.Update; logFunction = LogFunction.Update;
break; break;
case "delete": case "delete":
logFunction = LogFunction.Delete; logFunction = LogFunction.Delete;
break; break;
default: default:
logFunction = LogFunction.Read; logFunction = LogFunction.Read;
break; break;

View File

@ -0,0 +1,10 @@
using Oqtane.Shared;
namespace Oqtane.Modules
{
[OqtaneIgnore]
public abstract class ModuleControlBase : ModuleBase
{
}
}

View File

@ -6,7 +6,7 @@
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<RazorLangVersion>3.0</RazorLangVersion> <RazorLangVersion>3.0</RazorLangVersion>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<Version>1.0.1</Version> <Version>1.0.3</Version>
<Product>Oqtane</Product> <Product>Oqtane</Product>
<Authors>Shaun Walker</Authors> <Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company> <Company>.NET Foundation</Company>
@ -15,7 +15,7 @@
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl> <PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl> <RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes> <PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
<RootNamespace>Oqtane</RootNamespace> <RootNamespace>Oqtane</RootNamespace>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
</PropertyGroup> </PropertyGroup>

View File

@ -170,6 +170,19 @@ namespace Oqtane.Services
// can be used to override the default alias // can be used to override the default alias
public Alias Alias { get; set; } public Alias Alias { get; set; }
// add entityid parameter to url for custom authorization policy
public string CreateAuthorizationPolicyUrl(string url, int entityId)
{
if (url.Contains("?"))
{
return url + "&entityid=" + entityId.ToString();
}
else
{
return url + "?entityid=" + entityId.ToString();
}
}
[Obsolete("This method is obsolete. Use CreateApiUrl(Alias alias, string serviceName) instead.", false)] [Obsolete("This method is obsolete. Use CreateApiUrl(Alias alias, string serviceName) instead.", false)]
public string CreateApiUrl(Alias alias, string absoluteUri, string serviceName) public string CreateApiUrl(Alias alias, string absoluteUri, string serviceName)
{ {

View File

@ -126,10 +126,13 @@
@foreach (var moduledefinition in _moduleDefinitions) @foreach (var moduledefinition in _moduleDefinitions)
{ {
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, moduledefinition.Permissions)) if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, moduledefinition.Permissions))
{
if (moduledefinition.Runtimes == "" || moduledefinition.Runtimes.Contains(PageState.Runtime.ToString()))
{ {
<option value="@moduledefinition.ModuleDefinitionName">@moduledefinition.Name</option> <option value="@moduledefinition.ModuleDefinitionName">@moduledefinition.Name</option>
} }
} }
}
</select> </select>
@((MarkupString) Description) @((MarkupString) Description)
} }
@ -195,14 +198,6 @@
} }
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) || (PageState.Page.IsPersonalizable && PageState.User != null)) @if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) || (PageState.Page.IsPersonalizable && PageState.User != null))
{
@if (PageState.Page.EditMode)
{
<button type="button" class="btn @ButtonClass active" aria-pressed="true" autocomplete="off">
<span class="oi oi-pencil"></span>
</button>
}
else
{ {
if (PageState.EditMode) if (PageState.EditMode)
{ {
@ -217,7 +212,6 @@
</button> </button>
} }
} }
}
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions)) @if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
{ {

View File

@ -2,7 +2,7 @@
@inherits ModuleActionsBase @inherits ModuleActionsBase
@attribute [OqtaneIgnore] @attribute [OqtaneIgnore]
@if (PageState.EditMode && !PageState.Page.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions)) @if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions))
{ {
<div class="app-moduleactions"> <div class="app-moduleactions">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"></a> <a class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"></a>
@ -15,7 +15,18 @@
} }
else else
{ {
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">@action.Name</a> <a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">
@if (string.IsNullOrEmpty(action.Icon))
{
@((MarkupString) "&nbsp;&nbsp;");
}
else
{
<span class="oi oi-@action.Icon" aria-hidden="true"></span>
}
&nbsp;
@action.Name
</a>
} }
} }
</div> </div>

View File

@ -19,7 +19,7 @@ namespace Oqtane.Themes.Controls
[Inject] public IPageModuleService PageModuleService { get; set; } [Inject] public IPageModuleService PageModuleService { get; set; }
[Inject] public IModuleService ModuleService { get; set; } [Inject] public IModuleService ModuleService { get; set; }
protected List<ActionViewModel> Actions; public List<ActionViewModel> Actions;
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
@ -31,51 +31,52 @@ namespace Oqtane.Themes.Controls
var actionList = new List<ActionViewModel>(); var actionList = new List<ActionViewModel>();
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions)) if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions))
{ {
actionList.Add(new ActionViewModel {Name = "Manage Settings", Action = async (u, m) => await Settings(u, m)}); actionList.Add(new ActionViewModel {Icon = Icons.Cog, Name = "Manage Settings", Action = async (u, m) => await Settings(u, m)});
if (UserSecurity.GetPermissionStrings(ModuleState.Permissions).FirstOrDefault(item => item.PermissionName == PermissionNames.View).Permissions.Split(';').Contains(Constants.AllUsersRole)) if (UserSecurity.GetPermissionStrings(ModuleState.Permissions).FirstOrDefault(item => item.PermissionName == PermissionNames.View).Permissions.Split(';').Contains(Constants.AllUsersRole))
{ {
actionList.Add(new ActionViewModel { Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) }); actionList.Add(new ActionViewModel {Icon=Icons.CircleX, Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) });
} }
else else
{ {
actionList.Add(new ActionViewModel { Name = "Publish Module", Action = async (s, m) => await Publish(s, m) }); actionList.Add(new ActionViewModel {Icon=Icons.CircleCheck, Name = "Publish Module", Action = async (s, m) => await Publish(s, m) });
} }
actionList.Add(new ActionViewModel { Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) }); actionList.Add(new ActionViewModel {Icon=Icons.Trash, Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) });
if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "") if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "")
{ {
actionList.Add(new ActionViewModel { Name = "" }); actionList.Add(new ActionViewModel { Name = "" });
actionList.Add(new ActionViewModel {Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import")}); actionList.Add(new ActionViewModel {Icon=Icons.CloudUpload, Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import")});
actionList.Add(new ActionViewModel {Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export")}); actionList.Add(new ActionViewModel {Icon = Icons.CloudDownload, Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export")});
} }
actionList.Add(new ActionViewModel {Name = ""}); actionList.Add(new ActionViewModel {Name = ""});
if (ModuleState.PaneModuleIndex > 0) if (ModuleState.PaneModuleIndex > 0)
{ {
actionList.Add(new ActionViewModel {Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m)}); actionList.Add(new ActionViewModel {Icon = Icons.DataTransferUpload ,Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m)});
} }
if (ModuleState.PaneModuleIndex > 0) if (ModuleState.PaneModuleIndex > 0)
{ {
actionList.Add(new ActionViewModel {Name = "Move Up", Action = async (s, m) => await MoveUp(s, m)}); actionList.Add(new ActionViewModel {Icon = Icons.ArrowThickTop, Name = "Move Up", Action = async (s, m) => await MoveUp(s, m)});
} }
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1)) if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
{ {
actionList.Add(new ActionViewModel {Name = "Move Down", Action = async (s, m) => await MoveDown(s, m)}); actionList.Add(new ActionViewModel {Icon = Icons.ArrowThickBottom, Name = "Move Down", Action = async (s, m) => await MoveDown(s, m)});
} }
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1)) if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
{ {
actionList.Add(new ActionViewModel {Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)}); actionList.Add(new ActionViewModel {Icon = Icons.DataTransferDownload, Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)});
} }
foreach (string pane in PageState.Page.Panes) foreach (string pane in PageState.Page.Panes)
{ {
if (pane != ModuleState.Pane) if (pane != ModuleState.Pane)
{ {
actionList.Add(new ActionViewModel {Name = "Move To " + pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m)}); actionList.Add(new ActionViewModel {Icon = Icons.AccountLogin, Name = "Move To " + pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m)});
} }
} }
} }
@ -202,8 +203,8 @@ namespace Oqtane.Themes.Controls
public class ActionViewModel public class ActionViewModel
{ {
public string Icon { get; set; }
public string Name { set; get; } public string Name { set; get; }
public Func<string, PageModule, Task<string>> Action { set; get; } public Func<string, PageModule, Task<string>> Action { set; get; }
} }
} }

View File

@ -19,7 +19,7 @@
{ {
_moduleState = Module; // passed in from Pane component _moduleState = Module; // passed in from Pane component
string container = _moduleState.ContainerType; string container = _moduleState.ContainerType;
if (PageState.ModuleId != -1 && PageState.Action != "" && _moduleState.UseAdminContainer) if (PageState.ModuleId != -1 && _moduleState.UseAdminContainer)
{ {
container = Constants.DefaultAdminContainer; container = Constants.DefaultAdminContainer;
} }

View File

@ -14,6 +14,7 @@ namespace Oqtane.UI
public List<Module> Modules { get; set; } public List<Module> Modules { get; set; }
public Uri Uri { get; set; } public Uri Uri { get; set; }
public Dictionary<string, string> QueryString { get; set; } public Dictionary<string, string> QueryString { get; set; }
public string UrlParameters { get; set; }
public int ModuleId { get; set; } public int ModuleId { get; set; }
public string Action { get; set; } public string Action { get; set; }
public bool EditMode { get; set; } public bool EditMode { get; set; }

View File

@ -1,4 +1,5 @@
@namespace Oqtane.UI @using Microsoft.AspNetCore.Components.Rendering
@namespace Oqtane.UI
@inject IUserService UserService @inject IUserService UserService
@inject IModuleService ModuleService @inject IModuleService ModuleService
@inject IModuleDefinitionService ModuleDefinitionService @inject IModuleDefinitionService ModuleDefinitionService
@ -25,7 +26,7 @@
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
if (PageState.EditMode && !PageState.Page.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions) && Name != Constants.AdminPane) if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions) && Name != Constants.AdminPane)
{ {
_paneadminborder = "app-pane-admin-border"; _paneadminborder = "app-pane-admin-border";
_panetitle = "<div class=\"app-pane-admin-title\">" + Name + " Pane</div>"; _panetitle = "<div class=\"app-pane-admin-title\">" + Name + " Pane</div>";
@ -38,12 +39,12 @@
DynamicComponent = builder => DynamicComponent = builder =>
{ {
if (PageState.ModuleId != -1 && PageState.Action != "") if (PageState.ModuleId != -1 && PageState.Action != Constants.DefaultAction)
{ {
if (Name.ToLower() == Constants.AdminPane.ToLower()) if (Name.ToLower() == Constants.AdminPane.ToLower())
{ {
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId); Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
if (module != null) if (module != null && !module.IsDeleted)
{ {
var typename = module.ModuleType; var typename = module.ModuleType;
// check for core module actions component // check for core module actions component
@ -88,10 +89,7 @@
{ {
module.Title = module.ControlTitle; module.Title = module.ControlTitle;
} }
CreateComponent(builder, module);
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
builder.AddAttribute(1, "Module", module);
builder.CloseComponent();
} }
} }
else else
@ -106,14 +104,12 @@
if (PageState.ModuleId != -1) if (PageState.ModuleId != -1)
{ {
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId); Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
if (module != null && module.Pane.ToLower() == Name.ToLower()) if (module != null && module.Pane.ToLower() == Name.ToLower() && !module.IsDeleted)
{ {
// check if user is authorized to view module // check if user is authorized to view module
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.Permissions)) if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.Permissions))
{ {
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent)); CreateComponent(builder, module);
builder.AddAttribute(1, "Module", module);
builder.CloseComponent();
} }
} }
} }
@ -124,14 +120,19 @@
// check if user is authorized to view module // check if user is authorized to view module
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.Permissions)) if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.Permissions))
{ {
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent)); CreateComponent(builder, module);
builder.AddAttribute(1, "Module", module);
builder.SetKey(module.PageModuleId);
builder.CloseComponent();
} }
} }
} }
} }
}; };
} }
private void CreateComponent(RenderTreeBuilder builder, Module module)
{
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
builder.AddAttribute(1, "Module", module);
builder.SetKey(module.PageModuleId);
builder.CloseComponent();
}
} }

View File

@ -76,7 +76,8 @@
User user = null; User user = null;
List<Module> modules; List<Module> modules;
var moduleid = -1; var moduleid = -1;
var action = ""; var action = string.Empty;
var urlparameters = string.Empty;
var editmode = false; var editmode = false;
var reload = Reload.None; var reload = Reload.None;
var lastsyncdate = DateTime.UtcNow; var lastsyncdate = DateTime.UtcNow;
@ -179,23 +180,62 @@
// extract admin route elements from path // extract admin route elements from path
var segments = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); var segments = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
int result; int result;
// check if path has moduleid and action specification ie. pagename/moduleid/action/
if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result)) int modIdPos = 0;
int actionPos = 0;
int urlParametersPos = 0;
for (int i = 0; i < segments.Length; i++)
{ {
action = segments[segments.Length - 1];
moduleid = result; if (segments[i] == Constants.UrlParametersDelimiter)
path = path.Replace(moduleid.ToString() + "/" + action + "/", ""); {
urlParametersPos = i + 1;
}
if (i >= urlParametersPos && urlParametersPos != 0)
{
urlparameters += "/" + segments[i];
}
if (segments[i] == Constants.ModuleDelimiter)
{
modIdPos = i + 1;
actionPos = modIdPos + 1;
if (actionPos > segments.Length - 1)
{
action = Constants.DefaultAction;
} }
else else
{ {
// check if path has moduleid specification ie. pagename/moduleid/ action = segments[actionPos];
if (segments.Length >= 1 && int.TryParse(segments[segments.Length - 1], out result))
{
moduleid = result;
path = path.Replace(moduleid.ToString() + "/", "");
} }
} }
}
// check if path has moduleid and action specification ie. pagename/moduleid/action/
if (modIdPos > 0)
{
int.TryParse(segments[modIdPos], out result);
moduleid = result;
if (actionPos > segments.Length - 1)
{
path = path.Replace(segments[modIdPos - 1] + "/" + segments[modIdPos] + "/", "");
}
else
{
path = path.Replace(segments[modIdPos - 1] + "/" + segments[modIdPos] + "/" + segments[actionPos] + "/", "");
}
}
if (urlParametersPos > 0)
{
path = path.Replace(segments[urlParametersPos - 1] + urlparameters + "/", "");
}
// remove trailing slash so it can be used as a key for Pages // remove trailing slash so it can be used as a key for Pages
if (path.EndsWith("/")) path = path.Substring(0, path.Length - 1); if (path.EndsWith("/")) path = path.Substring(0, path.Length - 1);
@ -220,17 +260,14 @@
{ {
page = pages.Where(item => item.Path == path).FirstOrDefault(); page = pages.Where(item => item.Path == path).FirstOrDefault();
reload = Reload.Page; reload = Reload.Page;
if (page != null) editmode = false;
{
editmode = page.EditMode;
}
} }
if (page != null) if (page != null)
{ {
if (PageState == null) if (PageState == null)
{ {
editmode = page.EditMode; editmode = false;
} }
// check if user is authorized to view page // check if user is authorized to view page
@ -263,6 +300,7 @@
Modules = modules, Modules = modules,
Uri = new Uri(_absoluteUri, UriKind.Absolute), Uri = new Uri(_absoluteUri, UriKind.Absolute),
QueryString = querystring, QueryString = querystring,
UrlParameters = urlparameters,
ModuleId = moduleid, ModuleId = moduleid,
Action = action, Action = action,
EditMode = editmode, EditMode = editmode,
@ -360,6 +398,13 @@
string panes = ""; string panes = "";
Type themetype = Type.GetType(page.ThemeType); Type themetype = Type.GetType(page.ThemeType);
if (themetype == null)
{
// fallback
page.ThemeType = Constants.DefaultTheme;
page.LayoutType = Constants.DefaultLayout;
themetype = Type.GetType(Constants.DefaultTheme);
}
if (themetype != null) if (themetype != null)
{ {
var themeobject = Activator.CreateInstance(themetype) as IThemeControl; var themeobject = Activator.CreateInstance(themetype) as IThemeControl;
@ -401,7 +446,7 @@
if (module.PageId == page.PageId || module.ModuleId == moduleid) if (module.PageId == page.PageId || module.ModuleId == moduleid)
{ {
var typename = string.Empty; var typename = string.Empty;
if (module.ModuleDefinition != null) if (module.ModuleDefinition != null && (module.ModuleDefinition.Runtimes == "" || module.ModuleDefinition.Runtimes.Contains(GetRuntime().ToString())))
{ {
typename = module.ModuleDefinition.ControlTypeTemplate; typename = module.ModuleDefinition.ControlTypeTemplate;
} }

View File

@ -54,11 +54,6 @@
DynamicComponent = builder => DynamicComponent = builder =>
{ {
var themeType = Type.GetType(PageState.Page.ThemeType); var themeType = Type.GetType(PageState.Page.ThemeType);
if (themeType == null)
{
// fallback
themeType = Type.GetType(Constants.DefaultTheme);
}
builder.OpenComponent(0, themeType); builder.OpenComponent(0, themeType);
builder.CloseComponent(); builder.CloseComponent();
}; };

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>Oqtane.Client</id> <id>Oqtane.Client</id>
<version>1.0.1</version> <version>1.0.3</version>
<authors>Shaun Walker</authors> <authors>Shaun Walker</authors>
<owners>.NET Foundation</owners> <owners>.NET Foundation</owners>
<title>Oqtane Framework</title> <title>Oqtane Framework</title>
@ -13,7 +13,7 @@
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl> <projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl> <iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
<tags>oqtane</tags> <tags>oqtane</tags>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes> <releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</releaseNotes>
<summary>A modular application framework for Blazor</summary> <summary>A modular application framework for Blazor</summary>
</metadata> </metadata>
<files> <files>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>Oqtane.Framework</id> <id>Oqtane.Framework</id>
<version>1.0.1</version> <version>1.0.3</version>
<authors>Shaun Walker</authors> <authors>Shaun Walker</authors>
<owners>.NET Foundation</owners> <owners>.NET Foundation</owners>
<title>Oqtane Framework</title> <title>Oqtane Framework</title>
@ -13,16 +13,11 @@
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl> <projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl> <iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
<tags>oqtane framework</tags> <tags>oqtane framework</tags>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes> <releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</releaseNotes>
<summary>A modular application framework for Blazor</summary> <summary>A modular application framework for Blazor</summary>
</metadata> </metadata>
<files> <files>
<file src="..\Oqtane.Client\bin\Release\netstandard2.1\Oqtane.Client.dll" target="lib\netcoreapp3.1" /> <file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\*.*" target="lib\netcoreapp3.1" />
<file src="..\Oqtane.Client\bin\Release\netstandard2.1\Oqtane.Client.pdb" target="lib\netcoreapp3.1" /> <file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\wwwroot\**\*.*" target="wwwroot" />
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Server.dll" target="lib\netcoreapp3.1" />
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Server.pdb" target="lib\netcoreapp3.1" />
<file src="..\Oqtane.Shared\bin\Release\netstandard2.1\Oqtane.Shared.dll" target="lib\netcoreapp3.1" />
<file src="..\Oqtane.Shared\bin\Release\netstandard2.1\Oqtane.Shared.pdb" target="lib\netcoreapp3.1" />
<file src="..\Oqtane.Server\wwwroot\**\*.*" target="wwwroot" />
</files> </files>
</package> </package>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>Oqtane.Server</id> <id>Oqtane.Server</id>
<version>1.0.1</version> <version>1.0.3</version>
<authors>Shaun Walker</authors> <authors>Shaun Walker</authors>
<owners>.NET Foundation</owners> <owners>.NET Foundation</owners>
<title>Oqtane Framework</title> <title>Oqtane Framework</title>
@ -13,7 +13,7 @@
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl> <projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl> <iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
<tags>oqtane</tags> <tags>oqtane</tags>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes> <releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</releaseNotes>
<summary>A modular application framework for Blazor</summary> <summary>A modular application framework for Blazor</summary>
</metadata> </metadata>
<files> <files>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>Oqtane.Shared</id> <id>Oqtane.Shared</id>
<version>1.0.1</version> <version>1.0.3</version>
<authors>Shaun Walker</authors> <authors>Shaun Walker</authors>
<owners>.NET Foundation</owners> <owners>.NET Foundation</owners>
<title>Oqtane Framework</title> <title>Oqtane Framework</title>
@ -13,7 +13,7 @@
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl> <projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl> <iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
<tags>oqtane</tags> <tags>oqtane</tags>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes> <releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</releaseNotes>
<summary>A modular application framework for Blazor</summary> <summary>A modular application framework for Blazor</summary>
</metadata> </metadata>
<files> <files>

View File

@ -0,0 +1 @@
Compress-Archive -Path "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\*" -DestinationPath "..\Oqtane.Server\bin\Release\Oqtane.Framework.1.0.3.Install.zip" -Force

Binary file not shown.

View File

@ -1,5 +1,18 @@
DEL "*.nupkg" del "*.nupkg"
dotnet clean -c Release ..\Oqtane.sln dotnet clean -c Release ..\Oqtane.sln
dotnet build -c Release ..\Oqtane.sln dotnet build -c Release ..\Oqtane.sln
dotnet pack -o .\ -c Release ..\Oqtane.sln nuget.exe pack Oqtane.Client.nuspec
nuget.exe pack Oqtane.Server.nuspec
nuget.exe pack Oqtane.Shared.nuspec
del /F/Q/S "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish" > NUL
rmdir /Q/S "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish"
dotnet publish ..\Oqtane.Server\Oqtane.Server.csproj /p:Configuration=Release
del "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\appsettings.json"
ren "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\appsettings.release.json" "appsettings.json"
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\install.ps1"
del "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\appsettings.json"
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\upgrade.ps1"
del "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\Oqtane.Upgrade.*"
nuget.exe pack Oqtane.Framework.nuspec nuget.exe pack Oqtane.Framework.nuspec

View File

@ -0,0 +1 @@
Compress-Archive -Path "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\*" -DestinationPath "..\Oqtane.Server\bin\Release\Oqtane.Framework.1.0.3.Upgrade.zip" -Force

View File

@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -483,7 +483,7 @@ namespace Oqtane.Controllers
string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries); string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries);
foreach (string folder in folders) foreach (string folder in folders)
{ {
path = Utilities.PathCombine(path, folder, "\\"); path = Utilities.PathCombine(path, folder, Path.DirectorySeparatorChar.ToString());
if (!Directory.Exists(path)) if (!Directory.Exists(path))
{ {
Directory.CreateDirectory(path); Directory.CreateDirectory(path);

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Oqtane.Models; using Oqtane.Models;
@ -112,7 +113,7 @@ namespace Oqtane.Controllers
Folder parent = _folders.GetFolder(folder.ParentId.Value); Folder parent = _folders.GetFolder(folder.ParentId.Value);
folder.Path = Utilities.PathCombine(parent.Path, folder.Name); folder.Path = Utilities.PathCombine(parent.Path, folder.Name);
} }
folder.Path = Utilities.PathCombine(folder.Path, "\\"); folder.Path = Utilities.PathCombine(folder.Path, Path.DirectorySeparatorChar.ToString());
folder = _folders.AddFolder(folder); folder = _folders.AddFolder(folder);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Added {Folder}", folder); _logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Added {Folder}", folder);
} }
@ -147,7 +148,7 @@ namespace Oqtane.Controllers
Folder parent = _folders.GetFolder(folder.ParentId.Value); Folder parent = _folders.GetFolder(folder.ParentId.Value);
folder.Path = Utilities.PathCombine(parent.Path, folder.Name); folder.Path = Utilities.PathCombine(parent.Path, folder.Name);
} }
folder.Path = Utilities.PathCombine(folder.Path, "\\"); folder.Path = Utilities.PathCombine(folder.Path, Path.DirectorySeparatorChar.ToString());
folder = _folders.UpdateFolder(folder); folder = _folders.UpdateFolder(folder);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Updated {Folder}", folder); _logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Updated {Folder}", folder);
} }

View File

@ -122,7 +122,7 @@ namespace Oqtane.Controllers
var pages = _pages.GetPages(module.SiteId).ToList(); var pages = _pages.GetPages(module.SiteId).ToList();
foreach (Page page in pages) foreach (Page page in pages)
{ {
if (page.PageId != pageModule.PageId && !page.EditMode) if (page.PageId != pageModule.PageId && !page.Path.StartsWith("admin/"))
{ {
_pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType }); _pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType });
} }

View File

@ -0,0 +1,21 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Oqtane.Infrastructure;
namespace Oqtane.Controllers
{
public class ModuleControllerBase : Controller
{
protected readonly ILogManager _logger;
protected int _entityId = -1; // passed as a querystring parameter for policy authorization and used for validation
public ModuleControllerBase(ILogManager logger, IHttpContextAccessor accessor)
{
_logger = logger;
if (accessor.HttpContext.Request.Query.ContainsKey("entityid"))
{
_entityId = int.Parse(accessor.HttpContext.Request.Query["entityid"]);
}
}
}
}

View File

@ -94,8 +94,8 @@ namespace Oqtane.Controllers
[Authorize(Roles = Constants.HostRole)] [Authorize(Roles = Constants.HostRole)]
public void InstallModules() public void InstallModules()
{ {
_installationManager.InstallPackages("Modules", true);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Modules Installed"); _logger.Log(LogLevel.Information, this, LogFunction.Create, "Modules Installed");
_installationManager.InstallPackages("Modules", true);
} }
// DELETE api/<controller>/5?siteid=x // DELETE api/<controller>/5?siteid=x
@ -170,17 +170,17 @@ namespace Oqtane.Controllers
{ {
string rootPath; string rootPath;
DirectoryInfo rootFolder = Directory.GetParent(_environment.ContentRootPath); DirectoryInfo rootFolder = Directory.GetParent(_environment.ContentRootPath);
string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", moduleDefinition.Template,"\\"); string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", moduleDefinition.Template,Path.DirectorySeparatorChar.ToString());
if (moduleDefinition.Template == "internal") if (moduleDefinition.Template == "internal")
{ {
rootPath = Utilities.PathCombine(rootFolder.FullName,"\\"); rootPath = Utilities.PathCombine(rootFolder.FullName,Path.DirectorySeparatorChar.ToString());
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, Oqtane.Client"; moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, Oqtane.Client";
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, Oqtane.Server"; moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
} }
else else
{ {
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name + "s","\\"); rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name + "s",Path.DirectorySeparatorChar.ToString());
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Client.Oqtane"; moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Client.Oqtane";
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Server.Oqtane"; moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Server.Oqtane";
} }

View File

@ -125,7 +125,7 @@ namespace Oqtane.Controllers
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, page.SiteId); _syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, page.SiteId);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Page Added {Page}", page); _logger.Log(LogLevel.Information, this, LogFunction.Create, "Page Added {Page}", page);
if (!page.EditMode) if (!page.Path.StartsWith("admin/"))
{ {
var modules = _modules.GetModules(page.SiteId).Where(item => item.AllPages).ToList(); var modules = _modules.GetModules(page.SiteId).Where(item => item.AllPages).ToList();
foreach (Module module in modules) foreach (Module module in modules)
@ -163,7 +163,6 @@ namespace Oqtane.Controllers
page.Order = 0; page.Order = 0;
page.IsNavigation = false; page.IsNavigation = false;
page.Url = ""; page.Url = "";
page.EditMode = false;
page.ThemeType = parent.ThemeType; page.ThemeType = parent.ThemeType;
page.LayoutType = parent.LayoutType; page.LayoutType = parent.LayoutType;
page.DefaultContainerType = parent.DefaultContainerType; page.DefaultContainerType = parent.DefaultContainerType;

View File

@ -43,8 +43,8 @@ namespace Oqtane.Controllers
[Authorize(Roles = Constants.HostRole)] [Authorize(Roles = Constants.HostRole)]
public void InstallThemes() public void InstallThemes()
{ {
_installationManager.InstallPackages("Themes", true);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Themes Installed"); _logger.Log(LogLevel.Information, this, LogFunction.Create, "Themes Installed");
_installationManager.InstallPackages("Themes", true);
} }
// DELETE api/<controller>/xxx // DELETE api/<controller>/xxx

View File

@ -9,6 +9,7 @@ using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using Oqtane.Shared; using Oqtane.Shared;
using System; using System;
using System.IO;
using System.Net; using System.Net;
using Oqtane.Enums; using Oqtane.Enums;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
@ -174,7 +175,7 @@ namespace Oqtane.Controllers
} }
// add folder for user // add folder for user
Folder folder = _folders.GetFolder(user.SiteId, Utilities.PathCombine("Users","\\")); Folder folder = _folders.GetFolder(user.SiteId, Utilities.PathCombine("Users",Path.DirectorySeparatorChar.ToString()));
if (folder != null) if (folder != null)
{ {
_folders.AddFolder(new Folder _folders.AddFolder(new Folder
@ -182,7 +183,7 @@ namespace Oqtane.Controllers
SiteId = folder.SiteId, SiteId = folder.SiteId,
ParentId = folder.FolderId, ParentId = folder.FolderId,
Name = "My Folder", Name = "My Folder",
Path = Utilities.PathCombine(folder.Path, newUser.UserId.ToString(),"\\"), Path = Utilities.PathCombine(folder.Path, newUser.UserId.ToString(),Path.DirectorySeparatorChar.ToString()),
Order = 1, Order = 1,
IsSystem = true, IsSystem = true,
Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"[" + newUser.UserId.ToString() + "]\"},{\"PermissionName\":\"View\",\"Permissions\":\"All Users\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"[" + Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"[" + newUser.UserId.ToString() + "]\"},{\"PermissionName\":\"View\",\"Permissions\":\"All Users\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"[" +

View File

@ -461,7 +461,7 @@ namespace Oqtane.Infrastructure
userroles.AddUserRole(userRole); userroles.AddUserRole(userRole);
// add user folder // add user folder
var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", "\\")); var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString()));
if (folder != null) if (folder != null)
{ {
folders.AddFolder(new Folder folders.AddFolder(new Folder
@ -469,7 +469,7 @@ namespace Oqtane.Infrastructure
SiteId = folder.SiteId, SiteId = folder.SiteId,
ParentId = folder.FolderId, ParentId = folder.FolderId,
Name = "My Folder", Name = "My Folder",
Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), "\\"), Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()),
Order = 1, Order = 1,
IsSystem = true, IsSystem = true,
Permissions = new List<Permission> Permissions = new List<Permission>

View File

@ -1,13 +1,13 @@
using System.Reflection; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using Microsoft.Extensions.Hosting; using System.Reflection;
using Microsoft.AspNetCore.Hosting;
using System.Xml; using System.Xml;
using Oqtane.Shared; using Microsoft.AspNetCore.Hosting;
using System;
using System.Diagnostics;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Hosting;
using Oqtane.Shared;
namespace Oqtane.Infrastructure namespace Oqtane.Infrastructure
{ {
@ -88,7 +88,7 @@ namespace Oqtane.Infrastructure
// deploy to appropriate locations // deploy to appropriate locations
foreach (ZipArchiveEntry entry in archive.Entries) foreach (ZipArchiveEntry entry in archive.Entries)
{ {
string foldername = Path.GetDirectoryName(entry.FullName).Split('\\')[0]; string foldername = Path.GetDirectoryName(entry.FullName).Split(Path.DirectorySeparatorChar)[0];
string filename = Path.GetFileName(entry.FullName); string filename = Path.GetFileName(entry.FullName);
switch (foldername) switch (foldername)
@ -98,7 +98,12 @@ namespace Oqtane.Infrastructure
ExtractFile(entry, filename); ExtractFile(entry, filename);
break; break;
case "wwwroot": case "wwwroot":
filename = Path.Combine(webRootPath, Utilities.PathCombine(entry.FullName.Replace("wwwroot/", "").Split('/'))); filename = Path.Combine(webRootPath.Replace(Path.DirectorySeparatorChar + "wwwroot", ""), Utilities.PathCombine(entry.FullName.Split('/')));
ExtractFile(entry, filename);
break;
case "runtimes":
var destSubFolder = Path.GetDirectoryName(entry.FullName);
filename = Path.Combine(binFolder, destSubFolder, filename);
ExtractFile(entry, filename); ExtractFile(entry, filename);
break; break;
} }
@ -121,8 +126,16 @@ namespace Oqtane.Infrastructure
{ {
Directory.CreateDirectory(Path.GetDirectoryName(filename)); Directory.CreateDirectory(Path.GetDirectoryName(filename));
} }
try
{
entry.ExtractToFile(filename, true); entry.ExtractToFile(filename, true);
} }
catch
{
// an error occurred extracting the file
}
}
public void UpgradeFramework() public void UpgradeFramework()
{ {
@ -163,12 +176,13 @@ namespace Oqtane.Infrastructure
packageversion = node.InnerText; packageversion = node.InnerText;
} }
reader.Close(); reader.Close();
break;
} }
} }
} }
// ensure package version is higher than current framework version // ensure package version is greater than or equal to current framework version
if (packageversion != "" && Version.Parse(Constants.Version).CompareTo(Version.Parse(packageversion)) < 0) if (packageversion != "" && Version.Parse(Constants.Version).CompareTo(Version.Parse(packageversion)) <= 0)
{ {
FinishUpgrade(); FinishUpgrade();
} }
@ -179,28 +193,26 @@ namespace Oqtane.Infrastructure
private void FinishUpgrade() private void FinishUpgrade()
{ {
// check if upgrade application exists // check if upgrade application exists
string Upgrader = "Oqtane.Upgrade.dll";
string folder = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); string folder = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
if (folder == null || !File.Exists(Path.Combine(folder, "Oqtane.Upgrade.exe"))) return; if (folder == null || !File.Exists(Path.Combine(folder, Upgrader))) return;
// run upgrade application // run upgrade application
var process = new Process using (var process = new Process())
{ {
StartInfo = process.StartInfo = new ProcessStartInfo
{ {
FileName = Path.Combine(folder, "Oqtane.Upgrade.exe"), WorkingDirectory = folder,
Arguments = "\"" + _environment.ContentRootPath + "\" \"" + _environment.WebRootPath + "\"", FileName = "dotnet",
ErrorDialog = false, Arguments = Path.Combine(folder, Upgrader) + " \"" + _environment.ContentRootPath + "\" \"" + _environment.WebRootPath + "\"",
UseShellExecute = false, UseShellExecute = false,
ErrorDialog = false,
CreateNoWindow = true, CreateNoWindow = true,
RedirectStandardOutput = false, RedirectStandardOutput = false,
RedirectStandardError = false RedirectStandardError = false
}
}; };
process.Start(); process.Start();
process.Dispose(); };
// stop application so upgrade application can proceed
RestartApplication();
} }
public void RestartApplication() public void RestartApplication()

View File

@ -27,6 +27,8 @@ namespace Oqtane.Infrastructure
protected async Task ExecuteAsync(CancellationToken stoppingToken) protected async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
await Task.Yield(); // required so that this method does not block startup
try try
{ {
while (!stoppingToken.IsCancellationRequested) while (!stoppingToken.IsCancellationRequested)
@ -41,21 +43,26 @@ namespace Oqtane.Infrastructure
Job job = jobs.GetJobs().Where(item => item.JobType == jobType).FirstOrDefault(); Job job = jobs.GetJobs().Where(item => item.JobType == jobType).FirstOrDefault();
if (job != null && job.IsEnabled && !job.IsExecuting) if (job != null && job.IsEnabled && !job.IsExecuting)
{ {
// set next execution date // get next execution date
DateTime NextExecution;
if (job.NextExecution == null) if (job.NextExecution == null)
{ {
if (job.StartDate != null) if (job.StartDate != null)
{ {
job.NextExecution = job.StartDate; NextExecution = job.StartDate.Value;
} }
else else
{ {
job.NextExecution = DateTime.UtcNow; NextExecution = DateTime.UtcNow;
} }
} }
else
{
NextExecution = job.NextExecution.Value;
}
// determine if the job should be run // determine if the job should be run
if (job.NextExecution <= DateTime.UtcNow && (job.EndDate == null || job.EndDate >= DateTime.UtcNow)) if (NextExecution <= DateTime.UtcNow && (job.EndDate == null || job.EndDate >= DateTime.UtcNow))
{ {
IJobLogRepository jobLogs = scope.ServiceProvider.GetRequiredService<IJobLogRepository>(); IJobLogRepository jobLogs = scope.ServiceProvider.GetRequiredService<IJobLogRepository>();
@ -89,7 +96,7 @@ namespace Oqtane.Infrastructure
jobLogs.UpdateJobLog(log); jobLogs.UpdateJobLog(log);
// update the job // update the job
job.NextExecution = CalculateNextExecution(job.NextExecution.Value, job.Frequency, job.Interval); job.NextExecution = CalculateNextExecution(NextExecution, job.Frequency, job.Interval);
job.IsExecuting = false; job.IsExecuting = false;
jobs.UpdateJob(job); jobs.UpdateJob(job);

View File

@ -20,11 +20,15 @@ namespace Oqtane.Infrastructure
{ {
string log = ""; string log = "";
// iterate through aliases in this installation // iterate through tenants in this installation
List<int> tenants = new List<int>();
var aliasRepository = provider.GetRequiredService<IAliasRepository>(); var aliasRepository = provider.GetRequiredService<IAliasRepository>();
List<Alias> aliases = aliasRepository.GetAliases().ToList(); List<Alias> aliases = aliasRepository.GetAliases().ToList();
foreach (Alias alias in aliases) foreach (Alias alias in aliases)
{ {
if (tenants.Contains(alias.TenantId)) continue;
tenants.Add(alias.TenantId);
// use the SiteState to set the Alias explicitly so the tenant can be resolved // use the SiteState to set the Alias explicitly so the tenant can be resolved
var siteState = provider.GetRequiredService<SiteState>(); var siteState = provider.GetRequiredService<SiteState>();
siteState.Alias = alias; siteState.Alias = alias;
@ -34,11 +38,11 @@ namespace Oqtane.Infrastructure
var settingRepository = provider.GetRequiredService<ISettingRepository>(); var settingRepository = provider.GetRequiredService<ISettingRepository>();
var notificationRepository = provider.GetRequiredService<INotificationRepository>(); var notificationRepository = provider.GetRequiredService<INotificationRepository>();
// iterate through sites // iterate through sites for this tenant
List<Site> sites = siteRepository.GetSites().ToList(); List<Site> sites = siteRepository.GetSites().ToList();
foreach (Site site in sites) foreach (Site site in sites)
{ {
log += "Processing Notifications For Site: " + site.Name + "\n\n"; log += "Processing Notifications For Site: " + site.Name + "<br />";
// get site settings // get site settings
List<Setting> sitesettings = settingRepository.GetSettings(EntityNames.Site, site.SiteId).ToList(); List<Setting> sitesettings = settingRepository.GetSettings(EntityNames.Site, site.SiteId).ToList();
@ -101,14 +105,14 @@ namespace Oqtane.Infrastructure
catch (Exception ex) catch (Exception ex)
{ {
// error // error
log += ex.Message + "\n\n"; log += ex.Message + "<br />";
} }
} }
log += "Notifications Delivered: " + sent + "\n\n"; log += "Notifications Delivered: " + sent + "<br />";
} }
else else
{ {
log += "SMTP Not Configured" + "\n\n"; log += "SMTP Not Configured" + "<br />";
} }
} }
} }
@ -116,7 +120,6 @@ namespace Oqtane.Infrastructure
return log; return log;
} }
private Dictionary<string, string> GetSettings(List<Setting> settings) private Dictionary<string, string> GetSettings(List<Setting> settings)
{ {
Dictionary<string, string> dictionary = new Dictionary<string, string>(); Dictionary<string, string> dictionary = new Dictionary<string, string>();

View File

@ -42,7 +42,6 @@ namespace Oqtane.SiteTemplates
Icon = "home", Icon = "home",
IsNavigation = true, IsNavigation = true,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = false,
PagePermissions = new List<Permission> { PagePermissions = new List<Permission> {
new Permission(PermissionNames.View, Constants.AllUsersRole, true), new Permission(PermissionNames.View, Constants.AllUsersRole, true),
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -89,7 +88,6 @@ namespace Oqtane.SiteTemplates
Icon = "lock-locked", Icon = "lock-locked",
IsNavigation = true, IsNavigation = true,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = false,
PagePermissions = new List<Permission> { PagePermissions = new List<Permission> {
new Permission(PermissionNames.View, Constants.RegisteredRole, true), new Permission(PermissionNames.View, Constants.RegisteredRole, true),
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -114,7 +112,6 @@ namespace Oqtane.SiteTemplates
Icon = "target", Icon = "target",
IsNavigation = true, IsNavigation = true,
IsPersonalizable = true, IsPersonalizable = true,
EditMode = false,
PagePermissions = new List<Permission> { PagePermissions = new List<Permission> {
new Permission(PermissionNames.View, Constants.AllUsersRole, true), new Permission(PermissionNames.View, Constants.AllUsersRole, true),
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -134,7 +131,7 @@ namespace Oqtane.SiteTemplates
if (System.IO.File.Exists(Path.Combine(_environment.WebRootPath, "images", "logo-white.png"))) if (System.IO.File.Exists(Path.Combine(_environment.WebRootPath, "images", "logo-white.png")))
{ {
string folderpath = Utilities.PathCombine(_environment.ContentRootPath, "Content", "Tenants", site.TenantId.ToString(), "Sites", site.SiteId.ToString(),"\\"); string folderpath = Utilities.PathCombine(_environment.ContentRootPath, "Content", "Tenants", site.TenantId.ToString(), "Sites", site.SiteId.ToString(), Path.DirectorySeparatorChar.ToString());
System.IO.Directory.CreateDirectory(folderpath); System.IO.Directory.CreateDirectory(folderpath);
if (!System.IO.File.Exists(Path.Combine(folderpath, "logo-white.png"))) if (!System.IO.File.Exists(Path.Combine(folderpath, "logo-white.png")))
{ {

View File

@ -30,7 +30,6 @@ namespace Oqtane.SiteTemplates
Icon = "home", Icon = "home",
IsNavigation = true, IsNavigation = true,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = false,
PagePermissions = new List<Permission> { PagePermissions = new List<Permission> {
new Permission(PermissionNames.View, Constants.AllUsersRole, true), new Permission(PermissionNames.View, Constants.AllUsersRole, true),
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),

View File

@ -8,24 +8,18 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Oqtane.Enums; using Oqtane.Enums;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using Oqtane.Controllers;
namespace Oqtane.Modules.HtmlText.Controllers namespace Oqtane.Modules.HtmlText.Controllers
{ {
[Route("{alias}/api/[controller]")] [Route("{alias}/api/[controller]")]
public class HtmlTextController : Controller public class HtmlTextController : ModuleControllerBase
{ {
private readonly IHtmlTextRepository _htmlText; private readonly IHtmlTextRepository _htmlText;
private readonly ILogManager _logger;
private int _entityId = -1; // passed as a querystring parameter for authorization and used for validation
public HtmlTextController(IHtmlTextRepository htmlText, ILogManager logger, IHttpContextAccessor httpContextAccessor) public HtmlTextController(IHtmlTextRepository htmlText, ILogManager logger, IHttpContextAccessor accessor) : base(logger, accessor)
{ {
_htmlText = htmlText; _htmlText = htmlText;
_logger = logger;
if (httpContextAccessor.HttpContext.Request.Query.ContainsKey("entityid"))
{
_entityId = int.Parse(httpContextAccessor.HttpContext.Request.Query["entityid"]);
}
} }
// GET api/<controller>/5 // GET api/<controller>/5

View File

@ -4,7 +4,7 @@
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<Version>1.0.1</Version> <Version>1.0.3</Version>
<Product>Oqtane</Product> <Product>Oqtane</Product>
<Authors>Shaun Walker</Authors> <Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company> <Company>.NET Foundation</Company>
@ -13,7 +13,7 @@
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl> <PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl> <RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes> <PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
<RootNamespace>Oqtane</RootNamespace> <RootNamespace>Oqtane</RootNamespace>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
</PropertyGroup> </PropertyGroup>
@ -32,6 +32,7 @@
<EmbeddedResource Include="Scripts\Tenant.00.09.02.00.sql" /> <EmbeddedResource Include="Scripts\Tenant.00.09.02.00.sql" />
<EmbeddedResource Include="Scripts\Tenant.01.00.01.00.sql" /> <EmbeddedResource Include="Scripts\Tenant.01.00.01.00.sql" />
<EmbeddedResource Include="Scripts\Tenant.01.00.01.01.sql" /> <EmbeddedResource Include="Scripts\Tenant.01.00.01.01.sql" />
<EmbeddedResource Include="Scripts\Tenant.01.00.02.01.sql" />
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.1.0.0.sql" /> <EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.1.0.0.sql" />
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.Uninstall.sql" /> <EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.Uninstall.sql" />
</ItemGroup> </ItemGroup>
@ -49,4 +50,14 @@
<ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" /> <ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" />
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" /> <ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
</ItemGroup> </ItemGroup>
</Project> <ItemGroup>
<UpgradeFiles Include="$(ProjectDir)bin\Release\netcoreapp3.1\Oqtane.Upgrade.deps.json" />
<UpgradeFiles Include="$(ProjectDir)bin\Release\netcoreapp3.1\Oqtane.Upgrade.dll" />
<UpgradeFiles Include="$(ProjectDir)bin\Release\netcoreapp3.1\Oqtane.Upgrade.pdb" />
<UpgradeFiles Include="$(ProjectDir)bin\Release\netcoreapp3.1\Oqtane.Upgrade.runtimeconfig.json" />
<TemplateFiles Include="$(ProjectDir)wwwroot\Modules\Templates\**\*.*" />
</ItemGroup>
<Target Name="AddPayloadsFolder" AfterTargets="Publish">
<Copy SourceFiles="@(UpgradeFiles)" DestinationFiles="@(UpgradeFiles->'$(PublishDir)%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
<Copy SourceFiles="@(TemplateFiles)" DestinationFiles="@(TemplateFiles->'$(PublishDir)wwwroot\Modules\Templates\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
</Target></Project>

View File

@ -123,7 +123,7 @@ namespace Oqtane.Repository
ModuleDefinition moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == module.ModuleDefinitionName).FirstOrDefault(); ModuleDefinition moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == module.ModuleDefinitionName).FirstOrDefault();
if (moduledefinition != null) if (moduledefinition != null)
{ {
ModuleContent modulecontent = JsonSerializer.Deserialize<ModuleContent>(content); ModuleContent modulecontent = JsonSerializer.Deserialize<ModuleContent>(content.Replace("\n", ""));
if (modulecontent.ModuleDefinitionName == moduledefinition.ModuleDefinitionName) if (modulecontent.ModuleDefinitionName == moduledefinition.ModuleDefinitionName)
{ {
if (moduledefinition.ServerManagerType != "") if (moduledefinition.ServerManagerType != "")
@ -147,9 +147,10 @@ namespace Oqtane.Repository
} }
} }
} }
catch catch (Exception ex)
{ {
// error occurred during import // error occurred during import
string error = ex.Message;
} }
return success; return success;

View File

@ -21,7 +21,7 @@ namespace Oqtane.Repository
return _db.Notification return _db.Notification
.Where(item => item.SiteId == siteId) .Where(item => item.SiteId == siteId)
.Where(item => item.IsDelivered == false) .Where(item => item.IsDelivered == false)
.Where(item => item.SendOn < System.DateTime.UtcNow) .Where(item => item.SendOn == null || item.SendOn < System.DateTime.UtcNow)
.ToList(); .ToList();
} }

View File

@ -58,7 +58,6 @@ namespace Oqtane.Repository
Icon = Icons.LockLocked, Icon = Icons.LockLocked,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -88,7 +87,6 @@ namespace Oqtane.Repository
Icon = Icons.Person, Icon = Icons.Person,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -119,7 +117,6 @@ namespace Oqtane.Repository
Icon = Icons.Person, Icon = Icons.Person,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -149,7 +146,6 @@ namespace Oqtane.Repository
Icon = Icons.Person, Icon = Icons.Person,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -175,7 +171,7 @@ namespace Oqtane.Repository
// admin pages // admin pages
pageTemplates.Add(new PageTemplate pageTemplates.Add(new PageTemplate
{ {
Name = "Admin", Parent = "", Path = "admin", Icon = "", IsNavigation = false, IsPersonalizable = false, EditMode = true, Name = "Admin", Parent = "", Path = "admin", Icon = "", IsNavigation = false, IsPersonalizable = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -203,7 +199,6 @@ namespace Oqtane.Repository
Icon = Icons.Home, Icon = Icons.Home,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -231,7 +226,6 @@ namespace Oqtane.Repository
Icon = Icons.Layers, Icon = Icons.Layers,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -259,7 +253,6 @@ namespace Oqtane.Repository
Icon = Icons.People, Icon = Icons.People,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -287,7 +280,6 @@ namespace Oqtane.Repository
Icon = Icons.Person, Icon = Icons.Person,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -315,7 +307,6 @@ namespace Oqtane.Repository
Icon = Icons.LockLocked, Icon = Icons.LockLocked,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -343,7 +334,6 @@ namespace Oqtane.Repository
Icon = Icons.File, Icon = Icons.File,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -371,7 +361,6 @@ namespace Oqtane.Repository
Icon = Icons.Trash, Icon = Icons.Trash,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.AdminRole, true), new Permission(PermissionNames.View, Constants.AdminRole, true),
@ -401,7 +390,6 @@ namespace Oqtane.Repository
Icon = Icons.MagnifyingGlass, Icon = Icons.MagnifyingGlass,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.HostRole, true), new Permission(PermissionNames.View, Constants.HostRole, true),
@ -428,7 +416,6 @@ namespace Oqtane.Repository
Icon = Icons.List, Icon = Icons.List,
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.HostRole, true), new Permission(PermissionNames.View, Constants.HostRole, true),
@ -450,7 +437,7 @@ namespace Oqtane.Repository
}); });
pageTemplates.Add(new PageTemplate pageTemplates.Add(new PageTemplate
{ {
Name = "Site Management", Parent = "Admin", Path = "admin/sites", Icon = Icons.Globe, IsNavigation = false, IsPersonalizable = false, EditMode = true, Name = "Site Management", Parent = "Admin", Path = "admin/sites", Icon = Icons.Globe, IsNavigation = false, IsPersonalizable = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.HostRole, true), new Permission(PermissionNames.View, Constants.HostRole, true),
@ -472,7 +459,7 @@ namespace Oqtane.Repository
}); });
pageTemplates.Add(new PageTemplate pageTemplates.Add(new PageTemplate
{ {
Name = "Module Management", Parent = "Admin", Path = "admin/modules", Icon = Icons.Browser, IsNavigation = false, IsPersonalizable = false, EditMode = true, Name = "Module Management", Parent = "Admin", Path = "admin/modules", Icon = Icons.Browser, IsNavigation = false, IsPersonalizable = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.HostRole, true), new Permission(PermissionNames.View, Constants.HostRole, true),
@ -494,7 +481,7 @@ namespace Oqtane.Repository
}); });
pageTemplates.Add(new PageTemplate pageTemplates.Add(new PageTemplate
{ {
Name = "Theme Management", Parent = "Admin", Path = "admin/themes", Icon = Icons.Brush, IsNavigation = false, IsPersonalizable = false, EditMode = true, Name = "Theme Management", Parent = "Admin", Path = "admin/themes", Icon = Icons.Brush, IsNavigation = false, IsPersonalizable = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.HostRole, true), new Permission(PermissionNames.View, Constants.HostRole, true),
@ -516,7 +503,7 @@ namespace Oqtane.Repository
}); });
pageTemplates.Add(new PageTemplate pageTemplates.Add(new PageTemplate
{ {
Name = "Scheduled Jobs", Parent = "Admin", Path = "admin/jobs", Icon = Icons.Timer, IsNavigation = false, IsPersonalizable = false, EditMode = true, Name = "Scheduled Jobs", Parent = "Admin", Path = "admin/jobs", Icon = Icons.Timer, IsNavigation = false, IsPersonalizable = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.HostRole, true), new Permission(PermissionNames.View, Constants.HostRole, true),
@ -544,7 +531,6 @@ namespace Oqtane.Repository
Icon = "spreadsheet", Icon = "spreadsheet",
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.HostRole, true), new Permission(PermissionNames.View, Constants.HostRole, true),
@ -572,7 +558,6 @@ namespace Oqtane.Repository
Icon = "medical-cross", Icon = "medical-cross",
IsNavigation = false, IsNavigation = false,
IsPersonalizable = false, IsPersonalizable = false,
EditMode = true,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.HostRole, true), new Permission(PermissionNames.View, Constants.HostRole, true),
@ -594,7 +579,7 @@ namespace Oqtane.Repository
}); });
pageTemplates.Add(new PageTemplate pageTemplates.Add(new PageTemplate
{ {
Name = "System Update", Parent = "Admin", Path = "admin/update", Icon = Icons.Aperture, IsNavigation = false, IsPersonalizable = false, EditMode = true, Name = "System Update", Parent = "Admin", Path = "admin/update", Icon = Icons.Aperture, IsNavigation = false, IsPersonalizable = false,
PagePermissions = new List<Permission> PagePermissions = new List<Permission>
{ {
new Permission(PermissionNames.View, Constants.HostRole, true), new Permission(PermissionNames.View, Constants.HostRole, true),
@ -692,7 +677,7 @@ namespace Oqtane.Repository
}); });
_folderRepository.AddFolder(new Folder _folderRepository.AddFolder(new Folder
{ {
SiteId = site.SiteId, ParentId = folder.FolderId, Name = "Users", Path = Utilities.PathCombine("Users","\\"), Order = 1, IsSystem = true, SiteId = site.SiteId, ParentId = folder.FolderId, Name = "Users", Path = Utilities.PathCombine("Users",Path.DirectorySeparatorChar.ToString()), Order = 1, IsSystem = true,
Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]" Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]"
}); });
@ -754,7 +739,6 @@ namespace Oqtane.Repository
Order = 1, Order = 1,
Url = "", Url = "",
IsNavigation = pagetemplate.IsNavigation, IsNavigation = pagetemplate.IsNavigation,
EditMode = pagetemplate.EditMode,
ThemeType = "", ThemeType = "",
LayoutType = "", LayoutType = "",
DefaultContainerType = "", DefaultContainerType = "",

View File

@ -0,0 +1,9 @@
/*
Version 1.0.2.1 migration script
*/
ALTER TABLE [dbo].[Page]
DROP COLUMN EditMode
GO

View File

@ -72,7 +72,7 @@ namespace Oqtane
}); });
} }
// register authorization services // register custom authorization policies
services.AddAuthorizationCore(options => services.AddAuthorizationCore(options =>
{ {
options.AddPolicy("ViewPage", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.View))); options.AddPolicy("ViewPage", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.View)));

View File

@ -0,0 +1,15 @@
{
"Runtime": "Server",
"ConnectionStrings": {
"DefaultConnection": ""
},
"Installation": {
"DefaultAlias": "",
"HostPassword": "",
"HostEmail": "",
"SiteTemplate": "",
"DefaultTheme": "",
"DefaultLayout": "",
"DefaultContainer": ""
}
}

View File

@ -50,7 +50,7 @@
if (PageState.Action == "Edit") if (PageState.Action == "Edit")
{ {
_id = Int32.Parse(PageState.QueryString["id"]); _id = Int32.Parse(PageState.QueryString["id"]);
[Module] [Module] = await [Module]Service.Get[Module]Async(_id); [Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
if ([Module] != null) if ([Module] != null)
{ {
_name = [Module].Name; _name = [Module].Name;
@ -82,7 +82,7 @@
} }
else else
{ {
[Module] [Module] = await [Module]Service.Get[Module]Async(_id); [Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
[Module].Name = _name; [Module].Name = _name;
await [Module]Service.Update[Module]Async([Module]); await [Module]Service.Update[Module]Async([Module]);
await logger.LogInformation("[Module] Updated {[Module]}", [Module]); await logger.LogInformation("[Module] Updated {[Module]}", [Module]);

View File

@ -95,7 +95,7 @@ else
{ {
try try
{ {
await [Module]Service.Delete[Module]Async([Module].[Module]Id); await [Module]Service.Delete[Module]Async([Module].[Module]Id, ModuleState.ModuleId);
await logger.LogInformation("[Module] Deleted {[Module]}", [Module]); await logger.LogInformation("[Module] Deleted {[Module]}", [Module]);
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId); _[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
StateHasChanged(); StateHasChanged();

View File

@ -8,12 +8,12 @@ namespace [Owner].[Module]s.Services
{ {
Task<List<[Module]>> Get[Module]sAsync(int ModuleId); Task<List<[Module]>> Get[Module]sAsync(int ModuleId);
Task<[Module]> Get[Module]Async(int [Module]Id); Task<[Module]> Get[Module]Async(int [Module]Id, int ModuleId);
Task<[Module]> Add[Module]Async([Module] [Module]); Task<[Module]> Add[Module]Async([Module] [Module]);
Task<[Module]> Update[Module]Async([Module] [Module]); Task<[Module]> Update[Module]Async([Module] [Module]);
Task Delete[Module]Async(int [Module]Id); Task Delete[Module]Async(int [Module]Id, int ModuleId);
} }
} }

View File

@ -22,28 +22,40 @@ namespace [Owner].[Module]s.Services
public async Task<List<[Module]>> Get[Module]sAsync(int ModuleId) public async Task<List<[Module]>> Get[Module]sAsync(int ModuleId)
{ {
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>($"{Apiurl}?moduleid={ModuleId}"); List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>(CreateAuthPolicyUrl($"{Apiurl}?moduleid={ModuleId}", ModuleId));
return [Module]s.OrderBy(item => item.Name).ToList(); return [Module]s.OrderBy(item => item.Name).ToList();
} }
public async Task<[Module]> Get[Module]Async(int [Module]Id) public async Task<[Module]> Get[Module]Async(int [Module]Id, int ModuleId)
{ {
return await GetJsonAsync<[Module]>($"{Apiurl}/{[Module]Id}"); return await GetJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
} }
public async Task<[Module]> Add[Module]Async([Module] [Module]) public async Task<[Module]> Add[Module]Async([Module] [Module])
{ {
return await PostJsonAsync<[Module]>($"{Apiurl}?entityid={[Module].ModuleId}", [Module]); return await PostJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}", [Module].ModuleId), [Module]);
} }
public async Task<[Module]> Update[Module]Async([Module] [Module]) public async Task<[Module]> Update[Module]Async([Module] [Module])
{ {
return await PutJsonAsync<[Module]>($"{Apiurl}/{[Module].[Module]Id}?entityid={[Module].ModuleId}", [Module]); return await PutJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}/{[Module].[Module]Id}", [Module].ModuleId), [Module]);
} }
public async Task Delete[Module]Async(int [Module]Id) public async Task Delete[Module]Async(int [Module]Id, int ModuleId)
{ {
await DeleteAsync($"{Apiurl}/{[Module]Id}"); await DeleteAsync(CreateAuthPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
}
private string CreateAuthPolicyUrl(string Url, int ModuleId)
{
if (Url.Contains("?"))
{
return Url + "&entityid=" + ModuleId.ToString();
}
else
{
return Url + "?entityid=" + ModuleId.ToString();
}
} }
} }
} }

View File

@ -25,8 +25,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Oqtane.Client" Version="1.0.1" /> <PackageReference Include="Oqtane.Client" Version="1.0.3" />
<PackageReference Include="Oqtane.Shared" Version="1.0.1" /> <PackageReference Include="Oqtane.Shared" Version="1.0.3" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Oqtane.Shared; using Oqtane.Shared;
using Oqtane.Enums; using Oqtane.Enums;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
@ -9,21 +10,27 @@ using [Owner].[Module]s.Repository;
namespace [Owner].[Module]s.Controllers namespace [Owner].[Module]s.Controllers
{ {
[Route("{site}/api/[controller]")] [Route("{alias}/api/[controller]")]
public class [Module]Controller : Controller public class [Module]Controller : Controller
{ {
private readonly I[Module]Repository _[Module]s; private readonly I[Module]Repository _[Module]s;
private readonly ILogManager _logger; private readonly ILogManager _logger;
protected int _entityId = -1;
public [Module]Controller(I[Module]Repository [Module]s, ILogManager logger) public [Module]Controller(I[Module]Repository [Module]s, ILogManager logger, IHttpContextAccessor accessor)
{ {
_[Module]s = [Module]s; _[Module]s = [Module]s;
_logger = logger; _logger = logger;
if (accessor.HttpContext.Request.Query.ContainsKey("entityid"))
{
_entityId = int.Parse(accessor.HttpContext.Request.Query["entityid"]);
}
} }
// GET: api/<controller>?moduleid=x // GET: api/<controller>?moduleid=x
[HttpGet] [HttpGet]
[Authorize(Roles = Constants.RegisteredRole)] [Authorize(Policy = "ViewModule")]
public IEnumerable<[Module]> Get(string moduleid) public IEnumerable<[Module]> Get(string moduleid)
{ {
return _[Module]s.Get[Module]s(int.Parse(moduleid)); return _[Module]s.Get[Module]s(int.Parse(moduleid));
@ -31,18 +38,23 @@ namespace [Owner].[Module]s.Controllers
// GET api/<controller>/5 // GET api/<controller>/5
[HttpGet("{id}")] [HttpGet("{id}")]
[Authorize(Roles = Constants.RegisteredRole)] [Authorize(Policy = "ViewModule")]
public [Module] Get(int id) public [Module] Get(int id)
{ {
return _[Module]s.Get[Module](id); [Module] [Module] = _[Module]s.Get[Module](id);
if ([Module] != null && [Module].ModuleId != _entityId)
{
[Module] = null;
}
return [Module];
} }
// POST api/<controller> // POST api/<controller>
[HttpPost] [HttpPost]
[Authorize(Roles = Constants.AdminRole)] [Authorize(Policy = "EditModule")]
public [Module] Post([FromBody] [Module] [Module]) public [Module] Post([FromBody] [Module] [Module])
{ {
if (ModelState.IsValid) if (ModelState.IsValid && [Module].ModuleId == _entityId)
{ {
[Module] = _[Module]s.Add[Module]([Module]); [Module] = _[Module]s.Add[Module]([Module]);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "[Module] Added {[Module]}", [Module]); _logger.Log(LogLevel.Information, this, LogFunction.Create, "[Module] Added {[Module]}", [Module]);
@ -52,10 +64,10 @@ namespace [Owner].[Module]s.Controllers
// PUT api/<controller>/5 // PUT api/<controller>/5
[HttpPut("{id}")] [HttpPut("{id}")]
[Authorize(Roles = Constants.AdminRole)] [Authorize(Policy = "EditModule")]
public [Module] Put(int id, [FromBody] [Module] [Module]) public [Module] Put(int id, [FromBody] [Module] [Module])
{ {
if (ModelState.IsValid) if (ModelState.IsValid && [Module].ModuleId == _entityId)
{ {
[Module] = _[Module]s.Update[Module]([Module]); [Module] = _[Module]s.Update[Module]([Module]);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "[Module] Updated {[Module]}", [Module]); _logger.Log(LogLevel.Information, this, LogFunction.Update, "[Module] Updated {[Module]}", [Module]);
@ -65,11 +77,15 @@ namespace [Owner].[Module]s.Controllers
// DELETE api/<controller>/5 // DELETE api/<controller>/5
[HttpDelete("{id}")] [HttpDelete("{id}")]
[Authorize(Roles = Constants.AdminRole)] [Authorize(Policy = "EditModule")]
public void Delete(int id) public void Delete(int id)
{
[Module] [Module] = _[Module]s.Get[Module](id);
if ([Module] != null && [Module].ModuleId == _entityId)
{ {
_[Module]s.Delete[Module](id); _[Module]s.Delete[Module](id);
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id); _logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id);
} }
} }
} }
}

View File

@ -31,7 +31,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Oqtane.Server" Version="1.0.1" /> <PackageReference Include="Oqtane.Server" Version="1.0.3" />
<PackageReference Include="Oqtane.Shared" Version="1.0.1" /> <PackageReference Include="Oqtane.Shared" Version="1.0.3" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1 +0,0 @@
This is the location where static resources such as images, style sheets, or scripts for this module will be located. Static assets can be organized in subfolders. When the module package is deployed the assets will be extracted under the web root in a folder that matches the module namespace.

View File

@ -17,7 +17,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Oqtane.Shared" Version="1.0.1" /> <PackageReference Include="Oqtane.Shared" Version="1.0.3" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -28,8 +28,14 @@
@code { @code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Actions => "Add,Edit"; public override string Actions => "Add,Edit";
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
};
int _id; int _id;
string _name; string _name;
string _createdby; string _createdby;
@ -44,7 +50,7 @@
if (PageState.Action == "Edit") if (PageState.Action == "Edit")
{ {
_id = Int32.Parse(PageState.QueryString["id"]); _id = Int32.Parse(PageState.QueryString["id"]);
[Module] [Module] = await [Module]Service.Get[Module]Async(_id); [Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
if ([Module] != null) if ([Module] != null)
{ {
_name = [Module].Name; _name = [Module].Name;
@ -76,7 +82,7 @@
} }
else else
{ {
[Module] [Module] = await [Module]Service.Get[Module]Async(_id); [Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
[Module].Name = _name; [Module].Name = _name;
await [Module]Service.Update[Module]Async([Module]); await [Module]Service.Update[Module]Async([Module]);
await logger.LogInformation("[Module] Updated {[Module]}", [Module]); await logger.LogInformation("[Module] Updated {[Module]}", [Module]);

View File

@ -61,6 +61,11 @@ else
<!-- The content above is for informational purposes only and can be safely removed --> <!-- The content above is for informational purposes only and can be safely removed -->
@code { @code {
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
};
List<[Module]> _[Module]s; List<[Module]> _[Module]s;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
@ -80,7 +85,7 @@ else
{ {
try try
{ {
await [Module]Service.Delete[Module]Async([Module].[Module]Id); await [Module]Service.Delete[Module]Async([Module].[Module]Id, ModuleState.ModuleId);
await logger.LogInformation("[Module] Deleted {[Module]}", [Module]); await logger.LogInformation("[Module] Deleted {[Module]}", [Module]);
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId); _[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
StateHasChanged(); StateHasChanged();

View File

@ -8,12 +8,12 @@ namespace [Owner].[Module]s.Services
{ {
Task<List<[Module]>> Get[Module]sAsync(int ModuleId); Task<List<[Module]>> Get[Module]sAsync(int ModuleId);
Task<[Module]> Get[Module]Async(int [Module]Id); Task<[Module]> Get[Module]Async(int [Module]Id, int ModuleId);
Task<[Module]> Add[Module]Async([Module] [Module]); Task<[Module]> Add[Module]Async([Module] [Module]);
Task<[Module]> Update[Module]Async([Module] [Module]); Task<[Module]> Update[Module]Async([Module] [Module]);
Task Delete[Module]Async(int [Module]Id); Task Delete[Module]Async(int [Module]Id, int ModuleId);
} }
} }

View File

@ -22,28 +22,40 @@ namespace [Owner].[Module]s.Services
public async Task<List<[Module]>> Get[Module]sAsync(int ModuleId) public async Task<List<[Module]>> Get[Module]sAsync(int ModuleId)
{ {
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>($"{Apiurl}?moduleid={ModuleId}"); List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>(CreateAuthPolicyUrl($"{Apiurl}?moduleid={ModuleId}", ModuleId));
return [Module]s.OrderBy(item => item.Name).ToList(); return [Module]s.OrderBy(item => item.Name).ToList();
} }
public async Task<[Module]> Get[Module]Async(int [Module]Id) public async Task<[Module]> Get[Module]Async(int [Module]Id, int ModuleId)
{ {
return await GetJsonAsync<[Module]>($"{Apiurl}/{[Module]Id}"); return await GetJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
} }
public async Task<[Module]> Add[Module]Async([Module] [Module]) public async Task<[Module]> Add[Module]Async([Module] [Module])
{ {
return await PostJsonAsync<[Module]>($"{Apiurl}?entityid={[Module].ModuleId}", [Module]); return await PostJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}?entityid={[Module].ModuleId}", [Module].ModuleId), [Module]);
} }
public async Task<[Module]> Update[Module]Async([Module] [Module]) public async Task<[Module]> Update[Module]Async([Module] [Module])
{ {
return await PutJsonAsync<[Module]>($"{Apiurl}/{[Module].[Module]Id}?entityid={[Module].ModuleId}", [Module]); return await PutJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}/{[Module].[Module]Id}", [Module].ModuleId), [Module]);
} }
public async Task Delete[Module]Async(int [Module]Id) public async Task Delete[Module]Async(int [Module]Id, int ModuleId)
{ {
await DeleteAsync($"{Apiurl}/{[Module]Id}"); await DeleteAsync(CreateAuthPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
}
private string CreateAuthPolicyUrl(string Url, int ModuleId)
{
if (Url.Contains("?"))
{
return Url + "&entityid=" + ModuleId.ToString();
}
else
{
return Url + "?entityid=" + ModuleId.ToString();
}
} }
} }
} }

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Oqtane.Shared; using Oqtane.Shared;
using Oqtane.Enums; using Oqtane.Enums;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
@ -9,21 +10,27 @@ using [Owner].[Module]s.Repository;
namespace [Owner].[Module]s.Controllers namespace [Owner].[Module]s.Controllers
{ {
[Route("{site}/api/[controller]")] [Route("{alias}/api/[controller]")]
public class [Module]Controller : Controller public class [Module]Controller : Controller
{ {
private readonly I[Module]Repository _[Module]s; private readonly I[Module]Repository _[Module]s;
private readonly ILogManager _logger; private readonly ILogManager _logger;
protected int _entityId = -1;
public [Module]Controller(I[Module]Repository [Module]s, ILogManager logger) public [Module]Controller(I[Module]Repository [Module]s, ILogManager logger, IHttpContextAccessor accessor)
{ {
_[Module]s = [Module]s; _[Module]s = [Module]s;
_logger = logger; _logger = logger;
if (accessor.HttpContext.Request.Query.ContainsKey("entityid"))
{
_entityId = int.Parse(accessor.HttpContext.Request.Query["entityid"]);
}
} }
// GET: api/<controller>?moduleid=x // GET: api/<controller>?moduleid=x
[HttpGet] [HttpGet]
[Authorize(Roles = Constants.RegisteredRole)] [Authorize(Policy = "ViewModule")]
public IEnumerable<[Module]> Get(string moduleid) public IEnumerable<[Module]> Get(string moduleid)
{ {
return _[Module]s.Get[Module]s(int.Parse(moduleid)); return _[Module]s.Get[Module]s(int.Parse(moduleid));
@ -31,18 +38,23 @@ namespace [Owner].[Module]s.Controllers
// GET api/<controller>/5 // GET api/<controller>/5
[HttpGet("{id}")] [HttpGet("{id}")]
[Authorize(Roles = Constants.RegisteredRole)] [Authorize(Policy = "ViewModule")]
public [Module] Get(int id) public [Module] Get(int id)
{ {
return _[Module]s.Get[Module](id); [Module] [Module] = _[Module]s.Get[Module](id);
if ([Module] != null && [Module].ModuleId != _entityId)
{
[Module] = null;
}
return [Module];
} }
// POST api/<controller> // POST api/<controller>
[HttpPost] [HttpPost]
[Authorize(Roles = Constants.AdminRole)] [Authorize(Policy = "EditModule")]
public [Module] Post([FromBody] [Module] [Module]) public [Module] Post([FromBody] [Module] [Module])
{ {
if (ModelState.IsValid) if (ModelState.IsValid && [Module].ModuleId == _entityId)
{ {
[Module] = _[Module]s.Add[Module]([Module]); [Module] = _[Module]s.Add[Module]([Module]);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "[Module] Added {[Module]}", [Module]); _logger.Log(LogLevel.Information, this, LogFunction.Create, "[Module] Added {[Module]}", [Module]);
@ -52,10 +64,10 @@ namespace [Owner].[Module]s.Controllers
// PUT api/<controller>/5 // PUT api/<controller>/5
[HttpPut("{id}")] [HttpPut("{id}")]
[Authorize(Roles = Constants.AdminRole)] [Authorize(Policy = "EditModule")]
public [Module] Put(int id, [FromBody] [Module] [Module]) public [Module] Put(int id, [FromBody] [Module] [Module])
{ {
if (ModelState.IsValid) if (ModelState.IsValid && [Module].ModuleId == _entityId)
{ {
[Module] = _[Module]s.Update[Module]([Module]); [Module] = _[Module]s.Update[Module]([Module]);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "[Module] Updated {[Module]}", [Module]); _logger.Log(LogLevel.Information, this, LogFunction.Update, "[Module] Updated {[Module]}", [Module]);
@ -65,11 +77,15 @@ namespace [Owner].[Module]s.Controllers
// DELETE api/<controller>/5 // DELETE api/<controller>/5
[HttpDelete("{id}")] [HttpDelete("{id}")]
[Authorize(Roles = Constants.AdminRole)] [Authorize(Policy = "EditModule")]
public void Delete(int id) public void Delete(int id)
{
[Module] [Module] = _[Module]s.Get[Module](id);
if ([Module] != null && [Module].ModuleId == _entityId)
{ {
_[Module]s.Delete[Module](id); _[Module]s.Delete[Module](id);
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id); _logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id);
} }
} }
} }
}

View File

@ -1 +0,0 @@
This is the location where static resources such as images, style sheets, or scripts for this module will be located. Static assets can be organized in subfolders. When the module package is deployed the assets will be extracted under the web root in a folder that matches the module namespace.

View File

@ -9,8 +9,8 @@
</head> </head>
<body> <body>
<div> <div>
<br /><br /><h1 align="center">Please Wait... Upgrade In Progress....</h1> <br /><br />
<img src="https://www.oqtane.org/Portals/0/oqtane-black.png" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);" /> <h1 align="center">Please Wait... Upgrade In Progress....</h1>
</div> </div>
</body> </body>
</html> </html>

View File

@ -327,7 +327,7 @@ Oqtane.Interop = {
while (Chunk = FileChunk.shift()) { while (Chunk = FileChunk.shift()) {
PartCount++; PartCount++;
var FileName = file.name + ".part_" + PartCount + "_" + TotalParts; var FileName = file.name + ".part_" + PartCount.toString().padStart(3, '0') + "_" + TotalParts.toString().padStart(3, '0');
var data = new FormData(); var data = new FormData();
data.append('folder', folder); data.append('folder', folder);

View File

@ -20,6 +20,7 @@ namespace Oqtane.Models
ServerManagerType = ""; ServerManagerType = "";
ControlTypeRoutes = ""; ControlTypeRoutes = "";
ReleaseVersions = ""; ReleaseVersions = "";
Runtimes = "";
Template = ""; Template = "";
} }
@ -45,6 +46,8 @@ namespace Oqtane.Models
[NotMapped] [NotMapped]
public string License { get; set; } public string License { get; set; }
[NotMapped] [NotMapped]
public string Runtimes { get; set; }
[NotMapped]
public string Dependencies { get; set; } public string Dependencies { get; set; }
[NotMapped] [NotMapped]
public string PermissionNames { get; set; } public string PermissionNames { get; set; }

View File

@ -19,7 +19,6 @@ namespace Oqtane.Models
public string DefaultContainerType { get; set; } public string DefaultContainerType { get; set; }
public string Icon { get; set; } public string Icon { get; set; }
public bool IsNavigation { get; set; } public bool IsNavigation { get; set; }
public bool EditMode { get; set; }
public int? UserId { get; set; } public int? UserId { get; set; }
public bool IsPersonalizable { get; set; } public bool IsPersonalizable { get; set; }
@ -41,5 +40,9 @@ namespace Oqtane.Models
public int Level { get; set; } public int Level { get; set; }
[NotMapped] [NotMapped]
public bool HasChildren { get; set; } public bool HasChildren { get; set; }
[Obsolete("This property is obsolete", false)]
[NotMapped]
public bool EditMode { get; set; }
} }
} }

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
namespace Oqtane.Models namespace Oqtane.Models
{ {
@ -16,9 +17,11 @@ namespace Oqtane.Models
public string Icon { get; set; } public string Icon { get; set; }
public bool IsNavigation { get; set; } public bool IsNavigation { get; set; }
public bool IsPersonalizable { get; set; } public bool IsPersonalizable { get; set; }
public bool EditMode { get; set; }
public string PagePermissions { get; set; } public string PagePermissions { get; set; }
public List<PageTemplateModule> PageTemplateModules { get; set; } public List<PageTemplateModule> PageTemplateModules { get; set; }
[Obsolete("This property is obsolete", false)]
public bool EditMode { get; set; }
} }
public class PageTemplateModule public class PageTemplateModule

View File

@ -4,7 +4,7 @@
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<Version>1.0.1</Version> <Version>1.0.3</Version>
<Product>Oqtane</Product> <Product>Oqtane</Product>
<Authors>Shaun Walker</Authors> <Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company> <Company>.NET Foundation</Company>
@ -13,7 +13,7 @@
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl> <PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl> <RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes> <PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
<RootNamespace>Oqtane</RootNamespace> <RootNamespace>Oqtane</RootNamespace>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
</PropertyGroup> </PropertyGroup>

View File

@ -5,8 +5,8 @@ namespace Oqtane.Shared
public class Constants public class Constants
{ {
public const string PackageId = "Oqtane.Framework"; public const string PackageId = "Oqtane.Framework";
public const string Version = "1.0.1"; public const string Version = "1.0.3";
public const string ReleaseVersions = "0.9.0,0.9.1,0.9.2,1.0.0,1.0.1"; public const string ReleaseVersions = "0.9.0,0.9.1,0.9.2,1.0.0,1.0.1,1.0.2,1.0.3";
public const string PageComponent = "Oqtane.UI.ThemeBuilder, Oqtane.Client"; public const string PageComponent = "Oqtane.UI.ThemeBuilder, Oqtane.Client";
public const string ContainerComponent = "Oqtane.UI.ContainerBuilder, Oqtane.Client"; public const string ContainerComponent = "Oqtane.UI.ContainerBuilder, Oqtane.Client";
@ -19,6 +19,8 @@ namespace Oqtane.Shared
public const string ActionToken = "{Action}"; public const string ActionToken = "{Action}";
public const string DefaultAction = "Index"; public const string DefaultAction = "Index";
public const string AdminPane = "Admin"; public const string AdminPane = "Admin";
public const string ModuleDelimiter = "*";
public const string UrlParametersDelimiter = "!";
// Default Module Actions are reserved and should not be used by modules // Default Module Actions are reserved and should not be used by modules
public static readonly string[] DefaultModuleActions = new[] { "Settings", "Import", "Export" }; public static readonly string[] DefaultModuleActions = new[] { "Settings", "Import", "Export" };
@ -46,6 +48,7 @@ namespace Oqtane.Shared
public const string ImageFiles = "jpg,jpeg,jpe,gif,bmp,png"; public const string ImageFiles = "jpg,jpeg,jpe,gif,bmp,png";
public const string UploadableFiles = "jpg,jpeg,jpe,gif,bmp,png,mov,wmv,avi,mp4,mp3,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,nupkg"; public const string UploadableFiles = "jpg,jpeg,jpe,gif,bmp,png,mov,wmv,avi,mp4,mp3,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,nupkg";
public const string ReservedDevices = "CON,NUL,PRN,COM0,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8,COM9,LPT0,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9,CONIN$,CONOUT$"; public const string ReservedDevices = "CON,NUL,PRN,COM0,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8,COM9,LPT0,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9,CONIN$,CONOUT$";
public static readonly char[] InvalidFileNameChars = public static readonly char[] InvalidFileNameChars =
{ {
'\"', '<', '>', '|', '\0', (Char) 1, (Char) 2, (Char) 3, (Char) 4, (Char) 5, (Char) 6, (Char) 7, (Char) 8, '\"', '<', '>', '|', '\0', (Char) 1, (Char) 2, (Char) 3, (Char) 4, (Char) 5, (Char) 6, (Char) 7, (Char) 8,

View File

@ -20,8 +20,53 @@ namespace Oqtane.Shared
return $"{type.Namespace}, {assemblyName}"; return $"{type.Namespace}, {assemblyName}";
} }
public static (string UrlParameters, string Querystring, string Anchor) ParseParameters(string parameters)
{
// /urlparameters /urlparameters?Id=1 /urlparameters#5 /urlparameters?Id=1#5 /urlparameters?reload#5
// Id=1 Id=1#5 reload#5 reload
// #5
var urlparameters = string.Empty;
var querystring = string.Empty;
var anchor = string.Empty;
if (parameters.Contains('#'))
{
anchor = parameters.Split('#').Last();
parameters = parameters.Replace("#" + anchor, "");
}
if (parameters.Contains('?'))
{
urlparameters = parameters.Split('?').First();
querystring = parameters.Replace(urlparameters + "?", "");
}
else if (parameters.Contains('/'))
{
urlparameters = parameters;
}
else
{
querystring = parameters;
}
return (urlparameters, querystring, anchor);
}
public static string NavigateUrl(string alias, string path, string parameters) public static string NavigateUrl(string alias, string path, string parameters)
{ {
string urlparameters;
string querystring;
string anchor;
(urlparameters, querystring, anchor) = ParseParameters(parameters);
if (!string.IsNullOrEmpty(urlparameters))
{
if (urlparameters.StartsWith("/")) urlparameters = urlparameters.Remove(0, 1);
path += $"/{Constants.UrlParametersDelimiter}/{urlparameters}";
}
var uriBuilder = new UriBuilder var uriBuilder = new UriBuilder
{ {
Path = !string.IsNullOrEmpty(alias) Path = !string.IsNullOrEmpty(alias)
@ -29,17 +74,18 @@ namespace Oqtane.Shared
? $"{alias}/{path}" ? $"{alias}/{path}"
: $"{alias}" : $"{alias}"
: $"{path}", : $"{path}",
Query = parameters Query = querystring,
}; };
anchor = string.IsNullOrEmpty(anchor) ? "" : "#" + anchor;
return uriBuilder.Uri.PathAndQuery; var navigateUrl = uriBuilder.Uri.PathAndQuery + anchor;
return navigateUrl;
} }
public static string EditUrl(string alias, string path, int moduleid, string action, string parameters) public static string EditUrl(string alias, string path, int moduleid, string action, string parameters)
{ {
if (moduleid != -1) if (moduleid != -1)
{ {
path += $"/{moduleid}"; path += $"/{Constants.ModuleDelimiter}/{moduleid}";
if (!string.IsNullOrEmpty(action)) if (!string.IsNullOrEmpty(action))
{ {
path += $"/{action}"; path += $"/{action}";
@ -136,6 +182,7 @@ namespace Oqtane.Shared
stringBuilder.Append(RemapInternationalCharToAscii(c)); stringBuilder.Append(RemapInternationalCharToAscii(c));
prevdash = false; prevdash = false;
break; break;
case UnicodeCategory.SpaceSeparator: case UnicodeCategory.SpaceSeparator:
case UnicodeCategory.ConnectorPunctuation: case UnicodeCategory.ConnectorPunctuation:
case UnicodeCategory.DashPunctuation: case UnicodeCategory.DashPunctuation:
@ -284,7 +331,6 @@ namespace Oqtane.Shared
!Constants.ReservedDevices.Split(',').Contains(name.ToUpper().Split('.')[0])); !Constants.ReservedDevices.Split(',').Contains(name.ToUpper().Split('.')[0]));
} }
public static bool TryGetQueryValue( public static bool TryGetQueryValue(
this Uri uri, this Uri uri,
string key, string key,

View File

@ -4,7 +4,7 @@
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<Version>1.0.1</Version> <Version>1.0.3</Version>
<Product>Oqtane</Product> <Product>Oqtane</Product>
<Authors>Shaun Walker</Authors> <Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company> <Company>.NET Foundation</Company>
@ -13,7 +13,7 @@
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl> <PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl> <RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes> <PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
<RootNamespace>Oqtane</RootNamespace> <RootNamespace>Oqtane</RootNamespace>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>

View File

@ -4,7 +4,7 @@
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<Version>1.0.1</Version> <Version>1.0.3</Version>
<Product>Oqtane</Product> <Product>Oqtane</Product>
<Authors>Shaun Walker</Authors> <Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company> <Company>.NET Foundation</Company>
@ -13,7 +13,7 @@
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl> <PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl> <RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes> <PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
<RootNamespace>Oqtane</RootNamespace> <RootNamespace>Oqtane</RootNamespace>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>

View File

@ -11,12 +11,13 @@ namespace Oqtane.Upgrade
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
// requires 2 arguments - the ContentRootPath and the WebRootPath of the site
// for testing purposes set Oqtane.Upgrade as startup project and modify values below // for testing purposes set Oqtane.Upgrade as startup project and modify values below
//Array.Resize(ref args, 2); //Array.Resize(ref args, 2);
//args[0] = @"C:\yourpath\oqtane.framework\Oqtane.Server"; //args[0] = @"C:\yourpath\oqtane.framework\Oqtane.Server";
//args[1] = @"C:\yourpath\oqtane.framework\Oqtane.Server\wwwroot"; //args[1] = @"C:\yourpath\oqtane.framework\Oqtane.Server\wwwroot";
// requires 2 arguments - the contentrootpath and the webrootpath of the site
if (args.Length == 2) if (args.Length == 2)
{ {
string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
@ -47,30 +48,41 @@ namespace Oqtane.Upgrade
{ {
foreach (ZipArchiveEntry entry in archive.Entries) foreach (ZipArchiveEntry entry in archive.Entries)
{ {
switch (Path.GetDirectoryName(entry.FullName).Split('\\')[0]) string filename = Path.GetFileName(entry.FullName);
if (!string.IsNullOrEmpty(filename))
{
// use top level folder to determine location to extract files
switch (Path.GetDirectoryName(entry.FullName).Split(Path.DirectorySeparatorChar)[0])
{ {
case "lib": case "lib":
files.Add(Path.Combine(binfolder, Path.GetFileName(entry.FullName))); files.Add(Path.Combine(binfolder, filename));
break; break;
case "wwwroot": case "wwwroot":
files.Add(Path.Combine(webrootfolder, entry.FullName.Replace("wwwroot/", "").Replace("/","\\"))); files.Add(Path.Combine(webrootfolder.Replace(Path.DirectorySeparatorChar + "wwwroot", ""), entry.FullName.Replace('/', Path.DirectorySeparatorChar)));
break; break;
} }
} }
} }
}
// ensure files are not locked // ensure files are not locked
if (CanAccessFiles(files)) if (CanAccessFiles(files))
{
try
{ {
// create backup // create backup
foreach (string file in files) foreach (string file in files)
{ {
if (File.Exists(file))
{
// remove previous backup if it exists
if (File.Exists(file + ".bak")) if (File.Exists(file + ".bak"))
{ {
File.Delete(file + ".bak"); File.Delete(file + ".bak");
} }
File.Move(file, file + ".bak"); File.Move(file, file + ".bak");
} }
}
// extract files // extract files
bool success = true; bool success = true;
@ -80,28 +92,36 @@ namespace Oqtane.Upgrade
{ {
foreach (ZipArchiveEntry entry in archive.Entries) foreach (ZipArchiveEntry entry in archive.Entries)
{ {
string filename = ""; string filename = Path.GetFileName(entry.FullName);
switch (Path.GetDirectoryName(entry.FullName).Split('\\')[0]) if (!string.IsNullOrEmpty(filename))
{
// use top level folder to determine location to extract files
switch (Path.GetDirectoryName(entry.FullName).Split(Path.DirectorySeparatorChar)[0])
{ {
case "lib": case "lib":
filename = Path.Combine(binfolder, Path.GetFileName(entry.FullName)); filename = Path.Combine(binfolder, filename);
break; break;
case "wwwroot": case "wwwroot":
filename = Path.Combine(webrootfolder, entry.FullName.Replace("wwwroot/", "").Replace("/", "\\")); filename = Path.Combine(webrootfolder.Replace(Path.DirectorySeparatorChar + "wwwroot", ""), entry.FullName.Replace('/', Path.DirectorySeparatorChar));
break; break;
} }
if (files.Contains(filename)) if (files.Contains(filename))
{ {
if (!Directory.Exists(Path.GetDirectoryName(filename)))
{
Directory.CreateDirectory(Path.GetDirectoryName(filename));
}
entry.ExtractToFile(filename, true); entry.ExtractToFile(filename, true);
} }
} }
} }
} }
catch }
catch (Exception ex)
{ {
// an error occurred extracting a file // an error occurred extracting a file
success = false; success = false;
Console.WriteLine("Update Not Successful: Error Extracting Files From Package - " + ex.Message);
} }
if (success) if (success)
@ -127,10 +147,22 @@ namespace Oqtane.Upgrade
{ {
File.Delete(file); File.Delete(file);
} }
if (File.Exists(file + ".bak"))
{
File.Move(file + ".bak", file); File.Move(file + ".bak", file);
} }
} }
} }
}
catch (Exception ex)
{
Console.WriteLine("Update Not Successful: " + ex.Message);
}
}
else
{
Console.WriteLine("Upgrade Not Successful: Some Files Are Locked");
}
// bring the app back online // bring the app back online
if (File.Exists(Path.Combine(contentrootfolder, "app_offline.htm"))) if (File.Exists(Path.Combine(contentrootfolder, "app_offline.htm")))
@ -138,8 +170,20 @@ namespace Oqtane.Upgrade
File.Delete(Path.Combine(contentrootfolder, "app_offline.htm")); File.Delete(Path.Combine(contentrootfolder, "app_offline.htm"));
} }
} }
else
{
Console.WriteLine("Framework Upgrade Package Not Found");
} }
} }
else
{
Console.WriteLine("Framework Upgrade Folder " + deployfolder + " Does Not Exist");
}
}
else
{
Console.WriteLine("Missing ContentRootPath and WebRootPath Parameters");
}
} }
private static bool CanAccessFiles(List<string> files) private static bool CanAccessFiles(List<string> files)
@ -157,10 +201,17 @@ namespace Oqtane.Upgrade
while (attempts < 30 && locked) while (attempts < 30 && locked)
{ {
try try
{
if (File.Exists(filepath))
{ {
stream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.None); stream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.None);
locked = false; locked = false;
} }
else
{
locked = false;
}
}
catch // file is locked by another process catch // file is locked by another process
{ {
Thread.Sleep(1000); // wait 1 second Thread.Sleep(1000); // wait 1 second

View File

@ -1,23 +1,35 @@
# Oqtane Framework # Oqtane Framework
Oqtane is a Modular Application Framework for Blazor Oqtane is a Modular Application Framework for Blazor
[![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](https://github.com/oqtane/framework/blob/master/oqtane.png?raw=true "Oqtane") ![Oqtane](https://github.com/oqtane/framework/blob/master/oqtane.png?raw=true "Oqtane")
Oqtane uses 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. Oqtane uses 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.
Oqtane is being developed based on some fundamental principles which are outlined in the [Oqtane Philosophy](https://www.oqtane.org/Resources/Blog/PostId/538/oqtane-philosophy).
Please note that this project is owned by the .NET Foundation and is governed by the **[.NET Foundation Contributor Covenant Code of Conduct](https://dotnetfoundation.org/code-of-conduct)** Please note that this project is owned by the .NET Foundation and is governed by the **[.NET Foundation Contributor Covenant Code of Conduct](https://dotnetfoundation.org/code-of-conduct)**
**To get started with Oqtane:** # Getting Started
1.&nbsp;Install **[.NET Core 3.1 SDK (v3.1.300)](https://dotnet.microsoft.com/download/dotnet-core/thank-you/sdk-3.1.300-windows-x64-installer)**. **Using the latest code:**
2.&nbsp;Install the Preview edition of [Visual Studio 2019](https://visualstudio.microsoft.com/vs/preview/) (version 16.6 or higher) with the **ASP.NET and web development** workload enabled. Oqtane works with all editions of Visual Studio from Community to Enterprise. If you do not have a SQL Server installation available already and you wish to use LocalDB for development, you must also install the **.NET desktop development workload**. - Install **[.NET Core 3.1 SDK (v3.1.300)](https://dotnet.microsoft.com/download/dotnet-core/thank-you/sdk-3.1.300-windows-x64-installer)**.
3.&nbsp;Download or Clone the Oqtane source code to your local system. Open the **Oqtane.sln** solution file and Build the solution. - Install the Preview edition of [Visual Studio 2019](https://visualstudio.microsoft.com/vs/preview/) (Community, Professional, and Enterprise Editions are all supported) with the **ASP.NET and web development** workload enabled. Oqtane works with all editions of Visual Studio from Community to Enterprise. If you do not have a SQL Server installation available already and you wish to use LocalDB for development, you must also install the **.NET desktop development workload**.
NOTE: If you have already installed a previous version of Oqtane and you wish to do a clean database install, simply reset the DefaultConnection value in the Oqtane.Server\appsettings.json file to "". This will trigger a re-install when you run the application which will execute the database installation scripts. - Download or Clone the Oqtane source code to your local system. Open the **Oqtane.sln** solution file and Build the solution.
NOTE: If you want to submit pull requests make sure you install the [Github Extension For Visual Studio](https://visualstudio.github.com/). It is recommended you ignore any local changes you have made to the appsettings.json file before you submit a pull request. To automate this activity, open a command prompt and navigate to the /Oqtane.Server/ folder and enter the command "git update-index --skip-worktree appsettings.json" **Using an official release:**
- A detailed set of instructions for installing Oqtane on IIS is located here: [Installing Oqtane on IIS](https://www.oqtane.org/Resources/Blog/PostId/542/installing-oqtane-on-iis)
**Additional Instructions**
- If you have already installed a previous version of Oqtane and you wish to do a clean database install, simply reset the DefaultConnection value in the Oqtane.Server\appsettings.json file to "". This will trigger a re-install when you run the application which will execute the database installation scripts.
- If you want to submit pull requests make sure you install the [Github Extension For Visual Studio](https://visualstudio.github.com/). It is recommended you ignore any local changes you have made to the appsettings.json file before you submit a pull request. To automate this activity, open a command prompt and navigate to the /Oqtane.Server/ folder and enter the command "git update-index --skip-worktree appsettings.json"
# Roadmap # Roadmap
This project is a work in progress and the schedule for implementing enhancements is dependent upon the availability of community members who are willing/able to assist. This project is a work in progress and the schedule for implementing enhancements is dependent upon the availability of community members who are willing/able to assist.
@ -53,6 +65,8 @@ Oqtane was created by [Shaun Walker](https://www.linkedin.com/in/shaunbrucewalke
# Release Announcements # Release Announcements
[Oqtane 1.0.1](https://www.oqtane.org/Resources/Blog/PostId/541/oqtane-builds-momentum-with-101-release)
[Oqtane 1.0](https://www.oqtane.org/Resources/Blog/PostId/540/announcing-oqtane-10-a-modular-application-framework-for-blazor) [Oqtane 1.0](https://www.oqtane.org/Resources/Blog/PostId/540/announcing-oqtane-10-a-modular-application-framework-for-blazor)
[Oqtane POC](https://www.oqtane.org/Resources/Blog/PostId/520/announcing-oqtane-a-modular-application-framework-for-blazor) [Oqtane POC](https://www.oqtane.org/Resources/Blog/PostId/520/announcing-oqtane-a-modular-application-framework-for-blazor)
@ -87,7 +101,7 @@ Control panel for adding, editing, and deleting pages as well as adding new modu
![Manage Page](https://github.com/oqtane/framework/blob/master/screenshots/screenshot5.png?raw=true "Manage Page") ![Manage Page](https://github.com/oqtane/framework/blob/master/screenshots/screenshot5.png?raw=true "Manage Page")
Admin dashboard for accessing the variuous administrative features of the framework: Admin dashboard for accessing the various administrative features of the framework:
![Admin Dashboard](https://github.com/oqtane/framework/blob/master/screenshots/screenshot6.png?raw=true "Admin Dashboard") ![Admin Dashboard](https://github.com/oqtane/framework/blob/master/screenshots/screenshot6.png?raw=true "Admin Dashboard")

197
azuredeploy.json Normal file
View File

@ -0,0 +1,197 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.1",
"parameters": {
"sqlServerName": {
"type": "string",
"metadata": {
"description": "The name of the sql server. It has to be unique."
}
},
"databaseName": {
"type": "string",
"metadata": {
"description": "The name of the sql databaseName. It has to be unique."
}
},
"sqlAdministratorLogin": {
"type": "string",
"metadata": {
"description": "The admin user of the SQL Server"
}
},
"sqlAdministratorLoginPassword": {
"type": "securestring",
"metadata": {
"description": "The password of the admin user of the SQL Server"
}
},
"BlazorWebsiteName": {
"type": "string",
"metadata": {
"description": "The name of the website. It has to be unique."
}
},
"BlazorSKU": {
"type": "string",
"allowedValues": [
"Free",
"Shared",
"Basic",
"Standard"
],
"defaultValue": "Standard"
},
"BlazorWorkerSize": {
"type": "string",
"allowedValues": [
"0",
"1",
"2"
],
"defaultValue": "0"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
}
},
"variables": {
"hostingPlanName": "[concat('Oqtane-hostingplan-', uniqueString(resourceGroup().id))]",
"databaseEdition": "Standard",
"databaseCollation": "SQL_Latin1_General_CP1_CI_AS",
"databaseServiceObjectiveName": "Standard"
},
"resources": [
{
"name": "[parameters('sqlServerName')]",
"type": "Microsoft.Sql/servers",
"apiVersion": "2014-04-01",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "SqlServer"
},
"properties": {
"administratorLogin": "[parameters('sqlAdministratorLogin')]",
"administratorLoginPassword": "[parameters('sqlAdministratorLoginPassword')]",
"version": "12.0"
},
"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')]"
]
}
]
},
{
"name": "[variables('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"apiVersion": "2014-06-01",
"dependsOn": [],
"tags": {
"displayName": "Blazor"
},
"properties": {
"name": "[variables('hostingPlanName')]",
"sku": "[parameters('BlazorSKU')]",
"workerSize": "[parameters('BlazorWorkerSize')]",
"numberOfWorkers": 1
}
},
{
"apiVersion": "2018-02-01",
"name": "[parameters('BlazorWebsiteName')]",
"type": "Microsoft.Web/sites",
"location": "[parameters('location')]",
"dependsOn": [
"[variables('hostingPlanName')]"
],
"tags": {
"[concat('hidden-related:', resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName')))]": "empty",
"displayName": "Website"
},
"properties": {
"name": "[parameters('BlazorWebsiteName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"siteConfig": {
"webSocketsEnabled": true
}
},
"resources": [
{
"type": "sourcecontrols",
"apiVersion": "2018-02-01",
"name": "web",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('BlazorWebsiteName'))]",
"[resourceId('Microsoft.Web/Sites/config', parameters('BlazorWebsiteName'), 'connectionstrings')]"
],
"properties": {
"RepoUrl": "https://github.com/oqtane/oqtane.framework.git",
"branch": "master",
"IsManualIntegration": true
}
},
{
"apiVersion": "2018-02-01",
"type": "config",
"name": "connectionstrings",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('BlazorWebsiteName'))]"
],
"properties": {
"DefaultConnection": {
"value": "[concat('Data Source=tcp:', reference(concat('Microsoft.Sql/servers/', parameters('sqlserverName'))).fullyQualifiedDomainName, ',1433;Initial Catalog=', parameters('databaseName'), ';User Id=', parameters('sqlAdministratorLogin'), '@', reference(concat('Microsoft.Sql/servers/', parameters('sqlserverName'))).fullyQualifiedDomainName, ';Password=', parameters('sqlAdministratorLoginPassword'), ';')]",
"type": "SQLAzure"
}
}
}
]
}
]
}