Merge pull request #17 from oqtane/master

sync with upstream
This commit is contained in:
Shaun Walker 2020-05-07 15:28:39 -04:00 committed by GitHub
commit d53bdc5bb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 255 additions and 11022 deletions

View File

@ -13,7 +13,7 @@
<Label For="dateTime" HelpText="The date and time of this log">Date/Time: </Label> <Label For="dateTime" HelpText="The date and time of this log">Date/Time: </Label>
</td> </td>
<td> <td>
<input id="dateTime" class="form-control" @bind="@_logDate" disabled /> <input id="dateTime" class="form-control" @bind="@_logDate" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -21,7 +21,7 @@
<Label For="level" HelpText="The level of this log">Level: </Label> <Label For="level" HelpText="The level of this log">Level: </Label>
</td> </td>
<td> <td>
<input id="level" class="form-control" @bind="@_level" disabled /> <input id="level" class="form-control" @bind="@_level" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -29,7 +29,7 @@
<Label For="feature" HelpText="The feature that was affected">Feature: </Label> <Label For="feature" HelpText="The feature that was affected">Feature: </Label>
</td> </td>
<td> <td>
<input id="feature" class="form-control" @bind="@_feature" disabled /> <input id="feature" class="form-control" @bind="@_feature" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -37,7 +37,7 @@
<Label For="function" HelpText="The function that was performed">Function: </Label> <Label For="function" HelpText="The function that was performed">Function: </Label>
</td> </td>
<td> <td>
<input id="function" class="form-control" @bind="@_function" disabled /> <input id="function" class="form-control" @bind="@_function" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -45,7 +45,7 @@
<Label For="category" HelpText="The categories that were affected">Category: </Label> <Label For="category" HelpText="The categories that were affected">Category: </Label>
</td> </td>
<td> <td>
<input id="category" class="form-control" @bind="@_category" disabled /> <input id="category" class="form-control" @bind="@_category" readonly />
</td> </td>
</tr> </tr>
@if (_pageName != string.Empty) @if (_pageName != string.Empty)
@ -55,7 +55,7 @@
<Label For="page" HelpText="The page that was affected">Page: </Label> <Label For="page" HelpText="The page that was affected">Page: </Label>
</td> </td>
<td> <td>
<input id="page" class="form-control" @bind="@_pageName" disabled /> <input id="page" class="form-control" @bind="@_pageName" readonly />
</td> </td>
</tr> </tr>
} }
@ -66,7 +66,7 @@
<Label For="module" HelpText="The module that was affected">Module: </Label> <Label For="module" HelpText="The module that was affected">Module: </Label>
</td> </td>
<td> <td>
<input id="module" class="form-control" @bind="@_moduleTitle" disabled /> <input id="module" class="form-control" @bind="@_moduleTitle" readonly />
</td> </td>
</tr> </tr>
} }
@ -77,7 +77,7 @@
<Label For="user" HelpText="The user that caused this log">User: </Label> <Label For="user" HelpText="The user that caused this log">User: </Label>
</td> </td>
<td> <td>
<input id="user" class="form-control" @bind="@_username" disabled /> <input id="user" class="form-control" @bind="@_username" readonly />
</td> </td>
</tr> </tr>
} }
@ -86,7 +86,7 @@
<Label For="url" HelpText="The url the log comes from">Url: </Label> <Label For="url" HelpText="The url the log comes from">Url: </Label>
</td> </td>
<td> <td>
<input id="url" class="form-control" @bind="@_url" disabled /> <input id="url" class="form-control" @bind="@_url" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -94,7 +94,7 @@
<Label For="template" HelpText="What the log is about">Template: </Label> <Label For="template" HelpText="What the log is about">Template: </Label>
</td> </td>
<td> <td>
<input id="template" class="form-control" @bind="@_template" disabled /> <input id="template" class="form-control" @bind="@_template" readonly />
</td> </td>
</tr> </tr>
<tr> <tr>
@ -102,7 +102,7 @@
<Label For="message" HelpText="The message that the system generated"class="control-label">Message: </Label> <Label For="message" HelpText="The message that the system generated"class="control-label">Message: </Label>
</td> </td>
<td> <td>
<textarea id="message" class="form-control" @bind="@_message" rows="5" disabled></textarea> <textarea id="message" class="form-control" @bind="@_message" rows="5" readonly></textarea>
</td> </td>
</tr> </tr>
@if (!string.IsNullOrEmpty(_exception)) @if (!string.IsNullOrEmpty(_exception))
@ -112,7 +112,7 @@
<Label For="exception" HelpText="The exceptions generated by the system">Exception: </Label> <Label For="exception" HelpText="The exceptions generated by the system">Exception: </Label>
</td> </td>
<td> <td>
<textarea id="exception" class="form-control" @bind="@_exception" rows="5" disabled></textarea> <textarea id="exception" class="form-control" @bind="@_exception" rows="5" readonly></textarea>
</td> </td>
</tr> </tr>
} }
@ -121,7 +121,7 @@
<Label For="properties" HelpText="The properties that were affected">Properties: </Label> <Label For="properties" HelpText="The properties that were affected">Properties: </Label>
</td> </td>
<td> <td>
<textarea id="properties" class="form-control" @bind="@_properties" rows="5" disabled></textarea> <textarea id="properties" class="form-control" @bind="@_properties" rows="5" readonly></textarea>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -129,7 +129,7 @@
<Label For="server" HelpText="The server that was affected">Server: </Label> <Label For="server" HelpText="The server that was affected">Server: </Label>
</td> </td>
<td> <td>
<input id="server" class="form-control" @bind="@_server" disabled /> <input id="server" class="form-control" @bind="@_server" readonly />
</td> </td>
</tr> </tr>
</table> </table>

View File

@ -1,6 +1,6 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleBase
@attribute [OqtaneIgnore]
@if (_visible) @if (_visible)
{ {
<div class="app-admin-modal"> <div class="app-admin-modal">

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleBase
@attribute [OqtaneIgnore]
@inject IUserService UserService @inject IUserService UserService
@if (_authorized) @if (_authorized)

View File

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

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleBase
@attribute [OqtaneIgnore]
@inject IFolderService FolderService @inject IFolderService FolderService
@inject IFileService FileService @inject IFileService FileService
@inject IJSRuntime JsRuntime @inject IJSRuntime JsRuntime

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@inherits ModuleBase @inherits ModuleBase
@attribute [OqtaneIgnore]
@inject IJSRuntime JsRuntime @inject IJSRuntime JsRuntime
@if (_filemanagervisible) @if (_filemanagervisible)

View File

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

View File

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

View File

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

View File

@ -82,7 +82,6 @@ namespace Oqtane.Services
var result = await response.Content.ReadFromJsonAsync<TResult>(); var result = await response.Content.ReadFromJsonAsync<TResult>();
return result; return result;
} }
return default; return default;
} }
@ -121,6 +120,8 @@ namespace Oqtane.Services
if (response.StatusCode != HttpStatusCode.NoContent && response.StatusCode != HttpStatusCode.NotFound) if (response.StatusCode != HttpStatusCode.NoContent && response.StatusCode != HttpStatusCode.NotFound)
{ {
//TODO: Log errors here //TODO: Log errors here
Console.WriteLine($"Request: {response.RequestMessage.RequestUri}");
Console.WriteLine($"Response status: {response.StatusCode} {response.ReasonPhrase}"); Console.WriteLine($"Response status: {response.StatusCode} {response.ReasonPhrase}");
} }

View File

@ -1,5 +1,6 @@
@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,7 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@using Oqtane.Enums @using Oqtane.Enums
@inherits ThemeControlBase @inherits ThemeControlBase
@attribute [OqtaneIgnore]
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@inject IUserService UserService @inject IUserService UserService
@inject IModuleDefinitionService ModuleDefinitionService @inject IModuleDefinitionService ModuleDefinitionService

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits LoginBase @inherits LoginBase
@attribute [OqtaneIgnore]
<AuthorizeView> <AuthorizeView>
<Authorizing> <Authorizing>

View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits ModuleActionsBase @inherits ModuleActionsBase
@attribute [OqtaneIgnore]
@if (PageState.EditMode && !PageState.Page.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions)) @if (PageState.EditMode && !PageState.Page.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions))
{ {

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits ContainerBase @inherits ContainerBase
@attribute [OqtaneIgnore]
@((MarkupString)title) @((MarkupString)title)

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Themes.Controls @namespace Oqtane.Themes.Controls
@inherits ThemeControlBase @inherits ThemeControlBase
@attribute [OqtaneIgnore]
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
<AuthorizeView> <AuthorizeView>

View File

@ -18,6 +18,9 @@
protected override async Task OnParametersSetAsync() protected override async Task OnParametersSetAsync()
{ {
// go to https://www.bootstrapcdn.com/bootswatch/ and take your favorite theme
//<link href="https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css" rel="stylesheet" integrity="sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM" crossorigin="anonymous">
await LoadBootstrapTheme("https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css","sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM");
await IncludeCSS("Theme.css"); await IncludeCSS("Theme.css");
} }
} }

View File

@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop; using Microsoft.JSInterop;
using Oqtane.Shared; using Oqtane.Shared;
using Oqtane.UI; using Oqtane.UI;
@ -30,6 +30,13 @@ namespace Oqtane.Themes
await interop.IncludeCSS("Theme", Url); await interop.IncludeCSS("Theme", Url);
} }
public async Task LoadBootstrapTheme(string url, string integrity = null)
{
var interop = new Interop(JSRuntime);
string crossorigin = string.IsNullOrEmpty(integrity) ? string.Empty : "anonymous";
await interop.IncludeLink("bootstrap", "stylesheet", url, "text/css", integrity, crossorigin);
}
public string NavigateUrl() public string NavigateUrl()
{ {
return NavigateUrl(PageState.Page.Path); return NavigateUrl(PageState.Page.Path);

View File

@ -1,5 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using Oqtane.Shared;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace System.Reflection namespace System.Reflection
@ -31,5 +33,20 @@ namespace System.Reflection
return assembly.GetTypes() return assembly.GetTypes()
.Where(t => t.GetInterfaces().Contains(interfaceType)); .Where(t => t.GetInterfaces().Contains(interfaceType));
} }
public static bool IsOqtaneAssembly(this Assembly assembly)
{
return assembly.FullName != null && (assembly.FullName.Contains("oqtane.", StringComparison.OrdinalIgnoreCase));
}
public static bool IsOqtaneAssembly(this FileInfo fileInfo)
{
return (fileInfo.Name.Contains("oqtane.", StringComparison.OrdinalIgnoreCase));
}
public static IEnumerable<Assembly> GetOqtaneAssemblies(this AppDomain appDomain)
{
return appDomain.GetAssemblies().Where(a => a.IsOqtaneAssembly());
}
} }
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.ApplicationParts;
@ -16,10 +17,11 @@ namespace Microsoft.Extensions.DependencyInjection
} }
// load MVC application parts from module assemblies // load MVC application parts from module assemblies
foreach (var assembly in OqtaneServiceCollectionExtensions.GetOqtaneModuleAssemblies()) var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
foreach (var assembly in assemblies)
{ {
// check if assembly contains MVC Controllers // check if assembly contains MVC Controllers
if (assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Controller))).ToArray().Length > 0) if (assembly.GetTypes().Any(t => t.IsSubclassOf(typeof(Controller))))
{ {
var partFactory = ApplicationPartFactory.GetApplicationPartFactory(assembly); var partFactory = ApplicationPartFactory.GetApplicationPartFactory(assembly);
foreach (var part in partFactory.GetApplicationParts(assembly)) foreach (var part in partFactory.GetApplicationParts(assembly))

View File

@ -5,67 +5,35 @@ 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.Shared;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection namespace Microsoft.Extensions.DependencyInjection
{ {
public static class OqtaneServiceCollectionExtensions public static class OqtaneServiceCollectionExtensions
{ {
private static readonly IList<Assembly> OqtaneModuleAssemblies = new List<Assembly>(); public static IServiceCollection AddOqtaneParts(this IServiceCollection services)
private static Assembly[] Assemblies => AppDomain.CurrentDomain.GetAssemblies();
internal static IEnumerable<Assembly> GetOqtaneModuleAssemblies() => OqtaneModuleAssemblies;
public static IServiceCollection AddOqtaneModules(this IServiceCollection services)
{ {
if (services is null) LoadAssemblies();
{ services.AddOqtaneServices();
throw new ArgumentNullException(nameof(services));
}
LoadAssemblies("Module");
return services; return services;
} }
public static IServiceCollection AddOqtaneThemes(this IServiceCollection services) private static IServiceCollection AddOqtaneServices(this IServiceCollection services)
{ {
if (services is null) if (services is null)
{ {
throw new ArgumentNullException(nameof(services)); throw new ArgumentNullException(nameof(services));
} }
LoadAssemblies("Theme"); var hostedServiceType = typeof(IHostedService);
var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
return services;
}
public static IServiceCollection AddOqtaneSiteTemplates(this IServiceCollection services)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
LoadAssemblies("SiteTemplate");
return services;
}
public static IServiceCollection AddOqtaneServices(this IServiceCollection services)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
// dynamically register module services, contexts, and repository classes
var assemblies = Assemblies.Where(item => item.FullName != null && (item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Module."))).ToArray();
foreach (var assembly in assemblies) foreach (var assembly in assemblies)
{ {
// dynamically register module services, contexts, and repository classes
var implementationTypes = assembly.GetInterfaces<IService>(); var implementationTypes = assembly.GetInterfaces<IService>();
foreach (var implementationType in implementationTypes) foreach (var implementationType in implementationTypes)
{ {
@ -75,22 +43,8 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddScoped(serviceType ?? implementationType, implementationType); services.AddScoped(serviceType ?? implementationType, implementationType);
} }
} }
}
return services;
}
public static IServiceCollection AddOqtaneHostedServices(this IServiceCollection services)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
// dynamically register hosted services // dynamically register hosted services
var hostedServiceType = typeof(IHostedService);
foreach (var assembly in Assemblies)
{
var serviceTypes = assembly.GetTypes(hostedServiceType); var serviceTypes = assembly.GetTypes(hostedServiceType);
foreach (var serviceType in serviceTypes) foreach (var serviceType in serviceTypes)
{ {
@ -104,22 +58,37 @@ namespace Microsoft.Extensions.DependencyInjection
return services; return services;
} }
private static void LoadAssemblies(string pattern) 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); var assembliesFolder = new DirectoryInfo(assemblyPath);
// 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($"*.{pattern}.*.dll")) foreach (var dll in assembliesFolder.EnumerateFiles($"*.dll", SearchOption.TopDirectoryOnly).Where(f => f.IsOqtaneAssembly()))
{ {
// check if assembly is already loaded AssemblyName assemblyName;
var assembly = Assemblies.FirstOrDefault(a =>!a.IsDynamic && a.Location == dll.FullName); try
if (assembly == null)
{ {
assemblyName = AssemblyName.GetAssemblyName(dll.FullName);
}
catch
{
Console.WriteLine($"Not Assembly : {dll.Name}");
continue;
}
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
if (!assemblies.Any(a => AssemblyName.ReferenceMatchesDefinition(assemblyName, a.GetName())))
{
try
{
var pdb = Path.ChangeExtension(dll.FullName, ".pdb");
Assembly assembly = null;
// load assembly ( and symbols ) from stream to prevent locking files ( as long as dependencies are in /bin they will load as well ) // load assembly ( and symbols ) from stream to prevent locking files ( as long as dependencies are in /bin they will load as well )
string pdb = dll.FullName.Replace(".dll", ".pdb");
if (File.Exists(pdb)) if (File.Exists(pdb))
{ {
assembly = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(File.ReadAllBytes(dll.FullName)), new MemoryStream(File.ReadAllBytes(pdb))); assembly = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(File.ReadAllBytes(dll.FullName)), new MemoryStream(File.ReadAllBytes(pdb)));
@ -128,10 +97,11 @@ namespace Microsoft.Extensions.DependencyInjection
{ {
assembly = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(File.ReadAllBytes(dll.FullName))); assembly = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(File.ReadAllBytes(dll.FullName)));
} }
if (pattern == "Module") Console.WriteLine($"Loaded : {assemblyName}");
}
catch (Exception e)
{ {
// build a list of module assemblies Console.WriteLine($"Failed : {assemblyName}\n{e}");
OqtaneModuleAssemblies.Add(assembly);
} }
} }
} }

View File

@ -0,0 +1,17 @@
using System.Collections.Generic;
using System.Linq;
namespace Oqtane.Extensions
{
public static class StringExtensions
{
public static bool StartWithAnyOf(this string s, IEnumerable<string> list)
{
if (s == null)
{
return false;
}
return list.Any(f => s.StartsWith(f));
}
}
}

View File

@ -75,6 +75,7 @@ namespace Oqtane.Repository
// get module assemblies // get module assemblies
_moduleDefinitions = LoadModuleDefinitionsFromAssemblies(); _moduleDefinitions = LoadModuleDefinitionsFromAssemblies();
} }
List<ModuleDefinition> moduleDefinitions = _moduleDefinitions; List<ModuleDefinition> moduleDefinitions = _moduleDefinitions;
List<Permission> permissions = new List<Permission>(); List<Permission> permissions = new List<Permission>();
@ -94,7 +95,7 @@ namespace Oqtane.Repository
if (moduledef == null) if (moduledef == null)
{ {
// new module definition // new module definition
moduledef = new ModuleDefinition { ModuleDefinitionName = moduledefinition.ModuleDefinitionName }; moduledef = new ModuleDefinition {ModuleDefinitionName = moduledefinition.ModuleDefinitionName};
_db.ModuleDefinition.Add(moduledef); _db.ModuleDefinition.Add(moduledef);
_db.SaveChanges(); _db.SaveChanges();
if (siteId != -1) if (siteId != -1)
@ -109,18 +110,22 @@ namespace Oqtane.Repository
{ {
moduledefinition.Name = moduledef.Name; moduledefinition.Name = moduledef.Name;
} }
if (!string.IsNullOrEmpty(moduledef.Description)) if (!string.IsNullOrEmpty(moduledef.Description))
{ {
moduledefinition.Description = moduledef.Description; moduledefinition.Description = moduledef.Description;
} }
if (!string.IsNullOrEmpty(moduledef.Categories)) if (!string.IsNullOrEmpty(moduledef.Categories))
{ {
moduledefinition.Categories = moduledef.Categories; moduledefinition.Categories = moduledef.Categories;
} }
if (!string.IsNullOrEmpty(moduledef.Version)) if (!string.IsNullOrEmpty(moduledef.Version))
{ {
moduledefinition.Version = moduledef.Version; moduledefinition.Version = moduledef.Version;
} }
if (siteId != -1) if (siteId != -1)
{ {
if (permissions.Count == 0) if (permissions.Count == 0)
@ -139,9 +144,11 @@ namespace Oqtane.Repository
} }
} }
} }
// remove module definition from list as it is already synced // remove module definition from list as it is already synced
moduledefs.Remove(moduledef); moduledefs.Remove(moduledef);
} }
moduledefinition.ModuleDefinitionId = moduledef.ModuleDefinitionId; moduledefinition.ModuleDefinitionId = moduledef.ModuleDefinitionId;
moduledefinition.SiteId = siteId; moduledefinition.SiteId = siteId;
moduledefinition.CreatedBy = moduledef.CreatedBy; moduledefinition.CreatedBy = moduledef.CreatedBy;
@ -157,6 +164,7 @@ namespace Oqtane.Repository
{ {
_permissions.DeletePermissions(siteId, EntityNames.ModuleDefinition, moduledefinition.ModuleDefinitionId); _permissions.DeletePermissions(siteId, EntityNames.ModuleDefinition, moduledefinition.ModuleDefinitionId);
} }
_db.ModuleDefinition.Remove(moduledefinition); // delete _db.ModuleDefinition.Remove(moduledefinition); // delete
_db.SaveChanges(); _db.SaveChanges();
} }
@ -168,12 +176,12 @@ namespace Oqtane.Repository
{ {
List<ModuleDefinition> moduleDefinitions = new List<ModuleDefinition>(); List<ModuleDefinition> moduleDefinitions = new List<ModuleDefinition>();
// iterate through Oqtane module assemblies // iterate through Oqtane module assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies() var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
.Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Module.")).ToArray();
foreach (Assembly assembly in assemblies) foreach (Assembly assembly in assemblies)
{ {
moduleDefinitions = LoadModuleDefinitionsFromAssembly(moduleDefinitions, assembly); moduleDefinitions = LoadModuleDefinitionsFromAssembly(moduleDefinitions, assembly);
} }
return moduleDefinitions; return moduleDefinitions;
} }
@ -183,8 +191,12 @@ namespace Oqtane.Repository
Type[] modulecontroltypes = assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IModuleControl))).ToArray(); Type[] modulecontroltypes = assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IModuleControl))).ToArray();
foreach (Type modulecontroltype in modulecontroltypes) foreach (Type modulecontroltype in modulecontroltypes)
{ {
if (modulecontroltype.Name != "ModuleBase" && !modulecontroltype.Namespace.EndsWith(".Controls")) // Check if type should be ignored
{ if (modulecontroltype.Name == "ModuleBase"
|| modulecontroltype.IsGenericType
|| Attribute.IsDefined(modulecontroltype, typeof(OqtaneIgnoreAttribute))
) continue;
string[] typename = modulecontroltype.AssemblyQualifiedName?.Split(',').Select(item => item.Trim()).ToArray(); string[] typename = modulecontroltype.AssemblyQualifiedName?.Split(',').Select(item => item.Trim()).ToArray();
string[] segments = typename[0].Split('.'); string[] segments = typename[0].Split('.');
Array.Resize(ref segments, segments.Length - 1); Array.Resize(ref segments, segments.Length - 1);
@ -204,7 +216,7 @@ namespace Oqtane.Repository
{ {
// get property values from IModule // get property values from IModule
var moduleobject = Activator.CreateInstance(moduletype); var moduleobject = Activator.CreateInstance(moduletype);
moduledefinition = (ModuleDefinition)moduletype.GetProperty("ModuleDefinition").GetValue(moduleobject); moduledefinition = (ModuleDefinition) moduletype.GetProperty("ModuleDefinition").GetValue(moduleobject);
} }
else else
{ {
@ -216,6 +228,7 @@ namespace Oqtane.Repository
Categories = ((qualifiedModuleType.StartsWith("Oqtane.Modules.Admin.")) ? "Admin" : "") Categories = ((qualifiedModuleType.StartsWith("Oqtane.Modules.Admin.")) ? "Admin" : "")
}; };
} }
// set internal properties // set internal properties
moduledefinition.ModuleDefinitionName = qualifiedModuleType; moduledefinition.ModuleDefinitionName = qualifiedModuleType;
moduledefinition.Version = ""; // will be populated from database moduledefinition.Version = ""; // will be populated from database
@ -226,6 +239,7 @@ namespace Oqtane.Repository
{ {
moduledefinition.Categories = "Common"; moduledefinition.Categories = "Common";
} }
if (moduledefinition.Categories == "Admin") if (moduledefinition.Categories == "Admin")
{ {
moduledefinition.Permissions = new List<Permission> moduledefinition.Permissions = new List<Permission>
@ -241,13 +255,16 @@ namespace Oqtane.Repository
new Permission(PermissionNames.Utilize, Constants.RegisteredRole, true) new Permission(PermissionNames.Utilize, Constants.RegisteredRole, true)
}.EncodePermissions(); }.EncodePermissions();
} }
Console.WriteLine($"Registering module: {moduledefinition.ModuleDefinitionName}");
moduledefinitions.Add(moduledefinition); moduledefinitions.Add(moduledefinition);
index = moduledefinitions.FindIndex(item => item.ModuleDefinitionName == qualifiedModuleType); index = moduledefinitions.FindIndex(item => item.ModuleDefinitionName == qualifiedModuleType);
} }
moduledefinition = moduledefinitions[index]; moduledefinition = moduledefinitions[index];
// actions // actions
var modulecontrolobject = Activator.CreateInstance(modulecontroltype); var modulecontrolobject = Activator.CreateInstance(modulecontroltype);
string actions = (string)modulecontroltype.GetProperty("Actions")?.GetValue(modulecontrolobject); string actions = (string) modulecontroltype.GetProperty("Actions")?.GetValue(modulecontrolobject);
if (!string.IsNullOrEmpty(actions)) if (!string.IsNullOrEmpty(actions))
{ {
foreach (string action in actions.Split(',')) foreach (string action in actions.Split(','))
@ -255,12 +272,11 @@ namespace Oqtane.Repository
moduledefinition.ControlTypeRoutes += (action + "=" + modulecontroltype.FullName + ", " + typename[1] + ";"); moduledefinition.ControlTypeRoutes += (action + "=" + modulecontroltype.FullName + ", " + typename[1] + ";");
} }
} }
moduledefinitions[index] = moduledefinition; moduledefinitions[index] = moduledefinition;
} }
}
return moduledefinitions; return moduledefinitions;
} }
} }
} }

View File

@ -22,8 +22,8 @@ namespace Oqtane.Repository
List<SiteTemplate> siteTemplates = new List<SiteTemplate>(); List<SiteTemplate> siteTemplates = new List<SiteTemplate>();
// iterate through Oqtane site template assemblies // iterate through Oqtane site template assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies() var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
.Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".SiteTemplate.")).ToArray();
foreach (Assembly assembly in assemblies) foreach (Assembly assembly in assemblies)
{ {
siteTemplates = LoadSiteTemplatesFromAssembly(siteTemplates, assembly); siteTemplates = LoadSiteTemplatesFromAssembly(siteTemplates, assembly);

View File

@ -31,8 +31,7 @@ namespace Oqtane.Repository
List<Theme> themes = new List<Theme>(); List<Theme> themes = new List<Theme>();
// iterate through Oqtane theme assemblies // iterate through Oqtane theme assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies() var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
.Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Theme.")).ToArray();
foreach (Assembly assembly in assemblies) foreach (Assembly assembly in assemblies)
{ {
themes = LoadThemesFromAssembly(themes, assembly); themes = LoadThemesFromAssembly(themes, assembly);

View File

@ -41,7 +41,7 @@ namespace Oqtane
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddMvc().AddNewtonsoftJson();
services.AddServerSideBlazor(); services.AddServerSideBlazor();
// setup HttpClient for server side in a client side compatible fashion ( with auth cookie ) // setup HttpClient for server side in a client side compatible fashion ( with auth cookie )
@ -188,16 +188,13 @@ namespace Oqtane
services.AddTransient<IUpgradeManager, UpgradeManager>(); services.AddTransient<IUpgradeManager, UpgradeManager>();
// load the external assemblies into the app domain // load the external assemblies into the app domain
services.AddOqtaneModules(); services.AddOqtaneParts();
services.AddOqtaneThemes();
services.AddOqtaneSiteTemplates();
services.AddMvc() services.AddMvc()
.AddOqtaneApplicationParts() // register any Controllers from custom modules .AddOqtaneApplicationParts() // register any Controllers from custom modules
.AddNewtonsoftJson(); .AddNewtonsoftJson();
services.AddOqtaneServices();
services.AddOqtaneHostedServices();
services.AddSwaggerGen(c => services.AddSwaggerGen(c =>
{ {

File diff suppressed because it is too large Load Diff

View File

@ -70,7 +70,7 @@ window.interop = {
link.integrity = integrity; link.integrity = integrity;
} }
if (crossorigin !== "") { if (crossorigin !== "") {
link.crossorigin = crossorigin; link.crossOrigin = crossorigin;
} }
document.head.appendChild(link); document.head.appendChild(link);
} }
@ -87,7 +87,7 @@ window.interop = {
if (integrity !== "" && link.integrity !== integrity) { if (integrity !== "" && link.integrity !== integrity) {
link.setAttribute('integrity', integrity); link.setAttribute('integrity', integrity);
} }
if (crossorigin !== "" && link.crossorigin !== crossorigin) { if (crossorigin !== "" && link.crossOrigin !== crossorigin) {
link.setAttribute('crossorigin', crossorigin); link.setAttribute('crossorigin', crossorigin);
} }
} }

View File

@ -0,0 +1,9 @@
using System;
namespace Oqtane.Shared
{
[AttributeUsage(AttributeTargets.Class)]
public class OqtaneIgnoreAttribute : Attribute
{
}
}