Merge pull request #19 from oqtane/master

sync master
This commit is contained in:
Jim Spillane
2020-08-18 09:14:20 -04:00
committed by GitHub
174 changed files with 1900 additions and 998 deletions

2
.deployment Normal file
View File

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

View File

@ -0,0 +1,111 @@
@namespace Oqtane.Modules.Admin.Files
@inherits ModuleBase
@inject IFileService FileService
@inject IFolderService FolderService
@inject NavigationManager NavigationManager
@if (_folders != null)
{
<table class="table table-borderless">
<tr>
<td>
<Label for="name" HelpText="The name of the file">Name: </Label>
</td>
<td>
<input id="name" class="form-control" @bind="@_name" />
</td>
</tr>
<tr>
<td>
<Label For="parent" HelpText="The folder where the file is located">Folder: </Label>
</td>
<td>
<select id="parent" class="form-control" @bind="@_folderId">
@foreach (Folder folder in _folders)
{
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
}
</select>
</td>
</tr>
<tr>
<td>
<Label for="size" HelpText="The size of the file (in bytes)">Size: </Label>
</td>
<td>
<input id="size" class="form-control" @bind="@_size" readonly />
</td>
</tr>
</table>
<button type="button" class="btn btn-success" @onclick="SaveFile">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
<br />
<br />
<AuditInfo CreatedBy="@_createdBy" CreatedOn="@_createdOn" ModifiedBy="@_modifiedBy" ModifiedOn="@_modifiedOn"></AuditInfo>
}
@code {
private int _fileId = -1;
private string _name;
private List<Folder> _folders;
private int _folderId = -1;
private int _size;
private string _createdBy;
private DateTime _createdOn;
private string _modifiedBy;
private DateTime _modifiedOn;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
public override string Title => "File Management";
protected override async Task OnInitializedAsync()
{
try
{
_folders = await FolderService.GetFoldersAsync(PageState.Site.SiteId);
_fileId = Int32.Parse(PageState.QueryString["id"]);
File file = await FileService.GetFileAsync(_fileId);
if (file != null)
{
_name = file.Name;
_folderId = file.FolderId;
_size = file.Size;
_createdBy = file.CreatedBy;
_createdOn = file.CreatedOn;
_modifiedBy = file.ModifiedBy;
_modifiedOn = file.ModifiedOn;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading File {FileId} {Error}", _fileId, ex.Message);
AddModuleMessage("Error Loading File", MessageType.Error);
}
}
private async Task SaveFile()
{
try
{
if (_name.IsPathOrFileValid())
{
File file = await FileService.GetFileAsync(_fileId);
file.Name = _name;
file.FolderId = _folderId;
file = await FileService.UpdateFileAsync(file);
await logger.LogInformation("File Saved {File}", file);
NavigationManager.NavigateTo(NavigateUrl());
}
else
{
AddModuleMessage("File Name Not Valid", MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving File {FileId} {Error}", _fileId, ex.Message);
AddModuleMessage("Error Saving File", MessageType.Error);
}
}
}

View File

@ -174,17 +174,33 @@
catch (Exception ex) catch (Exception ex)
{ {
await logger.LogError(ex, "Error Saving Folder {FolderId} {Error}", _folderId, ex.Message); await logger.LogError(ex, "Error Saving Folder {FolderId} {Error}", _folderId, ex.Message);
AddModuleMessage("Error Saving Module", MessageType.Error); AddModuleMessage("Error Saving Folder", MessageType.Error);
} }
} }
private async Task DeleteFolder() private async Task DeleteFolder()
{ {
try try
{
bool isparent = false;
foreach (Folder folder in _folders)
{
if (folder.ParentId == _folderId)
{
isparent = true;
break;
}
}
if (!isparent)
{ {
await FolderService.DeleteFolderAsync(_folderId); await FolderService.DeleteFolderAsync(_folderId);
await logger.LogInformation("Folder Deleted {Folder}", _folderId); await logger.LogInformation("Folder Deleted {Folder}", _folderId);
AddModuleMessage("Folder Deleted", MessageType.Success); NavigationManager.NavigateTo(NavigateUrl());
}
else
{
AddModuleMessage("Folder Has Child Folders And Cannot Be Deleted", MessageType.Warning);
}
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -28,13 +28,15 @@
</table> </table>
<Pager Items="@_files"> <Pager Items="@_files">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
<th>Modified</th> <th>Modified</th>
<th>Type</th> <th>Type</th>
<th>Size</th> <th>Size</th>
</Header> </Header>
<Row> <Row>
<td><ActionLink Action="Details" Text="Edit" Parameters="@($"id=" + context.FileId.ToString())" /></td>
<td><ActionDialog Header="Delete File" Message="@("Are You Sure You Wish To Delete " + context.Name + "?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" /></td> <td><ActionDialog Header="Delete File" Message="@("Are You Sure You Wish To Delete " + context.Name + "?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" /></td>
<td><a href="@(ContentUrl(context.FileId))" target="_new">@context.Name</a></td> <td><a href="@(ContentUrl(context.FileId))" target="_new">@context.Name</a></td>
<td>@context.ModifiedOn</td> <td>@context.ModifiedOn</td>

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

@ -15,14 +15,14 @@ else
<Pager Items="@_jobs"> <Pager Items="@_jobs">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
<th>Status</th> <th>Status</th>
<th>Frequency</th> <th>Frequency</th>
<th>Next Execution</th> <th>Next Execution</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
</Header> </Header>
<Row> <Row>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.JobId.ToString())" /></td> <td><ActionLink Action="Edit" Parameters="@($"id=" + context.JobId.ToString())" /></td>

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

@ -49,7 +49,7 @@ else
{ {
<Pager Items="@_logs"> <Pager Items="@_logs">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Date</th> <th>Date</th>
<th>Level</th> <th>Level</th>
<th>Feature</th> <th>Feature</th>

View File

@ -16,7 +16,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<Label For="module" HelpText="Enter a name for this module. It should be in singular form (ie. Car) and not contain spaces or punctuation.">Module Name: </Label> <Label For="module" HelpText="Enter a name for this module. It should not contain spaces or punctuation.">Module Name: </Label>
</td> </td>
<td> <td>
<input id="module" class="form-control" @bind="@_module" /> <input id="module" class="form-control" @bind="@_module" />

View File

@ -16,7 +16,7 @@
<Header> <Header>
<th>Name</th> <th>Name</th>
<th>Version</th> <th>Version</th>
<th></th> <th style="width: 1px"></th>
</Header> </Header>
<Row> <Row>
<td>@context.Name</td> <td>@context.Name</td>
@ -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

@ -14,11 +14,11 @@ else
<Pager Items="@_moduleDefinitions"> <Pager Items="@_moduleDefinitions">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
<th>Version</th> <th>Version</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
</Header> </Header>
<Row> <Row>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" /></td> <td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" /></td>
@ -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)
{ {
@ -333,7 +320,7 @@
_children = new List<Page>(); _children = new List<Page>();
if (_parentid == "-1") if (_parentid == "-1")
{ {
foreach(Page p in PageState.Pages.Where(item => item.ParentId == null)) foreach (Page p in PageState.Pages.Where(item => item.ParentId == null))
{ {
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions)) if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
{ {
@ -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

@ -9,8 +9,8 @@
<Pager Items="@PageState.Pages.Where(item => !item.IsDeleted)"> <Pager Items="@PageState.Pages.Where(item => !item.IsDeleted)">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
</Header> </Header>
<Row> <Row>

View File

@ -145,6 +145,7 @@
profile = new Profile(); profile = new Profile();
} }
profile.SiteId = PageState.Site.SiteId;
profile.Name = _name; profile.Name = _name;
profile.Title = _title; profile.Title = _title;
profile.Description = _description; profile.Description = _description;

View File

@ -12,8 +12,8 @@ else
<Pager Items="@_profiles"> <Pager Items="@_profiles">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
</Header> </Header>
<Row> <Row>

View File

@ -16,8 +16,8 @@
{ {
<Pager Items="@_pages"> <Pager Items="@_pages">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
<th>Deleted By</th> <th>Deleted By</th>
<th>Deleted On</th> <th>Deleted On</th>
@ -42,8 +42,8 @@
{ {
<Pager Items="@_modules"> <Pager Items="@_modules">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Page</th> <th>Page</th>
<th>Module</th> <th>Module</th>
<th>Deleted By</th> <th>Deleted By</th>

View File

@ -12,9 +12,9 @@ else
<Pager Items="@_roles"> <Pager Items="@_roles">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
</Header> </Header>
<Row> <Row>

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

@ -14,8 +14,8 @@ else
<Pager Items="@_sites"> <Pager Items="@_sites">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
</Header> </Header>
<Row> <Row>

View File

@ -11,8 +11,8 @@ else
{ {
<Pager Items="@tenants"> <Pager Items="@tenants">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
</Header> </Header>
<Row> <Row>

View File

@ -16,7 +16,7 @@
<Header> <Header>
<th>Name</th> <th>Name</th>
<th>Version</th> <th>Version</th>
<th></th> <th style="width: 1px;"></th>
</Header> </Header>
<Row> <Row>
<td>@context.Name</td> <td>@context.Name</td>
@ -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

@ -15,10 +15,10 @@ else
<Pager Items="@_themes"> <Pager Items="@_themes">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th scope="col">Name</th>
<th>Version</th> <th scope="col">Version</th>
<th>&nbsp;</th> <th>&nbsp;</th>
</Header> </Header>
<Row> <Row>
@ -37,6 +37,7 @@ else
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.ThemeName, context.Version))>Upgrade</button> <button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.ThemeName, context.Version))>Upgrade</button>
} }
</td> </td>
<td></td>
</Row> </Row>
</Pager> </Pager>
} }
@ -86,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)
@ -102,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

@ -66,6 +66,7 @@
notification.CreatedOn = DateTime.UtcNow; notification.CreatedOn = DateTime.UtcNow;
notification.IsDelivered = false; notification.IsDelivered = false;
notification.DeliveredOn = null; notification.DeliveredOn = null;
notification.SendOn = DateTime.UtcNow;
notification = await NotificationService.AddNotificationAsync(notification); notification = await NotificationService.AddNotificationAsync(notification);
await logger.LogInformation("Notification Created {Notification}", notification); await logger.LogInformation("Notification Created {Notification}", notification);
NavigationManager.NavigateTo(NavigateUrl()); NavigationManager.NavigateTo(NavigateUrl());

View File

@ -32,7 +32,7 @@ else
<label for="Name" class="control-label">Password: </label> <label for="Name" class="control-label">Password: </label>
</td> </td>
<td> <td>
<input type="password" class="form-control" @bind="@password" /> <input type="password" class="form-control" @bind="@password" autocomplete="new-password" />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -40,7 +40,7 @@ else
<label for="Name" class="control-label">Confirm Password: </label> <label for="Name" class="control-label">Confirm Password: </label>
</td> </td>
<td> <td>
<input type="password" class="form-control" @bind="@confirm" /> <input type="password" class="form-control" @bind="@confirm" autocomplete="new-password" />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -79,6 +79,8 @@ else
@foreach (Profile profile in profiles) @foreach (Profile profile in profiles)
{ {
var p = profile; var p = profile;
if (!p.IsPrivate || UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole))
{
if (p.Category != category) if (p.Category != category)
{ {
<tr> <tr>
@ -90,13 +92,21 @@ else
} }
<tr> <tr>
<td> <td>
<label for="@p.Name" class="control-label">@p.Title: </label> <Label For="@p.Name" HelpText="@p.Description">@p.Title</Label>
</td> </td>
<td> <td>
<input class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" placeholder="@p.Description" @onchange="@(e => ProfileChanged(e, p.Name))" /> @if (p.IsRequired)
{
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" />
}
else
{
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" />
}
</td> </td>
</tr> </tr>
} }
}
</table> </table>
<button type="button" class="btn btn-primary" @onclick="Save">Save</button> <button type="button" class="btn btn-primary" @onclick="Save">Save</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">Cancel</button> <button type="button" class="btn btn-secondary" @onclick="Cancel">Cancel</button>
@ -111,8 +121,8 @@ else
{ {
<Pager Items="@notifications"> <Pager Items="@notifications">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>From</th> <th>From</th>
<th>Subject</th> <th>Subject</th>
<th>Received</th> <th>Received</th>
@ -241,7 +251,7 @@ else
{ {
try try
{ {
if (username != string.Empty && email != string.Empty) if (username != string.Empty && email != string.Empty && ValidateProfiles())
{ {
if (password == confirm) if (password == confirm)
{ {
@ -261,6 +271,7 @@ else
await UserService.UpdateUserAsync(user); await UserService.UpdateUserAsync(user);
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId); await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
await logger.LogInformation("User Profile Saved"); await logger.LogInformation("User Profile Saved");
AddModuleMessage("User Profile Updated Successfully", MessageType.Success);
} }
else else
{ {
@ -269,7 +280,7 @@ else
} }
else else
{ {
AddModuleMessage("You Must Provide A Username and Email Address", MessageType.Warning); AddModuleMessage("You Must Provide A Username and Email Address As Well As All Required Profile Information", MessageType.Warning);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -279,6 +290,26 @@ else
} }
} }
private bool ValidateProfiles()
{
bool valid = true;
foreach (Profile profile in profiles)
{
if (string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)) && !string.IsNullOrEmpty(profile.DefaultValue))
{
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
}
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole))
{
if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
{
valid = false;
}
}
}
return valid;
}
private void Cancel() private void Cancel()
{ {
NavigationManager.NavigateTo(NavigateUrl(string.Empty)); NavigationManager.NavigateTo(NavigateUrl(string.Empty));

View File

@ -33,7 +33,7 @@
<td> <td>
<input class="form-control" @bind="@subject" readonly /> <input class="form-control" @bind="@subject" readonly />
</td> </td>
} }
@if (title == "To") @if (title == "To")
{ {
<td> <td>
@ -51,7 +51,7 @@
<input class="form-control" @bind="@createdon" readonly /> <input class="form-control" @bind="@createdon" readonly />
</td> </td>
</tr> </tr>
} }
@if (title == "From") @if (title == "From")
{ {
<tr> <tr>
@ -62,7 +62,7 @@
<textarea class="form-control" @bind="@body" rows="5" readonly /> <textarea class="form-control" @bind="@body" rows="5" readonly />
</td> </td>
</tr> </tr>
} }
@if (title == "To") @if (title == "To")
{ {
<tr> <tr>
@ -73,7 +73,7 @@
<textarea class="form-control" @bind="@body" rows="5" /> <textarea class="form-control" @bind="@body" rows="5" />
</td> </td>
</tr> </tr>
} }
</table> </table>
@ -192,6 +192,7 @@
notification.CreatedOn = DateTime.UtcNow; notification.CreatedOn = DateTime.UtcNow;
notification.IsDelivered = false; notification.IsDelivered = false;
notification.DeliveredOn = null; notification.DeliveredOn = null;
notification.SendOn = DateTime.UtcNow;
notification = await NotificationService.AddNotificationAsync(notification); notification = await NotificationService.AddNotificationAsync(notification);
await logger.LogInformation("Notification Created {Notification}", notification); await logger.LogInformation("Notification Created {Notification}", notification);
NavigationManager.NavigateTo(NavigateUrl()); NavigationManager.NavigateTo(NavigateUrl());

View File

@ -71,10 +71,17 @@
} }
<tr> <tr>
<td> <td>
<label for="@p.Name" class="control-label">@p.Title: </label> <Label For="@p.Name" HelpText="@p.Description">@p.Title</Label>
</td> </td>
<td> <td>
<input class="form-control" maxlength="@p.MaxLength" placeholder="@p.Description" @onchange="@(e => ProfileChanged(e, p.Name))" /> @if (p.IsRequired)
{
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" />
}
else
{
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" />
}
</td> </td>
</tr> </tr>
} }
@ -112,11 +119,14 @@
} }
} }
private string GetProfileValue(string SettingName, string DefaultValue)
=> SettingService.GetSetting(settings, SettingName, DefaultValue);
private async Task SaveUser() private async Task SaveUser()
{ {
try try
{ {
if (username != string.Empty && password != string.Empty && confirm != string.Empty && email != string.Empty) if (username != string.Empty && password != string.Empty && confirm != string.Empty && email != string.Empty && ValidateProfiles())
{ {
if (password == confirm) if (password == confirm)
{ {
@ -149,7 +159,7 @@
} }
else else
{ {
AddModuleMessage("You Must Provide A Username, Password, and Email Address", MessageType.Warning); AddModuleMessage("You Must Provide A Username, Password, Email Address And All Required Profile Information", MessageType.Warning);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -159,6 +169,23 @@
} }
} }
private bool ValidateProfiles()
{
bool valid = true;
foreach (Profile profile in profiles)
{
if (string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)) && !string.IsNullOrEmpty(profile.DefaultValue))
{
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
}
if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
{
valid = false;
}
}
return valid;
}
private void ProfileChanged(ChangeEventArgs e, string SettingName) private void ProfileChanged(ChangeEventArgs e, string SettingName)
{ {
var value = (string)e.Value; var value = (string)e.Value;

View File

@ -98,10 +98,17 @@ else
} }
<tr> <tr>
<td> <td>
<label for="@p.Name" class="control-label">@p.Title: </label> <Label For="@p.Name" HelpText="@p.Description">@p.Title</Label>
</td> </td>
<td> <td>
<input class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" placeholder="@p.Description" @onchange="@(e => ProfileChanged(e, p.Name))" /> @if (p.IsRequired)
{
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" />
}
else
{
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" />
}
</td> </td>
</tr> </tr>
} }
@ -180,7 +187,7 @@ else
{ {
try try
{ {
if (username != string.Empty && email != string.Empty) if (username != string.Empty && email != string.Empty && ValidateProfiles())
{ {
if (password == confirm) if (password == confirm)
{ {
@ -213,7 +220,7 @@ else
} }
else else
{ {
AddModuleMessage("You Must Provide A Username, Password, and Email Address", MessageType.Warning); AddModuleMessage("You Must Provide A Username, Password, Email Address, And All Required Profile Information", MessageType.Warning);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -223,6 +230,23 @@ else
} }
} }
private bool ValidateProfiles()
{
bool valid = true;
foreach (Profile profile in profiles)
{
if (string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)) && !string.IsNullOrEmpty(profile.DefaultValue))
{
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
}
if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
{
valid = false;
}
}
return valid;
}
private void ProfileChanged(ChangeEventArgs e, string SettingName) private void ProfileChanged(ChangeEventArgs e, string SettingName)
{ {
var value = (string)e.Value; var value = (string)e.Value;

View File

@ -20,9 +20,9 @@ else
<Pager Items="@userroles"> <Pager Items="@userroles">
<Header> <Header>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>&nbsp;</th> <th style="width: 1px;">&nbsp;</th>
<th>Name</th> <th>Name</th>
</Header> </Header>
<Row> <Row>

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
@ -90,7 +89,7 @@
if (!string.IsNullOrEmpty(IconName)) if (!string.IsNullOrEmpty(IconName))
{ {
_iconSpan = $"<span class=\"oi oi-{IconName}\"></span>{(IconOnly?"":"&nbsp")}"; _iconSpan = $"<span class=\"oi oi-{IconName}\"></span>{(IconOnly ? "" : "&nbsp")}";
} }

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
@ -56,16 +54,16 @@
<div> <div>
@if (UploadMultiple) @if (UploadMultiple)
{ {
<input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple/> <input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple />
} }
else else
{ {
<input type="file" id="@_fileinputid" name="file" accept="@_filter"/> <input type="file" id="@_fileinputid" name="file" accept="@_filter" />
} }
<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;
@ -134,7 +131,7 @@
if (!string.IsNullOrEmpty(Folder)) if (!string.IsNullOrEmpty(Folder))
{ {
_folders = new List<Folder> {new Folder {FolderId = -1, Name = Folder}}; _folders = new List<Folder> { new Folder { FolderId = -1, Name = Folder } };
FolderId = -1; FolderId = -1;
} }
else else
@ -211,7 +208,7 @@
_message = string.Empty; _message = string.Empty;
try try
{ {
FolderId = int.Parse((string) e.Value); FolderId = int.Parse((string)e.Value);
await GetFiles(); await GetFiles();
FileId = -1; FileId = -1;
_image = string.Empty; _image = string.Empty;
@ -227,7 +224,7 @@
private async Task FileChanged(ChangeEventArgs e) private async Task FileChanged(ChangeEventArgs e)
{ {
_message = string.Empty; _message = string.Empty;
FileId = int.Parse((string) e.Value); FileId = int.Parse((string)e.Value);
await SetImage(); await SetImage();
StateHasChanged(); StateHasChanged();
@ -244,8 +241,8 @@
var maxwidth = 200; var maxwidth = 200;
var maxheight = 200; var maxheight = 200;
var ratioX = (double) maxwidth / (double) file.ImageWidth; var ratioX = (double)maxwidth / (double)file.ImageWidth;
var ratioY = (double) maxheight / (double) file.ImageHeight; var ratioY = (double)maxheight / (double)file.ImageHeight;
var ratio = ratioX < ratioY ? ratioX : ratioY; var ratio = ratioX < ratioY ? ratioX : ratioY;
_image = "<img src=\"" + ContentUrl(FileId) + "\" alt=\"" + file.Name + _image = "<img src=\"" + ContentUrl(FileId) + "\" alt=\"" + file.Name +

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,11 +1,9 @@
@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")
{ {
<table class="@Class"> <table class="@Class">
<thead> <thead>
@ -23,7 +21,7 @@
</tbody> </tbody>
</table> </table>
} }
@if(Format == "Grid") @if (Format == "Grid")
{ {
<div class="@Class"> <div class="@Class">
<div class="row">@Header</div> <div class="row">@Header</div>

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
@ -10,10 +9,10 @@
<table class="table" style="width: 50%; min-width: 250px;"> <table class="table" style="width: 50%; min-width: 250px;">
<tbody> <tbody>
<tr> <tr>
<th>Role</th> <th scope="col">Role</th>
@foreach (PermissionString permission in _permissions) @foreach (PermissionString permission in _permissions)
{ {
<th style="text-align: center;">@permission.PermissionName</th> <th style="text-align: center; width: 1px;">@permission.PermissionName</th>
} }
</tr> </tr>
@foreach (Role role in _roles) @foreach (Role role in _roles)
@ -36,10 +35,10 @@
<table class="table" style="width: 50%; min-width: 250px;"> <table class="table" style="width: 50%; min-width: 250px;">
<thead> <thead>
<tr> <tr>
<th>User</th> <th scope="col">User</th>
@foreach (PermissionString permission in _permissions) @foreach (PermissionString permission in _permissions)
{ {
<th style="text-align: center;">@permission.PermissionName</th> <th style="text-align: center; width: 1px;">@permission.PermissionName</th>
} }
</tr> </tr>
</thead> </thead>
@ -52,7 +51,7 @@
@foreach (PermissionString permission in _permissions) @foreach (PermissionString permission in _permissions)
{ {
var p = permission; var p = permission;
<td style="text-align: center;"> <td style="text-align: center; width: 1px;">
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled=false OnChange="@(e => PermissionChanged(e, p.PermissionName, userid))" /> <TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled=false OnChange="@(e => PermissionChanged(e, p.PermissionName, userid))" />
</td> </td>
} }
@ -64,9 +63,10 @@
<table class="table" style="width: 50%; min-width: 250px;"> <table class="table" style="width: 50%; min-width: 250px;">
<tbody> <tbody>
<tr> <tr>
<td style="text-align: right;"><label for="Username" class="control-label">User: </label></td> <td class="input-group">
<td><input type="text" name="Username" class="form-control" placeholder="Enter Username" @bind="@_username" /></td> <input type="text" name="Username" class="form-control" placeholder="Enter Username" @bind="@_username" />
<td style="text-align: left;"><button type="button" class="btn btn-primary" @onclick="AddUser">Add</button></td> <button type="button" class="btn btn-primary" @onclick="AddUser">Add</button>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

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">
@ -108,7 +107,7 @@
public string DebugLevel { get; set; } = "info"; public string DebugLevel { get; set; } = "info";
public override List<Resource> Resources => new List<Resource>() public override List<Resource> Resources => new List<Resource>()
{ {
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill1.3.6.min.js" }, new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill1.3.6.min.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js" }, new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js" } new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js" }

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.0</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>Not for production use.</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

@ -1,28 +1,26 @@
using Oqtane.Models; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Reflection; using Oqtane.Models;
using System;
using Oqtane.Shared; using Oqtane.Shared;
namespace Oqtane.Services namespace Oqtane.Services
{ {
public class ThemeService : ServiceBase, IThemeService public class ThemeService : ServiceBase, IThemeService
{ {
private readonly HttpClient _http; private readonly SiteState _siteState;
public ThemeService(HttpClient http) : base(http) public ThemeService(HttpClient http, SiteState siteState) : base(http)
{ {
_http = http; _siteState = siteState;
} }
private string Apiurl => CreateApiUrl("Theme"); private string ApiUrl => CreateApiUrl(_siteState.Alias, "Theme");
public async Task<List<Theme>> GetThemesAsync() public async Task<List<Theme>> GetThemesAsync()
{ {
List<Theme> themes = await GetJsonAsync<List<Theme>>(Apiurl); List<Theme> themes = await GetJsonAsync<List<Theme>>(ApiUrl);
return themes.OrderBy(item => item.Name).ToList(); return themes.OrderBy(item => item.Name).ToList();
} }
@ -45,12 +43,12 @@ namespace Oqtane.Services
public async Task InstallThemesAsync() public async Task InstallThemesAsync()
{ {
await GetJsonAsync<List<string>>($"{Apiurl}/install"); await GetJsonAsync<List<string>>($"{ApiUrl}/install");
} }
public async Task DeleteThemeAsync(string themeName) public async Task DeleteThemeAsync(string themeName)
{ {
await DeleteAsync($"{Apiurl}/{themeName}"); await DeleteAsync($"{ApiUrl}/{themeName}");
} }
} }
} }

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Themes.BlazorTheme @namespace Oqtane.Themes.BlazorTheme
@inherits ThemeBase @inherits ThemeBase
@implements IThemeControl
<div class="breadcrumbs"> <div class="breadcrumbs">
<Breadcrumbs /> <Breadcrumbs />
@ -31,11 +30,11 @@
public override List<Resource> Resources => new List<Resource>() public override List<Resource> Resources => new List<Resource>()
{ {
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css", Integrity = "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T", CrossOrigin = "anonymous" }, new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css", Integrity = "sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk", CrossOrigin = "anonymous" },
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }, new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://code.jquery.com/jquery-3.3.1.slim.min.js", Integrity = "sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo", CrossOrigin = "anonymous" }, new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://code.jquery.com/jquery-3.5.1.slim.min.js", Integrity = "sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj", CrossOrigin = "anonymous" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js", Integrity = "sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1", CrossOrigin = "anonymous" }, new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js", Integrity = "sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo", CrossOrigin = "anonymous" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js", Integrity = "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM", CrossOrigin = "anonymous" } new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js", Integrity = "sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI", CrossOrigin = "anonymous" }
}; };
} }

View File

@ -7,5 +7,6 @@ namespace Oqtane.Themes
{ {
[CascadingParameter] [CascadingParameter]
protected Module ModuleState { get; set; } protected Module ModuleState { get; set; }
} }
} }

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits ThemeControlBase @inherits ThemeControlBase
@attribute [OqtaneIgnore]
@if (BreadCrumbPages.Any()) @if (BreadCrumbPages.Any())
{ {

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits ThemeControlBase @inherits ThemeControlBase
@attribute [OqtaneIgnore]
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@inject IUserService UserService @inject IUserService UserService
@inject IModuleDefinitionService ModuleDefinitionService @inject IModuleDefinitionService ModuleDefinitionService
@ -127,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)
} }
@ -197,14 +199,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)
{ {
<button type="button" class="btn @ButtonClass active" data-toggle="button" aria-pressed="true" autocomplete="off" @onclick="(async () => await ToggleEditMode(PageState.EditMode))"> <button type="button" class="btn @ButtonClass active" data-toggle="button" aria-pressed="true" autocomplete="off" @onclick="(async () => await ToggleEditMode(PageState.EditMode))">
@ -217,7 +211,6 @@
<span class="oi oi-pencil"></span> <span class="oi oi-pencil"></span>
</button> </button>
} }
}
} }
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions)) @if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits LoginBase @inherits LoginBase
@attribute [OqtaneIgnore]
<span class="app-login"> <span class="app-login">
<AuthorizeView> <AuthorizeView>

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits ThemeControlBase @inherits ThemeControlBase
@attribute [OqtaneIgnore]
@if (PageState.Site.LogoFileId != null) @if (PageState.Site.LogoFileId != null)
{ {

View File

@ -1,6 +1,6 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits MenuBase @inherits MenuBase
@attribute [OqtaneIgnore]
@if (MenuPages.Any()) @if (MenuPages.Any())
{ {
<span class="app-menu-toggler"> <span class="app-menu-toggler">

View File

@ -1,6 +1,6 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits MenuBase @inherits MenuBase
@attribute [OqtaneIgnore]
@if (MenuPages.Any()) @if (MenuPages.Any())
{ {
<span class="app-menu-toggler"> <span class="app-menu-toggler">

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

@ -1,6 +1,6 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits ThemeControlBase @inherits ThemeControlBase
@attribute [OqtaneIgnore]
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
<span class="app-profile"> <span class="app-profile">

View File

@ -2,7 +2,6 @@
{ {
public interface IContainerControl public interface IContainerControl
{ {
string Name { get; } // friendly name for a container
string Thumbnail { get; } // screen shot of a container - assumed to be in the ThemePath() folder
} }
} }

View File

@ -2,9 +2,6 @@
{ {
public interface ILayoutControl public interface ILayoutControl
{ {
string Name { get; } // friendly name for a layout
string Thumbnail { get; } // screen shot of a layout - assumed to be in the ThemePath() folder
string Panes { get; } // identifies all panes in a theme ( delimited by "," or ";" )
} }
} }

View File

@ -1,6 +1,5 @@
@namespace Oqtane.Themes.OqtaneTheme @namespace Oqtane.Themes.OqtaneTheme
@inherits ThemeBase @inherits ThemeBase
@implements IThemeControl
<main role="main"> <main role="main">
<nav class="navbar navbar-expand-md navbar-dark bg-primary fixed-top"> <nav class="navbar navbar-expand-md navbar-dark bg-primary fixed-top">
@ -24,10 +23,10 @@
public override List<Resource> Resources => new List<Resource>() public override List<Resource> Resources => new List<Resource>()
{ {
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css", Integrity = "sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM", CrossOrigin = "anonymous" }, new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootswatch/4.5.0/cyborg/bootstrap.min.css", Integrity = "sha384-GKugkVcT8wqoh3M8z1lqHbU+g6j498/ZT/zuXbepz7Dc09/otQZxTimkEMTkRWHP", CrossOrigin = "anonymous" },
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }, new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://code.jquery.com/jquery-3.3.1.slim.min.js", Integrity = "sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo", CrossOrigin = "anonymous" }, new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://code.jquery.com/jquery-3.5.1.slim.min.js", Integrity = "sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj", CrossOrigin = "anonymous" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js", Integrity = "sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1", CrossOrigin = "anonymous" }, new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js", Integrity = "sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo", CrossOrigin = "anonymous" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js", Integrity = "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM", CrossOrigin = "anonymous" } new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js", Integrity = "sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI", CrossOrigin = "anonymous" }
}; };
} }

View File

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace Oqtane.Themes namespace Oqtane.Themes
{ {
public abstract class ThemeBase : ComponentBase public abstract class ThemeBase : ComponentBase, IThemeControl
{ {
[Inject] [Inject]
protected IJSRuntime JSRuntime { get; set; } protected IJSRuntime JSRuntime { get; set; }

View File

@ -1,5 +1,8 @@
namespace Oqtane.Themes using Oqtane.Shared;
namespace Oqtane.Themes
{ {
[OqtaneIgnore]
public abstract class ThemeControlBase : ThemeBase public abstract class ThemeControlBase : ThemeBase
{ {

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;
@ -375,7 +420,7 @@
Type layouttype = Type.GetType(page.LayoutType); Type layouttype = Type.GetType(page.LayoutType);
if (layouttype != null) if (layouttype != null)
{ {
var layoutobject = Activator.CreateInstance(layouttype) as ILayoutControl; var layoutobject = Activator.CreateInstance(layouttype) as IThemeControl;
if (layoutobject != null) if (layoutobject != null)
{ {
panes = layoutobject.Panes; panes = layoutobject.Panes;
@ -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.0</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>Initial Release</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.0</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>Initial Release</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.0</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>Initial Release</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.0</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>Initial Release</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;
@ -135,8 +135,20 @@ namespace Oqtane.Controllers
[Authorize(Roles = Constants.RegisteredRole)] [Authorize(Roles = Constants.RegisteredRole)]
public Models.File Put(int id, [FromBody] Models.File file) public Models.File Put(int id, [FromBody] Models.File file)
{ {
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Folder, file.Folder.FolderId, PermissionNames.Edit)) if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Folder, file.FolderId, PermissionNames.Edit))
{ {
file.Folder = _folders.GetFolder(file.FolderId);
Models.File _file = _files.GetFile(id, false);
if (_file.Name != file.Name || _file.FolderId != file.FolderId)
{
string folderpath = GetFolderPath(file.Folder);
if (!Directory.Exists(folderpath))
{
Directory.CreateDirectory(folderpath);
}
System.IO.File.Move(Path.Combine(GetFolderPath(_file.Folder), _file.Name), Path.Combine(folderpath, file.Name));
}
file.Extension = Path.GetExtension(file.Name).ToLower().Replace(".", "");
file = _files.UpdateFile(file); file = _files.UpdateFile(file);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "File Updated {File}", file); _logger.Log(LogLevel.Information, this, LogFunction.Update, "File Updated {File}", file);
} }
@ -483,7 +495,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;
@ -10,20 +11,25 @@ using Oqtane.Extensions;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using Oqtane.Repository; using Oqtane.Repository;
using Oqtane.Security; using Oqtane.Security;
using Microsoft.AspNetCore.Hosting;
namespace Oqtane.Controllers namespace Oqtane.Controllers
{ {
[Route("{alias}/api/[controller]")] [Route("{alias}/api/[controller]")]
public class FolderController : Controller public class FolderController : Controller
{ {
private readonly IWebHostEnvironment _environment;
private readonly IFolderRepository _folders; private readonly IFolderRepository _folders;
private readonly IUserPermissions _userPermissions; private readonly IUserPermissions _userPermissions;
private readonly ITenantResolver _tenants;
private readonly ILogManager _logger; private readonly ILogManager _logger;
public FolderController(IFolderRepository folders, IUserPermissions userPermissions, ILogManager logger) public FolderController(IWebHostEnvironment environment, IFolderRepository folders, IUserPermissions userPermissions, ITenantResolver tenants, ILogManager logger)
{ {
_environment = environment;
_folders = folders; _folders = folders;
_userPermissions = userPermissions; _userPermissions = userPermissions;
_tenants = tenants;
_logger = logger; _logger = logger;
} }
@ -112,7 +118,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);
} }
@ -142,12 +148,19 @@ namespace Oqtane.Controllers
{ {
if (folder.IsPathValid()) if (folder.IsPathValid())
{ {
if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null) if (folder.ParentId != null)
{ {
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());
Models.Folder _folder = _folders.GetFolder(id, false);
if (_folder.Path != folder.Path && Directory.Exists(GetFolderPath(_folder)))
{
Directory.Move(GetFolderPath(_folder), GetFolderPath(folder));
}
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);
} }
@ -210,5 +223,10 @@ namespace Oqtane.Controllers
HttpContext.Response.StatusCode = 401; HttpContext.Response.StatusCode = 401;
} }
} }
private string GetFolderPath(Folder folder)
{
return Utilities.PathCombine(_environment.ContentRootPath, "Content", "Tenants", _tenants.GetTenant().TenantId.ToString(), "Sites", folder.SiteId.ToString(), folder.Path);
}
} }
} }

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,19 +170,19 @@ 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 + ", Oqtane.Client";
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, Oqtane.Server"; moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + ".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,Path.DirectorySeparatorChar.ToString());
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Client.Oqtane"; moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + ", " + moduleDefinition.Owner + "." + moduleDefinition.Name + ".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 + ".Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + ".Server.Oqtane";
} }
ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, rootFolder.Name, templatePath, moduleDefinition); ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, rootFolder.Name, templatePath, moduleDefinition);
@ -196,8 +196,8 @@ namespace Oqtane.Controllers
{ {
// add embedded resources to project // add embedded resources to project
List<string> resources = new List<string>(); List<string> resources = new List<string>();
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name + "s", "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.1.0.0.sql")); resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + ".1.0.0.sql"));
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name + "s", "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Uninstall.sql")); resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + ".Uninstall.sql"));
EmbedResourceFiles(Utilities.PathCombine(rootPath, "Oqtane.Server", "Oqtane.Server.csproj"), resources); EmbedResourceFiles(Utilities.PathCombine(rootPath, "Oqtane.Server", "Oqtane.Server.csproj"), resources);
} }

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;
@ -148,7 +149,7 @@ namespace Oqtane.Controllers
notification.SiteId = user.SiteId; notification.SiteId = user.SiteId;
notification.FromUserId = null; notification.FromUserId = null;
notification.ToUserId = newUser.UserId; notification.ToUserId = newUser.UserId;
notification.ToEmail = ""; notification.ToEmail = newUser.Email;
notification.Subject = "User Account Verification"; notification.Subject = "User Account Verification";
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser); string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
string url = HttpContext.Request.Scheme + "://" + _tenants.GetAlias().Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token); string url = HttpContext.Request.Scheme + "://" + _tenants.GetAlias().Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
@ -157,6 +158,7 @@ namespace Oqtane.Controllers
notification.CreatedOn = DateTime.UtcNow; notification.CreatedOn = DateTime.UtcNow;
notification.IsDelivered = false; notification.IsDelivered = false;
notification.DeliveredOn = null; notification.DeliveredOn = null;
notification.SendOn = DateTime.UtcNow;
_notifications.AddNotification(notification); _notifications.AddNotification(notification);
} }
@ -173,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
@ -181,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\":\"[" +
@ -385,6 +387,7 @@ namespace Oqtane.Controllers
notification.CreatedOn = DateTime.UtcNow; notification.CreatedOn = DateTime.UtcNow;
notification.IsDelivered = false; notification.IsDelivered = false;
notification.DeliveredOn = null; notification.DeliveredOn = null;
notification.SendOn = DateTime.UtcNow;
_notifications.AddNotification(notification); _notifications.AddNotification(notification);
_logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset Notification Sent For {Username}", user.Username); _logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset Notification Sent For {Username}", user.Username);
} }

View File

@ -1,15 +1,12 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.Loader; using System.Runtime.Loader;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Oqtane.Extensions;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using Oqtane.Modules; using Oqtane.Modules;
using Oqtane.Services; using Oqtane.Services;
using Oqtane.Shared;
using Oqtane.UI; using Oqtane.UI;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
@ -72,14 +69,15 @@ namespace Microsoft.Extensions.DependencyInjection
return services; return services;
} }
private static void LoadAssemblies() private static void LoadAssemblies()
{ {
var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
if (assemblyPath == null) return; if (assemblyPath == null) return;
var assembliesFolder = new DirectoryInfo(assemblyPath); AssemblyLoadContext.Default.Resolving += ResolveDependencies;
var assembliesFolder = new DirectoryInfo(assemblyPath);
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
// iterate through Oqtane assemblies in /bin ( filter is narrow to optimize loading process ) // iterate through Oqtane assemblies in /bin ( filter is narrow to optimize loading process )
foreach (var dll in assembliesFolder.EnumerateFiles($"*.dll", SearchOption.TopDirectoryOnly).Where(f => f.IsOqtaneAssembly())) foreach (var dll in assembliesFolder.EnumerateFiles($"*.dll", SearchOption.TopDirectoryOnly).Where(f => f.IsOqtaneAssembly()))
@ -95,7 +93,6 @@ namespace Microsoft.Extensions.DependencyInjection
continue; continue;
} }
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
if (!assemblies.Any(a => AssemblyName.ReferenceMatchesDefinition(assemblyName, a.GetName()))) if (!assemblies.Any(a => AssemblyName.ReferenceMatchesDefinition(assemblyName, a.GetName())))
{ {
try try
@ -121,5 +118,19 @@ namespace Microsoft.Extensions.DependencyInjection
} }
} }
} }
private static Assembly ResolveDependencies(AssemblyLoadContext context, AssemblyName name)
{
var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location) + "\\" + name.Name + ".dll";
if (File.Exists(assemblyPath))
{
return context.LoadFromStream(new MemoryStream(File.ReadAllBytes(assemblyPath)));
}
else
{
return null;
}
}
} }
} }

View File

@ -342,7 +342,8 @@ namespace Oqtane.Infrastructure
if (!string.IsNullOrEmpty(moduledefinition.ReleaseVersions) && !string.IsNullOrEmpty(moduledefinition.ServerManagerType)) if (!string.IsNullOrEmpty(moduledefinition.ReleaseVersions) && !string.IsNullOrEmpty(moduledefinition.ServerManagerType))
{ {
Type moduletype = Type.GetType(moduledefinition.ServerManagerType); Type moduletype = Type.GetType(moduledefinition.ServerManagerType);
if (moduletype != null)
{
string[] versions = moduledefinition.ReleaseVersions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); string[] versions = moduledefinition.ReleaseVersions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))) using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey))))
{ {
@ -387,6 +388,7 @@ namespace Oqtane.Infrastructure
} }
} }
} }
}
if (string.IsNullOrEmpty(result.Message)) if (string.IsNullOrEmpty(result.Message))
{ {
@ -461,7 +463,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 +471,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()
{ {
@ -131,7 +144,7 @@ namespace Oqtane.Infrastructure
{ {
// get package with highest version and clean up any others // get package with highest version and clean up any others
string packagename = ""; string packagename = "";
foreach(string package in Directory.GetFiles(folder, "Oqtane.Framework.*.nupkg")) foreach (string package in Directory.GetFiles(folder, "Oqtane.Framework.*.nupkg"))
{ {
if (packagename != "") if (packagename != "")
{ {
@ -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.0</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>Not for production use.</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>
@ -31,6 +31,8 @@
<EmbeddedResource Include="Scripts\Tenant.00.09.01.00.sql" /> <EmbeddedResource Include="Scripts\Tenant.00.09.01.00.sql" />
<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.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>
@ -48,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

@ -45,7 +45,21 @@ namespace Oqtane.Repository
public File GetFile(int fileId) public File GetFile(int fileId)
{ {
File file = _db.File.Where(item => item.FileId == fileId).Include(item => item.Folder).FirstOrDefault(); return GetFile(fileId, true);
}
public File GetFile(int fileId, bool tracking)
{
File file;
if (tracking)
{
file = _db.File.Where(item => item.FileId == fileId).Include(item => item.Folder).FirstOrDefault();
}
else
{
file = _db.File.AsNoTracking().Where(item => item.FileId == fileId).Include(item => item.Folder).FirstOrDefault();
}
if (file != null) if (file != null)
{ {
IEnumerable<Permission> permissions = _permissions.GetPermissions(EntityNames.Folder, file.FolderId).ToList(); IEnumerable<Permission> permissions = _permissions.GetPermissions(EntityNames.Folder, file.FolderId).ToList();

Some files were not shown because too many files have changed in this diff Show More