commit
a886ae12cc
|
@ -149,12 +149,18 @@
|
||||||
{
|
{
|
||||||
folder = await FolderService.AddFolderAsync(folder);
|
folder = await FolderService.AddFolderAsync(folder);
|
||||||
}
|
}
|
||||||
|
if (folder != null)
|
||||||
|
{
|
||||||
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
|
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
|
||||||
await logger.LogInformation("Folder Saved {Folder}", folder);
|
await logger.LogInformation("Folder Saved {Folder}", folder);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage("An Error Was Encountered Saving The Folder", MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage("Folders Must Have A Parent And A Name", MessageType.Warning);
|
AddModuleMessage("Folders Must Have A Parent And A Name", MessageType.Warning);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,8 @@
|
||||||
|
|
||||||
@namespace [Owner].[Module]s.Modules
|
@namespace [Owner].[Module]s.Modules
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@inject I[Module]Service [Module]Service
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject HttpClient http
|
|
||||||
@inject SiteState sitestate
|
|
||||||
|
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -31,7 +30,6 @@
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
public override string Actions => "Add,Edit";
|
public override string Actions => "Add,Edit";
|
||||||
|
|
||||||
I[Module]Service [Module]Service;
|
|
||||||
int _id;
|
int _id;
|
||||||
string _name;
|
string _name;
|
||||||
string _createdby;
|
string _createdby;
|
||||||
|
@ -43,7 +41,6 @@
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
[Module]Service = new [Module]Service(http, sitestate);
|
|
||||||
if (PageState.Action == "Edit")
|
if (PageState.Action == "Edit")
|
||||||
{
|
{
|
||||||
_id = Int32.Parse(PageState.QueryString["id"]);
|
_id = Int32.Parse(PageState.QueryString["id"]);
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
|
|
||||||
@namespace [Owner].[Module]s.Modules
|
@namespace [Owner].[Module]s.Modules
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@inject I[Module]Service [Module]Service
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject HttpClient http
|
|
||||||
@inject SiteState sitestate
|
|
||||||
|
|
||||||
@if (_[Module]s == null)
|
@if (_[Module]s == null)
|
||||||
{
|
{
|
||||||
|
@ -71,14 +70,12 @@ else
|
||||||
<!-- The content above is for informational purposes only and can be safely removed -->
|
<!-- The content above is for informational purposes only and can be safely removed -->
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
I[Module]Service [Module]Service;
|
|
||||||
List<[Module]> _[Module]s;
|
List<[Module]> _[Module]s;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
[Module]Service = new [Module]Service(http, sitestate);
|
|
||||||
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
|
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
@ -10,7 +10,6 @@ namespace [Owner].[Module]s.Modules
|
||||||
Name = "[Module]",
|
Name = "[Module]",
|
||||||
Description = "[Module]",
|
Description = "[Module]",
|
||||||
Version = "1.0.0",
|
Version = "1.0.0",
|
||||||
Dependencies = "[Owner].[Module]s.Shared.Oqtane",
|
|
||||||
ServerManagerType = "[ServerManagerType]",
|
ServerManagerType = "[ServerManagerType]",
|
||||||
ReleaseVersions = "1.0.0"
|
ReleaseVersions = "1.0.0"
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,9 +4,8 @@
|
||||||
|
|
||||||
@namespace [Owner].[Module]s.Modules
|
@namespace [Owner].[Module]s.Modules
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@inject I[Module]Service [Module]Service
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject HttpClient http
|
|
||||||
@inject SiteState sitestate
|
|
||||||
|
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -31,7 +30,6 @@
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
public override string Actions => "Add,Edit";
|
public override string Actions => "Add,Edit";
|
||||||
|
|
||||||
I[Module]Service [Module]Service;
|
|
||||||
int _id;
|
int _id;
|
||||||
string _name;
|
string _name;
|
||||||
string _createdby;
|
string _createdby;
|
||||||
|
@ -43,7 +41,6 @@
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
[Module]Service = new [Module]Service(http, sitestate);
|
|
||||||
if (PageState.Action == "Edit")
|
if (PageState.Action == "Edit")
|
||||||
{
|
{
|
||||||
_id = Int32.Parse(PageState.QueryString["id"]);
|
_id = Int32.Parse(PageState.QueryString["id"]);
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
|
|
||||||
@namespace [Owner].[Module]s.Modules
|
@namespace [Owner].[Module]s.Modules
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@inject I[Module]Service [Module]Service
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject HttpClient http
|
|
||||||
@inject SiteState sitestate
|
|
||||||
|
|
||||||
@if (_[Module]s == null)
|
@if (_[Module]s == null)
|
||||||
{
|
{
|
||||||
|
@ -62,14 +61,12 @@ else
|
||||||
<!-- The content above is for informational purposes only and can be safely removed -->
|
<!-- The content above is for informational purposes only and can be safely removed -->
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
I[Module]Service [Module]Service;
|
|
||||||
List<[Module]> _[Module]s;
|
List<[Module]> _[Module]s;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
[Module]Service = new [Module]Service(http, sitestate);
|
|
||||||
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
|
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
@ -10,7 +10,6 @@ namespace [Owner].[Module]s.Modules
|
||||||
Name = "[Module]",
|
Name = "[Module]",
|
||||||
Description = "[Module]",
|
Description = "[Module]",
|
||||||
Version = "1.0.0",
|
Version = "1.0.0",
|
||||||
Dependencies = "[Owner].[Module]s.Module.Shared",
|
|
||||||
ServerManagerType = "[ServerManagerType]",
|
ServerManagerType = "[ServerManagerType]",
|
||||||
ReleaseVersions = "1.0.0"
|
ReleaseVersions = "1.0.0"
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
@using Oqtane.Modules.Controls
|
@using Oqtane.Modules.Controls
|
||||||
@namespace Oqtane.Modules.HtmlText
|
@namespace Oqtane.Modules.HtmlText
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@inject IHtmlTextService HtmlTextService
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject HttpClient http
|
|
||||||
@inject SiteState sitestate
|
|
||||||
|
|
||||||
@if (_content != null)
|
@if (_content != null)
|
||||||
{
|
{
|
||||||
|
@ -14,7 +13,8 @@
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
@if (!string.IsNullOrEmpty(_content))
|
@if (!string.IsNullOrEmpty(_content))
|
||||||
{
|
{
|
||||||
<br /><br />
|
<br />
|
||||||
|
<br />
|
||||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,7 @@
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var htmltextservice = new HtmlTextService(http, sitestate);
|
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||||
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
|
||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
_content = htmltext.Content;
|
_content = htmltext.Content;
|
||||||
|
@ -65,19 +64,18 @@
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var htmltextservice = new HtmlTextService(http, sitestate);
|
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||||
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
|
||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
htmltext.Content = content;
|
htmltext.Content = content;
|
||||||
await htmltextservice.UpdateHtmlTextAsync(htmltext);
|
await HtmlTextService.UpdateHtmlTextAsync(htmltext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
htmltext = new HtmlTextInfo();
|
htmltext = new HtmlTextInfo();
|
||||||
htmltext.ModuleId = ModuleState.ModuleId;
|
htmltext.ModuleId = ModuleState.ModuleId;
|
||||||
htmltext.Content = content;
|
htmltext.Content = content;
|
||||||
await htmltextservice.AddHtmlTextAsync(htmltext);
|
await HtmlTextService.AddHtmlTextAsync(htmltext);
|
||||||
}
|
}
|
||||||
|
|
||||||
await logger.LogInformation("Html/Text Content Saved {HtmlText}", htmltext);
|
await logger.LogInformation("Html/Text Content Saved {HtmlText}", htmltext);
|
||||||
|
|
|
@ -1,21 +1,13 @@
|
||||||
@using Oqtane.Modules.HtmlText.Services
|
@using Oqtane.Modules.HtmlText.Services
|
||||||
@using Oqtane.Modules.HtmlText.Models
|
|
||||||
@namespace Oqtane.Modules.HtmlText
|
@namespace Oqtane.Modules.HtmlText
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject IHtmlTextService HtmlTextService
|
||||||
@inject HttpClient http
|
|
||||||
@inject SiteState sitestate
|
|
||||||
|
|
||||||
@((MarkupString)content)
|
@((MarkupString)content)
|
||||||
|
|
||||||
@if (PageState.EditMode)
|
@if (PageState.EditMode)
|
||||||
{
|
{
|
||||||
<br />
|
<br /><ActionLink Action="Edit" /><br /><br />
|
||||||
}
|
|
||||||
<ActionLink Action="Edit" />
|
|
||||||
@if (PageState.EditMode)
|
|
||||||
{
|
|
||||||
<br /><br />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
@ -25,8 +17,7 @@
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var htmltextservice = new HtmlTextService(http, sitestate);
|
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||||
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
|
||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
content = htmltext.Content;
|
content = htmltext.Content;
|
||||||
|
|
|
@ -8,7 +8,7 @@ using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Modules.HtmlText.Services
|
namespace Oqtane.Modules.HtmlText.Services
|
||||||
{
|
{
|
||||||
public class HtmlTextService : ServiceBase, IHtmlTextService
|
public class HtmlTextService : ServiceBase, IHtmlTextService, IService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ using Oqtane.UI;
|
||||||
|
|
||||||
namespace Oqtane.Modules
|
namespace Oqtane.Modules
|
||||||
{
|
{
|
||||||
public class ModuleBase : ComponentBase, IModuleControl
|
public abstract class ModuleBase : ComponentBase, IModuleControl
|
||||||
{
|
{
|
||||||
private Logger _logger;
|
private Logger _logger;
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@ using System.Threading.Tasks;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.Providers;
|
using Oqtane.Providers;
|
||||||
|
@ -19,10 +21,9 @@ namespace Oqtane.Client
|
||||||
{
|
{
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||||
builder.RootComponents.Add<App>("app");
|
builder.RootComponents.Add<App>("app");
|
||||||
|
HttpClient httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)};
|
||||||
|
|
||||||
builder.Services.AddSingleton(
|
builder.Services.AddSingleton(httpClient);
|
||||||
new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }
|
|
||||||
);
|
|
||||||
builder.Services.AddOptions();
|
builder.Services.AddOptions();
|
||||||
|
|
||||||
// register auth services
|
// register auth services
|
||||||
|
@ -57,14 +58,16 @@ namespace Oqtane.Client
|
||||||
builder.Services.AddScoped<ISqlService, SqlService>();
|
builder.Services.AddScoped<ISqlService, SqlService>();
|
||||||
builder.Services.AddScoped<ISystemService, SystemService>();
|
builder.Services.AddScoped<ISystemService, SystemService>();
|
||||||
|
|
||||||
|
await LoadClientAssemblies(httpClient);
|
||||||
|
|
||||||
// dynamically register module contexts and repository services
|
// dynamically register module contexts and repository services
|
||||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||||
foreach (Assembly assembly in assemblies)
|
foreach (Assembly assembly in assemblies)
|
||||||
{
|
{
|
||||||
Type[] implementationtypes = assembly.GetTypes()
|
var implementationTypes = assembly.GetTypes()
|
||||||
.Where(item => item.GetInterfaces().Contains(typeof(IService)))
|
.Where(item => item.GetInterfaces().Contains(typeof(IService)));
|
||||||
.ToArray();
|
|
||||||
foreach (Type implementationtype in implementationtypes)
|
foreach (Type implementationtype in implementationTypes)
|
||||||
{
|
{
|
||||||
Type servicetype = Type.GetType(implementationtype.AssemblyQualifiedName.Replace(implementationtype.Name, "I" + implementationtype.Name));
|
Type servicetype = Type.GetType(implementationtype.AssemblyQualifiedName.Replace(implementationtype.Name, "I" + implementationtype.Name));
|
||||||
if (servicetype != null)
|
if (servicetype != null)
|
||||||
|
@ -76,9 +79,27 @@ namespace Oqtane.Client
|
||||||
builder.Services.AddScoped(implementationtype, implementationtype); // no interface defined for service
|
builder.Services.AddScoped(implementationtype, implementationtype); // no interface defined for service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assembly.GetInstances<IClientStartup>()
|
||||||
|
.ToList()
|
||||||
|
.ForEach(x => x.ConfigureServices(builder.Services));
|
||||||
}
|
}
|
||||||
|
|
||||||
await builder.Build().RunAsync();
|
await builder.Build().RunAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task LoadClientAssemblies(HttpClient http)
|
||||||
|
{
|
||||||
|
var list = await http.GetFromJsonAsync<List<string>>($"/~/api/ModuleDefinition/load");
|
||||||
|
// get list of loaded assemblies on the client ( in the client-side hosting module the browser client has its own app domain )
|
||||||
|
var assemblyList = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).ToList();
|
||||||
|
foreach (var name in list)
|
||||||
|
{
|
||||||
|
if (assemblyList.Contains(name)) continue;
|
||||||
|
// download assembly from server and load
|
||||||
|
var bytes = await http.GetByteArrayAsync($"/~/api/ModuleDefinition/load/{name}.dll");
|
||||||
|
Assembly.Load(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,21 @@ using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System;
|
using System;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class AliasService : ServiceBase, IAliasService
|
public class AliasService : ServiceBase, IAliasService
|
||||||
{
|
{
|
||||||
|
|
||||||
public AliasService(HttpClient http) :base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Alias");
|
public AliasService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "Alias");
|
||||||
|
|
||||||
public async Task<List<Alias>> GetAliasesAsync()
|
public async Task<List<Alias>> GetAliasesAsync()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,14 +3,20 @@ using System.Threading.Tasks;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class JobLogService : ServiceBase, IJobLogService
|
public class JobLogService : ServiceBase, IJobLogService
|
||||||
{
|
{
|
||||||
public JobLogService(HttpClient http) :base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("JobLog");
|
public JobLogService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "JobLog");
|
||||||
|
|
||||||
public async Task<List<JobLog>> GetJobLogsAsync()
|
public async Task<List<JobLog>> GetJobLogsAsync()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,14 +3,20 @@ using System.Threading.Tasks;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class JobService : ServiceBase, IJobService
|
public class JobService : ServiceBase, IJobService
|
||||||
{
|
{
|
||||||
public JobService(HttpClient http) : base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Job");
|
public JobService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "Job");
|
||||||
|
|
||||||
public async Task<List<Job>> GetJobsAsync()
|
public async Task<List<Job>> GetJobsAsync()
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,13 +135,13 @@ namespace Oqtane.Services
|
||||||
//TODO Missing content JSON validation
|
//TODO Missing content JSON validation
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an API Url which is tenant agnostic ( for use with entities in the MasterDB )
|
// create an API Url which is tenant agnostic ( for use during installation )
|
||||||
public string CreateApiUrl(string serviceName)
|
public string CreateApiUrl(string serviceName)
|
||||||
{
|
{
|
||||||
return CreateApiUrl(null, serviceName);
|
return CreateApiUrl(null, serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an API Url which is tenant aware ( for use with entities in the TenantDB )
|
// create an API Url which is tenant aware ( for use with repositories )
|
||||||
public string CreateApiUrl(Alias alias, string serviceName)
|
public string CreateApiUrl(Alias alias, string serviceName)
|
||||||
{
|
{
|
||||||
string apiurl = "/";
|
string apiurl = "/";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -6,9 +7,14 @@ namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class SqlService : ServiceBase, ISqlService
|
public class SqlService : ServiceBase, ISqlService
|
||||||
{
|
{
|
||||||
public SqlService(HttpClient http) : base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Sql");
|
public SqlService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "Sql");
|
||||||
|
|
||||||
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
|
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,14 +3,20 @@ using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class TenantService : ServiceBase, ITenantService
|
public class TenantService : ServiceBase, ITenantService
|
||||||
{
|
{
|
||||||
public TenantService(HttpClient http) : base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Tenant");
|
public TenantService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "Tenant");
|
||||||
|
|
||||||
public async Task<List<Tenant>> GetTenantsAsync()
|
public async Task<List<Tenant>> GetTenantsAsync()
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@ using System.Net;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
|
using Microsoft.AspNetCore.Routing.Constraints;
|
||||||
|
|
||||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||||
|
|
||||||
|
@ -194,7 +195,7 @@ namespace Oqtane.Controllers
|
||||||
CreateDirectory(folderPath);
|
CreateDirectory(folderPath);
|
||||||
string filename = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1);
|
string filename = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1);
|
||||||
// check for allowable file extensions
|
// check for allowable file extensions
|
||||||
if (Constants.UploadableFiles.Contains(Path.GetExtension(filename).Replace(".", "")))
|
if (Constants.UploadableFiles.Split(',').Contains(Path.GetExtension(filename).ToLower().Replace(".", "")))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -317,7 +318,7 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for allowable file extensions
|
// check for allowable file extensions
|
||||||
if (!Constants.UploadableFiles.Contains(Path.GetExtension(filename)?.Replace(".", "")))
|
if (!Constants.UploadableFiles.Split(',').Contains(Path.GetExtension(filename)?.ToLower().Replace(".", "")))
|
||||||
{
|
{
|
||||||
System.IO.File.Delete(Path.Combine(folder, filename + ".tmp"));
|
System.IO.File.Delete(Path.Combine(folder, filename + ".tmp"));
|
||||||
}
|
}
|
||||||
|
@ -396,12 +397,13 @@ namespace Oqtane.Controllers
|
||||||
[HttpGet("download/{id}")]
|
[HttpGet("download/{id}")]
|
||||||
public IActionResult Download(int id)
|
public IActionResult Download(int id)
|
||||||
{
|
{
|
||||||
|
string errorpath = Path.Combine(GetFolderPath("images"), "error.png");
|
||||||
Models.File file = _files.GetFile(id);
|
Models.File file = _files.GetFile(id);
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
if (_userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.Permissions))
|
if (_userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.Permissions))
|
||||||
{
|
{
|
||||||
string filepath = Path.Combine(GetFolderPath(file.Folder) , file.Name);
|
string filepath = Path.Combine(GetFolderPath(file.Folder), file.Name);
|
||||||
if (System.IO.File.Exists(filepath))
|
if (System.IO.File.Exists(filepath))
|
||||||
{
|
{
|
||||||
byte[] filebytes = System.IO.File.ReadAllBytes(filepath);
|
byte[] filebytes = System.IO.File.ReadAllBytes(filepath);
|
||||||
|
@ -411,21 +413,24 @@ namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath);
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath);
|
||||||
HttpContext.Response.StatusCode = 404;
|
HttpContext.Response.StatusCode = 404;
|
||||||
return null;
|
byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
|
||||||
|
return File(filebytes, "application/octet-stream", file.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access File {FileId}", id);
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access File {FileId}", id);
|
||||||
HttpContext.Response.StatusCode = 401;
|
HttpContext.Response.StatusCode = 401;
|
||||||
return null;
|
byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
|
||||||
|
return File(filebytes, "application/octet-stream", file.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Not Found {FileId}", id);
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Not Found {FileId}", id);
|
||||||
HttpContext.Response.StatusCode = 404;
|
HttpContext.Response.StatusCode = 404;
|
||||||
return null;
|
byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
|
||||||
|
return File(filebytes, "application/octet-stream", "error.png");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,7 +474,7 @@ namespace Oqtane.Controllers
|
||||||
file.ImageHeight = 0;
|
file.ImageHeight = 0;
|
||||||
file.ImageWidth = 0;
|
file.ImageWidth = 0;
|
||||||
|
|
||||||
if (Constants.ImageFiles.Contains(file.Extension))
|
if (Constants.ImageFiles.Split(',').Contains(file.Extension.ToLower()))
|
||||||
{
|
{
|
||||||
FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
|
FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
|
||||||
using (var image = Image.FromStream(stream))
|
using (var image = Image.FromStream(stream))
|
||||||
|
|
|
@ -10,7 +10,6 @@ using Oqtane.Extensions;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
|
@ -105,16 +104,26 @@ namespace Oqtane.Controllers
|
||||||
}.EncodePermissions();
|
}.EncodePermissions();
|
||||||
}
|
}
|
||||||
if (_userPermissions.IsAuthorized(User,PermissionNames.Edit, permissions))
|
if (_userPermissions.IsAuthorized(User,PermissionNames.Edit, permissions))
|
||||||
|
{
|
||||||
|
if (FolderPathValid(folder))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
|
if (string.IsNullOrEmpty(folder.Path) && 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 = _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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Name Not Valid {Folder}", folder);
|
||||||
|
HttpContext.Response.StatusCode = 401;
|
||||||
|
folder = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Create, "User Not Authorized To Add Folder {Folder}", folder);
|
_logger.Log(LogLevel.Error, this, LogFunction.Create, "User Not Authorized To Add Folder {Folder}", folder);
|
||||||
HttpContext.Response.StatusCode = 401;
|
HttpContext.Response.StatusCode = 401;
|
||||||
|
@ -130,16 +139,26 @@ namespace Oqtane.Controllers
|
||||||
public Folder Put(int id, [FromBody] Folder folder)
|
public Folder Put(int id, [FromBody] Folder folder)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Folder, folder.FolderId, PermissionNames.Edit))
|
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Folder, folder.FolderId, PermissionNames.Edit))
|
||||||
|
{
|
||||||
|
if (FolderPathValid(folder))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
|
if (string.IsNullOrEmpty(folder.Path) && 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 = _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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Name Not Valid {Folder}", folder);
|
||||||
|
HttpContext.Response.StatusCode = 401;
|
||||||
|
folder = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Update, "User Not Authorized To Update Folder {Folder}", folder);
|
_logger.Log(LogLevel.Error, this, LogFunction.Update, "User Not Authorized To Update Folder {Folder}", folder);
|
||||||
HttpContext.Response.StatusCode = 401;
|
HttpContext.Response.StatusCode = 401;
|
||||||
|
@ -191,5 +210,11 @@ namespace Oqtane.Controllers
|
||||||
HttpContext.Response.StatusCode = 401;
|
HttpContext.Response.StatusCode = 401;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool FolderPathValid(Folder folder)
|
||||||
|
{
|
||||||
|
// prevent folder path traversal and reserved devices
|
||||||
|
return (!folder.Name.Contains("\\") && !folder.Name.Contains("/") && !Constants.ReservedDevices.Split(',').Contains(folder.Name.ToUpper()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,6 +170,16 @@ namespace Oqtane.Controllers
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// GET api/<controller>/load/assembyname
|
||||||
|
[HttpGet("load")]
|
||||||
|
public List<string> Load()
|
||||||
|
{
|
||||||
|
var assemblies = AppDomain.CurrentDomain.GetOqtaneClientAssemblies();
|
||||||
|
var list = AppDomain.CurrentDomain.GetOqtaneClientAssemblies().Select(a => a.GetName().Name).ToList();
|
||||||
|
var deps = assemblies.SelectMany(a => a.GetReferencedAssemblies()).Distinct();
|
||||||
|
list.AddRange(deps.Where(a=>a.Name.EndsWith(".oqtane",StringComparison.OrdinalIgnoreCase)).Select(a=>a.Name));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
// POST api/<controller>?moduleid=x
|
// POST api/<controller>?moduleid=x
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
|
@ -17,6 +19,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// GET: api/<controller>
|
// GET: api/<controller>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
public IEnumerable<SiteTemplate> Get()
|
public IEnumerable<SiteTemplate> Get()
|
||||||
{
|
{
|
||||||
return _siteTemplates.GetSiteTemplates();
|
return _siteTemplates.GetSiteTemplates();
|
||||||
|
|
26
Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs
Normal file
26
Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Oqtane.Infrastructure;
|
||||||
|
|
||||||
|
namespace Oqtane.Extensions
|
||||||
|
{
|
||||||
|
public static class ApplicationBuilderExtensions
|
||||||
|
{
|
||||||
|
public static IApplicationBuilder ConfigureOqtaneAssemblies(this IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
|
{
|
||||||
|
var startUps = AppDomain.CurrentDomain
|
||||||
|
.GetOqtaneAssemblies()
|
||||||
|
.SelectMany(x => x.GetInstances<IServerStartup>());
|
||||||
|
|
||||||
|
foreach (var startup in startUps)
|
||||||
|
{
|
||||||
|
startup.Configure(app, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
|
using Oqtane.Infrastructure;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace Microsoft.Extensions.DependencyInjection
|
namespace Microsoft.Extensions.DependencyInjection
|
||||||
|
@ -30,6 +31,22 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mvcBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static IMvcBuilder ConfigureOqtaneMvc(this IMvcBuilder mvcBuilder)
|
||||||
|
{
|
||||||
|
var startUps = AppDomain.CurrentDomain
|
||||||
|
.GetOqtaneAssemblies()
|
||||||
|
.SelectMany(x => x.GetInstances<IServerStartup>());
|
||||||
|
|
||||||
|
foreach (var startup in startUps)
|
||||||
|
{
|
||||||
|
startup.ConfigureMvc(mvcBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
return mvcBuilder;
|
return mvcBuilder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,21 +8,23 @@ using Microsoft.Extensions.Hosting;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
using Oqtane.UI;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace Microsoft.Extensions.DependencyInjection
|
namespace Microsoft.Extensions.DependencyInjection
|
||||||
{
|
{
|
||||||
public static class OqtaneServiceCollectionExtensions
|
public static class OqtaneServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddOqtaneParts(this IServiceCollection services)
|
public static IServiceCollection AddOqtaneParts(this IServiceCollection services, Runtime runtime)
|
||||||
{
|
{
|
||||||
LoadAssemblies();
|
LoadAssemblies();
|
||||||
services.AddOqtaneServices();
|
services.AddOqtaneServices(runtime);
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IServiceCollection AddOqtaneServices(this IServiceCollection services)
|
private static IServiceCollection AddOqtaneServices(this IServiceCollection services, Runtime runtime)
|
||||||
{
|
{
|
||||||
if (services is null)
|
if (services is null)
|
||||||
{
|
{
|
||||||
|
@ -53,11 +55,24 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
services.AddSingleton(hostedServiceType, serviceType);
|
services.AddSingleton(hostedServiceType, serviceType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var startUps = assembly.GetInstances<IServerStartup>();
|
||||||
|
foreach (var startup in startUps)
|
||||||
|
{
|
||||||
|
startup.ConfigureServices(services);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (runtime == Runtime.Server)
|
||||||
|
{
|
||||||
|
assembly.GetInstances<IClientStartup>()
|
||||||
|
.ToList()
|
||||||
|
.ForEach(x => x.ConfigureServices(services));
|
||||||
|
}
|
||||||
|
}
|
||||||
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);
|
||||||
|
|
17
Oqtane.Server/Infrastructure/Interfaces/IServerStartup.cs
Normal file
17
Oqtane.Server/Infrastructure/Interfaces/IServerStartup.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Oqtane.Infrastructure
|
||||||
|
{
|
||||||
|
public interface IServerStartup
|
||||||
|
{
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||||
|
void ConfigureServices(IServiceCollection services);
|
||||||
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
void Configure(IApplicationBuilder app, IWebHostEnvironment env);
|
||||||
|
void ConfigureMvc(IMvcBuilder mvcBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,11 +14,13 @@ using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Oqtane.Extensions;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
using Oqtane.UI;
|
||||||
|
|
||||||
namespace Oqtane
|
namespace Oqtane
|
||||||
{
|
{
|
||||||
|
@ -26,6 +28,7 @@ namespace Oqtane
|
||||||
{
|
{
|
||||||
public IConfigurationRoot Configuration { get; }
|
public IConfigurationRoot Configuration { get; }
|
||||||
private string _webRoot;
|
private string _webRoot;
|
||||||
|
private Runtime _runtime;
|
||||||
|
|
||||||
public Startup(IWebHostEnvironment env)
|
public Startup(IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
|
@ -33,6 +36,9 @@ namespace Oqtane
|
||||||
.SetBasePath(env.ContentRootPath)
|
.SetBasePath(env.ContentRootPath)
|
||||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
|
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
|
||||||
Configuration = builder.Build();
|
Configuration = builder.Build();
|
||||||
|
|
||||||
|
_runtime = (Configuration.GetSection("Runtime").Value == "WebAssembly") ? Runtime.WebAssembly : Runtime.Server;
|
||||||
|
|
||||||
_webRoot = env.WebRootPath;
|
_webRoot = env.WebRootPath;
|
||||||
AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(env.ContentRootPath, "Data"));
|
AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(env.ContentRootPath, "Data"));
|
||||||
}
|
}
|
||||||
|
@ -187,14 +193,13 @@ namespace Oqtane
|
||||||
services.AddTransient<ISqlRepository, SqlRepository>();
|
services.AddTransient<ISqlRepository, SqlRepository>();
|
||||||
services.AddTransient<IUpgradeManager, UpgradeManager>();
|
services.AddTransient<IUpgradeManager, UpgradeManager>();
|
||||||
|
|
||||||
// load the external assemblies into the app domain
|
// load the external assemblies into the app domain, install services
|
||||||
services.AddOqtaneParts();
|
services.AddOqtaneParts(_runtime);
|
||||||
|
|
||||||
services.AddMvc()
|
services.AddMvc()
|
||||||
|
.AddNewtonsoftJson()
|
||||||
.AddOqtaneApplicationParts() // register any Controllers from custom modules
|
.AddOqtaneApplicationParts() // register any Controllers from custom modules
|
||||||
.AddNewtonsoftJson();
|
.ConfigureOqtaneMvc(); // any additional configuration from IStart classes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
services.AddSwaggerGen(c =>
|
services.AddSwaggerGen(c =>
|
||||||
{
|
{
|
||||||
|
@ -217,14 +222,12 @@ namespace Oqtane
|
||||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||||
app.UseHsts();
|
app.UseHsts();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
app.UseBlazorFrameworkFiles();
|
app.UseBlazorFrameworkFiles();
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
app.UseSwaggerUI(c =>
|
app.UseSwaggerUI(c =>
|
||||||
{
|
{
|
||||||
|
@ -237,6 +240,7 @@ namespace Oqtane
|
||||||
endpoints.MapControllers();
|
endpoints.MapControllers();
|
||||||
endpoints.MapFallbackToPage("/_Host");
|
endpoints.MapFallbackToPage("/_Host");
|
||||||
});
|
});
|
||||||
|
app.ConfigureOqtaneAssemblies(env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,12 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-logo {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.breadcrumbs {
|
.breadcrumbs {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 275px;
|
left: 275px;
|
||||||
|
@ -164,6 +170,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
|
.app-logo {
|
||||||
|
height: 80px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.breadcrumbs {
|
.breadcrumbs {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 150px;
|
top: 150px;
|
||||||
|
|
BIN
Oqtane.Server/wwwroot/images/error.png
Normal file
BIN
Oqtane.Server/wwwroot/images/error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -81,15 +81,27 @@ window.interop = {
|
||||||
if (link.href !== url) {
|
if (link.href !== url) {
|
||||||
link.setAttribute('href', url);
|
link.setAttribute('href', url);
|
||||||
}
|
}
|
||||||
if (type !== "" && link.type !== type) {
|
if (type !== "") {
|
||||||
|
if (link.type !== type) {
|
||||||
link.setAttribute('type', type);
|
link.setAttribute('type', type);
|
||||||
}
|
}
|
||||||
if (integrity !== "" && link.integrity !== integrity) {
|
} else {
|
||||||
|
link.removeAttribute('type');
|
||||||
|
}
|
||||||
|
if (integrity !== "") {
|
||||||
|
if (link.integrity !== integrity) {
|
||||||
link.setAttribute('integrity', integrity);
|
link.setAttribute('integrity', integrity);
|
||||||
}
|
}
|
||||||
if (crossorigin !== "" && link.crossOrigin !== crossorigin) {
|
} else {
|
||||||
|
link.removeAttribute('integrity');
|
||||||
|
}
|
||||||
|
if (crossorigin !== "") {
|
||||||
|
if (link.crossOrigin !== crossorigin) {
|
||||||
link.setAttribute('crossorigin', crossorigin);
|
link.setAttribute('crossorigin', crossorigin);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
link.removeAttribute('crossorigin');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
includeScript: function (id, src, content, location, integrity, crossorigin) {
|
includeScript: function (id, src, content, location, integrity, crossorigin) {
|
||||||
|
@ -126,12 +138,20 @@ window.interop = {
|
||||||
if (script.src !== src) {
|
if (script.src !== src) {
|
||||||
script.src = src;
|
script.src = src;
|
||||||
}
|
}
|
||||||
if (integrity !== "" && script.integrity !== integrity) {
|
if (integrity !== "") {
|
||||||
|
if (script.integrity !== integrity) {
|
||||||
script.setAttribute('integrity', integrity);
|
script.setAttribute('integrity', integrity);
|
||||||
}
|
}
|
||||||
if (crossorigin !== "" && script.crossorigin !== crossorigin) {
|
} else {
|
||||||
|
script.removeAttribute('integrity');
|
||||||
|
}
|
||||||
|
if (crossorigin !== "") {
|
||||||
|
if (script.crossOrigin !== crossorigin) {
|
||||||
script.setAttribute('crossorigin', crossorigin);
|
script.setAttribute('crossorigin', crossorigin);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
script.removeAttribute('crossorigin');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (script.innerHTML !== content) {
|
if (script.innerHTML !== content) {
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Oqtane.Modules;
|
||||||
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
using Oqtane.Themes;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace System.Reflection
|
namespace System.Reflection
|
||||||
|
@ -31,7 +34,29 @@ namespace System.Reflection
|
||||||
}
|
}
|
||||||
|
|
||||||
return assembly.GetTypes()
|
return assembly.GetTypes()
|
||||||
.Where(t => t.GetInterfaces().Contains(interfaceType));
|
//.Where(t => t.GetInterfaces().Contains(interfaceType));
|
||||||
|
.Where(x => interfaceType.IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Type> GetTypes<T>(this Assembly assembly)
|
||||||
|
{
|
||||||
|
return assembly.GetTypes(typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> GetInstances<T>(this Assembly assembly) where T : class
|
||||||
|
{
|
||||||
|
if (assembly is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(assembly));
|
||||||
|
}
|
||||||
|
var type = typeof(T);
|
||||||
|
var list = assembly.GetTypes()
|
||||||
|
.Where(x => type.IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract && !x.IsGenericType);
|
||||||
|
|
||||||
|
foreach (var type1 in list)
|
||||||
|
{
|
||||||
|
if (Activator.CreateInstance(type1) is T instance) yield return instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsOqtaneAssembly(this Assembly assembly)
|
public static bool IsOqtaneAssembly(this Assembly assembly)
|
||||||
|
@ -48,5 +73,10 @@ namespace System.Reflection
|
||||||
{
|
{
|
||||||
return appDomain.GetAssemblies().Where(a => a.IsOqtaneAssembly());
|
return appDomain.GetAssemblies().Where(a => a.IsOqtaneAssembly());
|
||||||
}
|
}
|
||||||
|
public static IEnumerable<Assembly> GetOqtaneClientAssemblies(this AppDomain appDomain)
|
||||||
|
{
|
||||||
|
return appDomain.GetOqtaneAssemblies()
|
||||||
|
.Where(a => a.GetTypes<IModuleControl>().Any() || a.GetTypes<IThemeControl>().Any() || a.GetTypes<IClientStartup>().Any());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
11
Oqtane.Shared/Interfaces/IClientStartup.cs
Normal file
11
Oqtane.Shared/Interfaces/IClientStartup.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
public interface IClientStartup
|
||||||
|
{
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
void ConfigureServices(IServiceCollection services);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,6 @@ namespace Oqtane.Modules
|
||||||
SecurityAccessLevel SecurityAccessLevel { get; } // defines the security access level for this control - defaults to View
|
SecurityAccessLevel SecurityAccessLevel { get; } // defines the security access level for this control - defaults to View
|
||||||
string Title { get; } // title to display for this control - defaults to module title
|
string Title { get; } // title to display for this control - defaults to module title
|
||||||
string Actions { get; } // allows for routing by configuration rather than by convention ( comma delimited ) - defaults to using component file name
|
string Actions { get; } // allows for routing by configuration rather than by convention ( comma delimited ) - defaults to using component file name
|
||||||
bool UseAdminContainer { get; } // container for embedding module control - defaults to true
|
bool UseAdminContainer { get; } // container for embedding module control - defaults to true. false will suppress the default modal UI popup behavior and render the component in the page.
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,6 +18,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.2" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
||||||
<PackageReference Include="System.Text.Json" Version="4.7.1" />
|
<PackageReference Include="System.Text.Json" Version="4.7.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -43,5 +43,6 @@
|
||||||
|
|
||||||
public const string ImageFiles = "jpg,jpeg,jpe,gif,bmp,png";
|
public const string ImageFiles = "jpg,jpeg,jpe,gif,bmp,png";
|
||||||
public const string UploadableFiles = "jpg,jpeg,jpe,gif,bmp,png,mov,wmv,avi,mp4,mp3,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,nupkg";
|
public const string UploadableFiles = "jpg,jpeg,jpe,gif,bmp,png,mov,wmv,avi,mp4,mp3,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,nupkg";
|
||||||
|
public const string ReservedDevices = "CON,NUL,PRN,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8,COM9,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user