Username And Email Must Be Provided And Password Must Be Greater Than 5 Characters
";
}
}
}
diff --git a/Oqtane.Client/Shared/Interop.cs b/Oqtane.Client/Shared/Interop.cs
index 16a0096f..4ff07ae4 100644
--- a/Oqtane.Client/Shared/Interop.cs
+++ b/Oqtane.Client/Shared/Interop.cs
@@ -100,6 +100,20 @@ namespace Oqtane.Shared
}
}
+ public ValueTask GetFiles(string name)
+ {
+ try
+ {
+ return jsRuntime.InvokeAsync(
+ "interop.getFiles",
+ name);
+ }
+ catch
+ {
+ return new ValueTask(Task.FromResult(new string[0]));
+ }
+ }
+
public Task UploadFiles(string posturl, string folder, string name)
{
try
diff --git a/Oqtane.Client/Shared/ModuleInstance.razor b/Oqtane.Client/Shared/ModuleInstance.razor
index 51dcae06..30574fa4 100644
--- a/Oqtane.Client/Shared/ModuleInstance.razor
+++ b/Oqtane.Client/Shared/ModuleInstance.razor
@@ -21,10 +21,12 @@
DynamicComponent = builder =>
{
string typename = ModuleState.ModuleType;
- if (PageState.Control == "Settings") // module settings are a core component
- {
- typename = Constants.DefaultSettingsControl;
+ // check for core module actions component
+ if (Constants.DefaultModuleActions.Contains(PageState.Control))
+ {
+ typename = Constants.DefaultModuleActionsTemplate.Replace("{Control}", PageState.Control);
}
+
Type moduleType = null;
if (typename != null)
{
diff --git a/Oqtane.Client/Shared/Pane.razor b/Oqtane.Client/Shared/Pane.razor
index f55e9881..ecad62f5 100644
--- a/Oqtane.Client/Shared/Pane.razor
+++ b/Oqtane.Client/Shared/Pane.razor
@@ -40,21 +40,22 @@
{
if (PageState.ModuleId != -1 && PageState.Control != "")
{
- if (Name == Constants.AdminPane)
+ if (Name.ToLower() == Constants.AdminPane.ToLower())
{
Module module = PageState.Modules.Where(item => item.ModuleId == PageState.ModuleId).FirstOrDefault();
if (module != null)
{
string typename = module.ModuleType;
- if (PageState.Control == "Settings")
+ // check for core module actions component
+ if (Constants.DefaultModuleActions.Contains(PageState.Control))
{
- typename = Constants.DefaultSettingsControl;
+ typename = Constants.DefaultModuleActionsTemplate.Replace("{Control}", PageState.Control);
}
Type moduleType = Type.GetType(typename);
if (moduleType != null)
{
bool authorized = false;
- if (PageState.Control == "Settings")
+ if (Constants.DefaultModuleActions.Contains(PageState.Control))
{
authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions);
}
@@ -82,7 +83,7 @@
}
if (authorized)
{
- if (PageState.Control != "Settings" && module.ControlTitle != "")
+ if (!Constants.DefaultModuleActions.Contains(PageState.Control) && module.ControlTitle != "")
{
module.Title = module.ControlTitle;
}
@@ -93,8 +94,8 @@
}
else
{
- // module control does not exist with name specified
- }
+ // module control does not exist with name specified
+ }
}
}
}
@@ -103,10 +104,10 @@
if (PageState.ModuleId != -1)
{
Module module = PageState.Modules.Where(item => item.ModuleId == PageState.ModuleId).FirstOrDefault();
- if (module != null && module.Pane == Name)
+ if (module != null && module.Pane.ToLower() == Name.ToLower())
{
- // check if user is authorized to view module
- if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
+ // check if user is authorized to view module
+ if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
{
builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer));
builder.AddAttribute(1, "Module", module);
@@ -116,10 +117,10 @@
}
else
{
- foreach (Module module in PageState.Modules.Where(item => item.Pane == Name).OrderBy(x => x.Order).ToArray())
+ foreach (Module module in PageState.Modules.Where(item => item.Pane.ToLower() == Name.ToLower()).OrderBy(x => x.Order).ToArray())
{
- // check if user is authorized to view module
- if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
+ // check if user is authorized to view module
+ if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
{
builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer));
builder.AddAttribute(1, "Module", module);
diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor
index ab32578e..17324f25 100644
--- a/Oqtane.Client/Shared/SiteRouter.razor
+++ b/Oqtane.Client/Shared/SiteRouter.razor
@@ -342,9 +342,10 @@
// get IModuleControl properties
typename = module.ModuleType;
- if (control == "Settings")
+ // check for core module actions component
+ if (Constants.DefaultModuleActions.Contains(control))
{
- typename = Constants.DefaultSettingsControl;
+ typename = Constants.DefaultModuleActionsTemplate.Replace("{Control}", control);
}
Type moduletype = Type.GetType(typename);
if (moduletype != null)
@@ -358,7 +359,7 @@
}
// ensure module's pane exists in current page and if not, assign it to the Admin pane
- if (!panes.Contains(module.Pane))
+ if (!panes.ToLower().Contains(module.Pane.ToLower()))
{
module.Pane = Constants.AdminPane;
}
diff --git a/Oqtane.Client/Shared/Utilities.cs b/Oqtane.Client/Shared/Utilities.cs
index 42f2abde..57db7a24 100644
--- a/Oqtane.Client/Shared/Utilities.cs
+++ b/Oqtane.Client/Shared/Utilities.cs
@@ -59,6 +59,18 @@ namespace Oqtane.Shared
return url;
}
+ public static string GetTypeName(string fullyqualifiedtypename)
+ {
+ if (fullyqualifiedtypename.Contains(","))
+ {
+ return fullyqualifiedtypename.Substring(0, fullyqualifiedtypename.IndexOf(","));
+ }
+ else
+ {
+ return fullyqualifiedtypename;
+ }
+ }
+
public static string GetTypeNameClass(string typename)
{
if (typename.Contains(","))
diff --git a/Oqtane.Client/Themes/ContainerBase.cs b/Oqtane.Client/Themes/ContainerBase.cs
index 4475bed6..4d8c437b 100644
--- a/Oqtane.Client/Themes/ContainerBase.cs
+++ b/Oqtane.Client/Themes/ContainerBase.cs
@@ -3,6 +3,7 @@ using Microsoft.JSInterop;
using Oqtane.Shared;
using Oqtane.Models;
using System.Threading.Tasks;
+using System.Linq;
namespace Oqtane.Themes
{
@@ -17,6 +18,14 @@ namespace Oqtane.Themes
[CascadingParameter]
protected Module ModuleState { get; set; }
+ protected ModuleDefinition ModuleDefinition
+ {
+ get
+ {
+ return PageState.ModuleDefinitions.Where(item => item.ModuleDefinitionName == ModuleState.ModuleDefinitionName).FirstOrDefault();
+ }
+ }
+
public virtual string Name { get; set; }
public string ThemePath()
diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor
index 1d1236d9..a86e7548 100644
--- a/Oqtane.Client/Themes/Controls/ModuleActions.razor
+++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor
@@ -48,8 +48,13 @@
actions.Add(new ActionViewModel { Action = pane, Name = "Move To " + pane + " Pane" });
}
}
- actions.Add(new ActionViewModel { Action = "settings", Name = "Settings" });
- actions.Add(new ActionViewModel { Action = "delete", Name = "Delete" });
+ actions.Add(new ActionViewModel { Action = "settings", Name = "Manage Settings" });
+ if (ModuleDefinition.ServerAssemblyName != "")
+ {
+ actions.Add(new ActionViewModel { Action = "import", Name = "Import Content" });
+ actions.Add(new ActionViewModel { Action = "export", Name = "Export Content" });
+ }
+ actions.Add(new ActionViewModel { Action = "delete", Name = "Delete Module" });
}
}
@@ -85,6 +90,12 @@
case "settings":
url = EditUrl(pagemodule.ModuleId, "Settings");
break;
+ case "import":
+ url = EditUrl(pagemodule.ModuleId, "Import");
+ break;
+ case "export":
+ url = EditUrl(pagemodule.ModuleId, "Export");
+ break;
case "delete":
await PageModuleService.DeletePageModuleAsync(pagemodule.PageModuleId);
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
diff --git a/Oqtane.Client/Themes/Controls/ModuleTitle.razor b/Oqtane.Client/Themes/Controls/ModuleTitle.razor
index 8e394d21..ffe99613 100644
--- a/Oqtane.Client/Themes/Controls/ModuleTitle.razor
+++ b/Oqtane.Client/Themes/Controls/ModuleTitle.razor
@@ -9,7 +9,8 @@
protected override Task OnParametersSetAsync()
{
title = ModuleState.Title;
- if (PageState.Control == "Settings")
+ // check for core module actions component
+ if (Constants.DefaultModuleActions.Contains(PageState.Control))
{
title = PageState.Control;
}
diff --git a/Oqtane.Client/wwwroot/js/interop.js b/Oqtane.Client/wwwroot/js/interop.js
index 0832cee0..3c4279d0 100644
--- a/Oqtane.Client/wwwroot/js/interop.js
+++ b/Oqtane.Client/wwwroot/js/interop.js
@@ -64,6 +64,16 @@ window.interop = {
document.body.appendChild(form);
form.submit();
},
+ getFiles: function (name) {
+ var files = [];
+ var fileinput = document.getElementById(name);
+ if (fileinput !== null) {
+ for (var i = 0; i < fileinput.files.length; i++) {
+ files.push(fileinput.files[i].name);
+ }
+ }
+ return files;
+ },
uploadFiles: function (posturl, folder, name) {
var files = document.getElementById(name + 'FileInput').files;
var progressinfo = document.getElementById(name + 'ProgressInfo');
diff --git a/Oqtane.Server/Controllers/AliasController.cs b/Oqtane.Server/Controllers/AliasController.cs
index b559c41e..cf7bbf9f 100644
--- a/Oqtane.Server/Controllers/AliasController.cs
+++ b/Oqtane.Server/Controllers/AliasController.cs
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authorization;
using Oqtane.Repository;
using Oqtane.Models;
using Oqtane.Shared;
+using System.Linq;
namespace Oqtane.Controllers
{
diff --git a/Oqtane.Server/Controllers/FileController.cs b/Oqtane.Server/Controllers/FileController.cs
index 430b1cbf..43057e6f 100644
--- a/Oqtane.Server/Controllers/FileController.cs
+++ b/Oqtane.Server/Controllers/FileController.cs
@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@@ -17,7 +18,25 @@ namespace Oqtane.Controllers
this.environment = environment;
}
- // GET api//current
+ // GET: api/?folder=x
+ [HttpGet]
+ public IEnumerable Get(string folder)
+ {
+ List files = new List();
+ folder = folder.Replace("/", "\\");
+ if (folder.StartsWith("\\")) folder = folder.Substring(1);
+ folder = Path.Combine(environment.WebRootPath, folder);
+ if (Directory.Exists(folder))
+ {
+ foreach(string file in Directory.GetFiles(folder))
+ {
+ files.Add(file);
+ }
+ }
+ return files;
+ }
+
+ // POST api//upload
[HttpPost("upload")]
public async Task UploadFile(string folder, IFormFile file)
{
diff --git a/Oqtane.Server/Controllers/InstallationController.cs b/Oqtane.Server/Controllers/InstallationController.cs
index 99f0f769..e32ed335 100644
--- a/Oqtane.Server/Controllers/InstallationController.cs
+++ b/Oqtane.Server/Controllers/InstallationController.cs
@@ -1,9 +1,12 @@
using DbUp;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
+using Oqtane.Infrastructure;
using Oqtane.Models;
+using Oqtane.Shared;
using System;
using System.Data.SqlClient;
using System.IO;
@@ -17,28 +20,41 @@ namespace Oqtane.Controllers
public class InstallationController : Controller
{
private readonly IConfigurationRoot Config;
+ private readonly IInstallationManager InstallationManager;
- public InstallationController(IConfigurationRoot Config)
+ public InstallationController(IConfigurationRoot Config, IInstallationManager InstallationManager)
{
this.Config = Config;
+ this.InstallationManager = InstallationManager;
}
// POST api/
[HttpPost]
- public GenericResponse Post([FromBody] string connectionString)
+ public GenericResponse Post([FromBody] string connectionstring)
{
var response = new GenericResponse { Success = false, Message = "" };
if (ModelState.IsValid)
{
- bool exists = IsInstalled().Success;
+ bool master = false;
+ string defaultconnectionstring = Config.GetConnectionString("DefaultConnection");
+ if (string.IsNullOrEmpty(defaultconnectionstring) || connectionstring != defaultconnectionstring)
+ {
+ master = true;
+ }
+
+ bool exists = false;
+ if (master)
+ {
+ exists = IsInstalled().Success;
+ }
if (!exists)
{
string datadirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
- connectionString = connectionString.Replace("|DataDirectory|", datadirectory);
+ connectionstring = connectionstring.Replace("|DataDirectory|", datadirectory);
- SqlConnection connection = new SqlConnection(connectionString);
+ SqlConnection connection = new SqlConnection(connectionstring);
try
{
using (connection)
@@ -57,7 +73,7 @@ namespace Oqtane.Controllers
{
string masterConnectionString = "";
string databaseName = "";
- string[] fragments = connectionString.Split(';', StringSplitOptions.RemoveEmptyEntries);
+ string[] fragments = connectionstring.Split(';', StringSplitOptions.RemoveEmptyEntries);
foreach (string fragment in fragments)
{
if (fragment.ToLower().Contains("initial catalog=") || fragment.ToLower().Contains("database="))
@@ -79,7 +95,7 @@ namespace Oqtane.Controllers
{
connection.Open();
SqlCommand command;
- if (connectionString.ToLower().Contains("attachdbfilename=")) // LocalDB
+ if (connectionstring.ToLower().Contains("attachdbfilename=")) // LocalDB
{
command = new SqlCommand("CREATE DATABASE [" + databaseName + "] ON ( NAME = '" + databaseName + "', FILENAME = '" + datadirectory + "\\" + databaseName + ".mdf')", connection);
}
@@ -104,14 +120,17 @@ namespace Oqtane.Controllers
{
// get master initialization script and update connectionstring and alias in seed data
string initializationScript = "";
- using (StreamReader reader = new StreamReader(Directory.GetCurrentDirectory() + "\\Scripts\\Master.sql"))
+ if (master)
{
- initializationScript = reader.ReadToEnd();
+ using (StreamReader reader = new StreamReader(Directory.GetCurrentDirectory() + "\\Scripts\\Master.sql"))
+ {
+ initializationScript = reader.ReadToEnd();
+ }
+ initializationScript = initializationScript.Replace("{ConnectionString}", connectionstring);
+ initializationScript = initializationScript.Replace("{Alias}", HttpContext.Request.Host.Value);
}
- initializationScript = initializationScript.Replace("{ConnectionString}", connectionString);
- initializationScript = initializationScript.Replace("{Alias}", HttpContext.Request.Host.Value);
- var dbUpgradeConfig = DeployChanges.To.SqlDatabase(connectionString)
+ var dbUpgradeConfig = DeployChanges.To.SqlDatabase(connectionstring)
.WithScript(new DbUp.Engine.SqlScript("Master.sql", initializationScript))
.WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()); // tenant scripts should be added to /Scripts folder as Embedded Resources
var dbUpgrade = dbUpgradeConfig.Build();
@@ -125,19 +144,22 @@ namespace Oqtane.Controllers
else
{
// update appsettings
- string config = "";
- using (StreamReader reader = new StreamReader(Directory.GetCurrentDirectory() + "\\appsettings.json"))
+ if (master)
{
- config = reader.ReadToEnd();
+ string config = "";
+ using (StreamReader reader = new StreamReader(Directory.GetCurrentDirectory() + "\\appsettings.json"))
+ {
+ config = reader.ReadToEnd();
+ }
+ connectionstring = connectionstring.Replace(datadirectory, "|DataDirectory|");
+ connectionstring = connectionstring.Replace(@"\", @"\\");
+ config = config.Replace("DefaultConnection\": \"", "DefaultConnection\": \"" + connectionstring);
+ using (StreamWriter writer = new StreamWriter(Directory.GetCurrentDirectory() + "\\appsettings.json"))
+ {
+ writer.WriteLine(config);
+ }
+ Config.Reload();
}
- connectionString = connectionString.Replace(datadirectory, "|DataDirectory|");
- connectionString = connectionString.Replace(@"\", @"\\");
- config = config.Replace("DefaultConnection\": \"", "DefaultConnection\": \"" + connectionString);
- using (StreamWriter writer = new StreamWriter(Directory.GetCurrentDirectory() + "\\appsettings.json"))
- {
- writer.WriteLine(config);
- }
- Config.Reload();
response.Success = true;
}
}
@@ -235,6 +257,15 @@ namespace Oqtane.Controllers
}
}
}
+
+ [HttpGet("upgrade")]
+ [Authorize(Roles = Constants.HostRole)]
+ public GenericResponse Upgrade()
+ {
+ var response = new GenericResponse { Success = true, Message = "" };
+ InstallationManager.InstallPackages("Framework");
+ return response;
+ }
}
public class InstallationContext : DbContext
diff --git a/Oqtane.Server/Controllers/ModuleController.cs b/Oqtane.Server/Controllers/ModuleController.cs
index 1c60310a..7d85e47a 100644
--- a/Oqtane.Server/Controllers/ModuleController.cs
+++ b/Oqtane.Server/Controllers/ModuleController.cs
@@ -4,6 +4,12 @@ using Microsoft.AspNetCore.Authorization;
using Oqtane.Repository;
using Oqtane.Models;
using Oqtane.Shared;
+using System.Linq;
+using System.Reflection;
+using System;
+using Oqtane.Modules;
+using Microsoft.Extensions.DependencyInjection;
+using System.Text.Json;
namespace Oqtane.Controllers
{
@@ -12,24 +18,28 @@ namespace Oqtane.Controllers
{
private readonly IModuleRepository Modules;
private readonly IPageModuleRepository PageModules;
+ private readonly IModuleDefinitionRepository ModuleDefinitions;
+ private readonly IServiceProvider ServiceProvider;
- public ModuleController(IModuleRepository Modules, IPageModuleRepository PageModules)
+ public ModuleController(IModuleRepository Modules, IPageModuleRepository PageModules, IModuleDefinitionRepository ModuleDefinitions, IServiceProvider ServiceProvider)
{
this.Modules = Modules;
this.PageModules = PageModules;
+ this.ModuleDefinitions = ModuleDefinitions;
+ this.ServiceProvider = ServiceProvider;
}
// GET: api/?pageid=x
// GET: api/?siteid=x&moduledefinitionname=x
[HttpGet]
- public IEnumerable Get(string pageid, string siteid, string moduledefinitionname)
+ public IEnumerable Get(string pageid, string siteid, string moduledefinitionname)
{
if (!string.IsNullOrEmpty(pageid))
{
- List modulelist = new List();
+ List modulelist = new List();
foreach (PageModule pagemodule in PageModules.GetPageModules(int.Parse(pageid)))
{
- Module module = pagemodule.Module;
+ Models.Module module = pagemodule.Module;
module.PageModuleId = pagemodule.PageModuleId;
module.PageId = pagemodule.PageId;
module.Title = pagemodule.Title;
@@ -48,7 +58,7 @@ namespace Oqtane.Controllers
// GET api//5
[HttpGet("{id}")]
- public Module Get(int id)
+ public Models.Module Get(int id)
{
return Modules.GetModule(id);
}
@@ -56,7 +66,7 @@ namespace Oqtane.Controllers
// POST api/
[HttpPost]
[Authorize(Roles = Constants.AdminRole)]
- public Module Post([FromBody] Module Module)
+ public Models.Module Post([FromBody] Models.Module Module)
{
if (ModelState.IsValid)
{
@@ -68,7 +78,7 @@ namespace Oqtane.Controllers
// PUT api//5
[HttpPut("{id}")]
[Authorize(Roles = Constants.AdminRole)]
- public Module Put(int id, [FromBody] Module Module)
+ public Models.Module Put(int id, [FromBody] Models.Module Module)
{
if (ModelState.IsValid)
{
@@ -84,5 +94,103 @@ namespace Oqtane.Controllers
{
Modules.DeleteModule(id);
}
+
+ // GET api//export?moduleid=x
+ [HttpGet("export")]
+ [Authorize(Roles = Constants.AdminRole)]
+ public string Export(int moduleid)
+ {
+ string content = "";
+ try
+ {
+ Models.Module module = Modules.GetModule(moduleid);
+ if (module != null)
+ {
+ List moduledefinitions = ModuleDefinitions.GetModuleDefinitions(module.SiteId).ToList();
+ ModuleDefinition moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == module.ModuleDefinitionName).FirstOrDefault();
+ if (moduledefinition != null)
+ {
+ ModuleContent modulecontent = new ModuleContent();
+ modulecontent.ModuleDefinitionName = moduledefinition.ModuleDefinitionName;
+ modulecontent.Version = moduledefinition.Version;
+ modulecontent.Content = "";
+
+ if (moduledefinition.ServerAssemblyName != "")
+ {
+ Assembly assembly = AppDomain.CurrentDomain.GetAssemblies()
+ .Where(item => item.FullName.StartsWith(moduledefinition.ServerAssemblyName)).FirstOrDefault();
+ if (assembly != null)
+ {
+ Type moduletype = assembly.GetTypes()
+ .Where(item => item.Namespace != null)
+ .Where(item => item.Namespace.StartsWith(moduledefinition.ModuleDefinitionName.Substring(0, moduledefinition.ModuleDefinitionName.IndexOf(","))))
+ .Where(item => item.GetInterfaces().Contains(typeof(IPortable))).FirstOrDefault();
+ if (moduletype != null)
+ {
+ var moduleobject = ActivatorUtilities.CreateInstance(ServiceProvider, moduletype);
+ modulecontent.Content = ((IPortable)moduleobject).ExportModule(module);
+ }
+ }
+ }
+ content = JsonSerializer.Serialize(modulecontent);
+ }
+ }
+ }
+ catch
+ {
+ // error occurred during export
+ }
+ return content;
+ }
+
+ // POST api//import?moduleid=x
+ [HttpPost("import")]
+ [Authorize(Roles = Constants.AdminRole)]
+ public bool Import(int moduleid, [FromBody] string Content)
+ {
+ bool success = false;
+ if (ModelState.IsValid)
+ {
+ try
+ {
+ Models.Module module = Modules.GetModule(moduleid);
+ if (module != null)
+ {
+ List moduledefinitions = ModuleDefinitions.GetModuleDefinitions(module.SiteId).ToList();
+ ModuleDefinition moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == module.ModuleDefinitionName).FirstOrDefault();
+ if (moduledefinition != null)
+ {
+ ModuleContent modulecontent = JsonSerializer.Deserialize(Content);
+ if (modulecontent.ModuleDefinitionName == moduledefinition.ModuleDefinitionName)
+ {
+ if (moduledefinition.ServerAssemblyName != "")
+ {
+ Assembly assembly = AppDomain.CurrentDomain.GetAssemblies()
+ .Where(item => item.FullName.StartsWith(moduledefinition.ServerAssemblyName)).FirstOrDefault();
+ if (assembly != null)
+ {
+ Type moduletype = assembly.GetTypes()
+ .Where(item => item.Namespace != null)
+ .Where(item => item.Namespace.StartsWith(moduledefinition.ModuleDefinitionName.Substring(0, moduledefinition.ModuleDefinitionName.IndexOf(","))))
+ .Where(item => item.GetInterfaces().Contains(typeof(IPortable))).FirstOrDefault();
+ if (moduletype != null)
+ {
+ var moduleobject = ActivatorUtilities.CreateInstance(ServiceProvider, moduletype);
+ ((IPortable)moduleobject).ImportModule(module, modulecontent.Content, modulecontent.Version);
+ success = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch
+ {
+ // error occurred during import
+ }
+ }
+ return success;
+ }
}
}
diff --git a/Oqtane.Server/Controllers/PackageController.cs b/Oqtane.Server/Controllers/PackageController.cs
index d91ca1af..3ee78da4 100644
--- a/Oqtane.Server/Controllers/PackageController.cs
+++ b/Oqtane.Server/Controllers/PackageController.cs
@@ -9,6 +9,8 @@ using System.Threading;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Authorization;
+using Oqtane.Shared;
namespace Oqtane.Controllers
{
@@ -24,6 +26,7 @@ namespace Oqtane.Controllers
// GET: api/?tag=x
[HttpGet]
+ [Authorize(Roles = Constants.HostRole)]
public async Task> Get(string tag)
{
List packages = new List();
@@ -52,6 +55,7 @@ namespace Oqtane.Controllers
}
[HttpPost]
+ [Authorize(Roles = Constants.HostRole)]
public async Task Post(string packageid, string version, string folder)
{
using (var httpClient = new HttpClient())
diff --git a/Oqtane.Server/Infrastructure/InstallationManager.cs b/Oqtane.Server/Infrastructure/InstallationManager.cs
index 32ffd323..5f357640 100644
--- a/Oqtane.Server/Infrastructure/InstallationManager.cs
+++ b/Oqtane.Server/Infrastructure/InstallationManager.cs
@@ -45,11 +45,12 @@ namespace Oqtane.Infrastructure
foreach (ZipArchiveEntry entry in archive.Entries)
{
string filename = Path.GetFileName(entry.FullName);
- switch (Path.GetExtension(filename))
+ switch (Path.GetExtension(filename).ToLower())
{
case ".dll":
entry.ExtractToFile(Path.Combine(binfolder, filename), true);
break;
+ case ".nuspec":
case ".png":
case ".jpg":
case ".jpeg":
diff --git a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs
new file mode 100644
index 00000000..71f37091
--- /dev/null
+++ b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs
@@ -0,0 +1,46 @@
+using Oqtane.Models;
+using Oqtane.Modules.HtmlText.Models;
+using Oqtane.Modules.HtmlText.Repository;
+using System.Net;
+
+namespace Oqtane.Modules.HtmlText.Manager
+{
+ public class HtmlTextManager : IPortable
+ {
+ private IHtmlTextRepository htmltexts;
+
+ public HtmlTextManager(IHtmlTextRepository htmltexts)
+ {
+ this.htmltexts = htmltexts;
+ }
+
+ public string ExportModule(Module Module)
+ {
+ string content = "";
+ HtmlTextInfo htmltext = htmltexts.GetHtmlText(Module.ModuleId);
+ if (htmltext != null)
+ {
+ content = WebUtility.HtmlEncode(htmltext.Content);
+ }
+ return content;
+ }
+
+ public void ImportModule(Module Module, string Content, string Version)
+ {
+ Content = WebUtility.HtmlDecode(Content);
+ HtmlTextInfo htmltext = htmltexts.GetHtmlText(Module.ModuleId);
+ if (htmltext != null)
+ {
+ htmltext.Content = Content;
+ htmltexts.UpdateHtmlText(htmltext);
+ }
+ else
+ {
+ htmltext = new HtmlTextInfo();
+ htmltext.ModuleId = Module.ModuleId;
+ htmltext.Content = Content;
+ htmltexts.AddHtmlText(htmltext);
+ }
+ }
+ }
+}
diff --git a/Oqtane.Server/Modules/IPortable.cs b/Oqtane.Server/Modules/IPortable.cs
new file mode 100644
index 00000000..871c3045
--- /dev/null
+++ b/Oqtane.Server/Modules/IPortable.cs
@@ -0,0 +1,13 @@
+using Oqtane.Models;
+
+namespace Oqtane.Modules
+{
+ public interface IPortable
+ {
+ // You Must Set The "ServerAssemblyName" In Your IModule Interface
+
+ string ExportModule(Module Module);
+
+ void ImportModule(Module Module, string Content, string Version);
+ }
+}
diff --git a/Oqtane.Server/Repository/AliasRepository.cs b/Oqtane.Server/Repository/AliasRepository.cs
index e8fd87b9..3df7eac5 100644
--- a/Oqtane.Server/Repository/AliasRepository.cs
+++ b/Oqtane.Server/Repository/AliasRepository.cs
@@ -31,6 +31,7 @@ namespace Oqtane.Repository
{
db.Alias.Add(Alias);
db.SaveChanges();
+ _cache.Remove("aliases");
return Alias;
}
@@ -38,6 +39,7 @@ namespace Oqtane.Repository
{
db.Entry(Alias).State = EntityState.Modified;
db.SaveChanges();
+ _cache.Remove("aliases");
return Alias;
}
@@ -50,6 +52,7 @@ namespace Oqtane.Repository
{
Alias alias = db.Alias.Find(AliasId);
db.Alias.Remove(alias);
+ _cache.Remove("aliases");
db.SaveChanges();
}
}
diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs
index 260e0403..47c0ec41 100644
--- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs
+++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs
@@ -5,31 +5,32 @@ using Oqtane.Models;
using System.Reflection;
using System;
using Oqtane.Modules;
+using Microsoft.Extensions.Caching.Memory;
namespace Oqtane.Repository
{
public class ModuleDefinitionRepository : IModuleDefinitionRepository
{
private MasterDBContext db;
+ private readonly IMemoryCache _cache;
private readonly IPermissionRepository Permissions;
- public ModuleDefinitionRepository(MasterDBContext context, IPermissionRepository Permissions)
+ public ModuleDefinitionRepository(MasterDBContext context, IMemoryCache cache, IPermissionRepository Permissions)
{
db = context;
+ _cache = cache;
this.Permissions = Permissions;
}
private List LoadModuleDefinitions(int SiteId)
{
- List ModuleDefinitions = new List();
+ List ModuleDefinitions;
- // iterate through Oqtane module assemblies
- Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies()
- .Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Module.")).ToArray();
- foreach (Assembly assembly in assemblies)
+ ModuleDefinitions = _cache.GetOrCreate("moduledefinitions", entry =>
{
- ModuleDefinitions = LoadModuleDefinitionsFromAssembly(ModuleDefinitions, assembly);
- }
+ entry.SlidingExpiration = TimeSpan.FromMinutes(30);
+ return LoadModuleDefinitionsFromAssemblies();
+ });
// sync module definitions with database
List moduledefs = db.ModuleDefinition.ToList();
@@ -65,6 +66,19 @@ namespace Oqtane.Repository
return ModuleDefinitions;
}
+ private List LoadModuleDefinitionsFromAssemblies()
+ {
+ List ModuleDefinitions = new List();
+ // iterate through Oqtane module assemblies
+ Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies()
+ .Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Module.")).ToArray();
+ foreach (Assembly assembly in assemblies)
+ {
+ ModuleDefinitions = LoadModuleDefinitionsFromAssembly(ModuleDefinitions, assembly);
+ }
+ return ModuleDefinitions;
+ }
+
private List LoadModuleDefinitionsFromAssembly(List moduledefinitions, Assembly assembly)
{
ModuleDefinition moduledefinition;
@@ -105,6 +119,7 @@ namespace Oqtane.Repository
License = GetProperty(properties, "License"),
Dependencies = GetProperty(properties, "Dependencies"),
PermissionNames = GetProperty(properties, "PermissionNames"),
+ ServerAssemblyName = GetProperty(properties, "ServerAssemblyName"),
ControlTypeTemplate = ModuleType + ".{Control}" + ", " + typename[1],
ControlTypeRoutes = "",
AssemblyName = assembly.FullName.Split(",")[0]
@@ -125,6 +140,7 @@ namespace Oqtane.Repository
License = "",
Dependencies = "",
PermissionNames = "",
+ ServerAssemblyName = "",
ControlTypeTemplate = ModuleType + ".{Control}" + ", " + typename[1],
ControlTypeRoutes = "",
AssemblyName = assembly.FullName.Split(",")[0]
diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs
index 1430f594..6a190ca8 100644
--- a/Oqtane.Server/Repository/SiteRepository.cs
+++ b/Oqtane.Server/Repository/SiteRepository.cs
@@ -4,6 +4,9 @@ using System.Linq;
using Oqtane.Models;
using Oqtane.Shared;
using System;
+using System.Reflection;
+using Oqtane.Modules;
+using Microsoft.Extensions.DependencyInjection;
namespace Oqtane.Repository
{
@@ -15,9 +18,11 @@ namespace Oqtane.Repository
private readonly IPageRepository PageRepository;
private readonly IModuleRepository ModuleRepository;
private readonly IPageModuleRepository PageModuleRepository;
+ private readonly IModuleDefinitionRepository ModuleDefinitionRepository;
+ private readonly IServiceProvider ServiceProvider;
private readonly List SiteTemplate;
- public SiteRepository(TenantDBContext context, IRoleRepository RoleRepository, IProfileRepository ProfileRepository, IPageRepository PageRepository, IModuleRepository ModuleRepository, IPageModuleRepository PageModuleRepository)
+ public SiteRepository(TenantDBContext context, IRoleRepository RoleRepository, IProfileRepository ProfileRepository, IPageRepository PageRepository, IModuleRepository ModuleRepository, IPageModuleRepository PageModuleRepository, IModuleDefinitionRepository ModuleDefinitionRepository, IServiceProvider ServiceProvider)
{
db = context;
this.RoleRepository = RoleRepository;
@@ -25,33 +30,54 @@ namespace Oqtane.Repository
this.PageRepository = PageRepository;
this.ModuleRepository = ModuleRepository;
this.PageModuleRepository = PageModuleRepository;
+ this.ModuleDefinitionRepository = ModuleDefinitionRepository;
+ this.ServiceProvider = ServiceProvider;
- // defines the default site template
+ // define the default site template
SiteTemplate = new List();
- SiteTemplate.Add(new PageTemplate { Name = "Home", Parent = "", Path = "", Order = 1, Icon = "home", IsNavigation = true, EditMode = false, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "", ModulePermissions = "", Title = "", Pane = "", ContainerType = "" });
- SiteTemplate.Add(new PageTemplate { Name = "Admin", Parent = "", Path = "admin", Order = 1, Icon = "", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Dashboard, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Administration", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "Site Management", Parent = "Admin", Path = "admin/sites", Order = 1, Icon = "globe", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Sites, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Site Management", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "Page Management", Parent = "Admin", Path = "admin/pages", Order = 1, Icon = "layers", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Pages, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Page Management", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "Module Management", Parent = "Admin", Path = "admin/modules", Order = 1, Icon = "browser", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.ModuleDefinitions, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Module Management", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "Theme Management", Parent = "Admin", Path = "admin/themes", Order = 1, Icon = "brush", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Themes, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Theme Management", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "User Management", Parent = "Admin", Path = "admin/users", Order = 1, Icon = "person", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Users, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "User Management", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "Role Management", Parent = "Admin", Path = "admin/roles", Order = 1, Icon = "lock-locked", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Roles, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Role Management", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "Tenant Management", Parent = "Admin", Path = "admin/tenants", Order = 1, Icon = "list", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Tenants, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Site Management", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "Login", Parent = "", Path = "login", Order = 1, Icon = "lock-locked", IsNavigation = false, EditMode = false, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Login, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Login", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "Register", Parent = "", Path = "register", Order = 1, Icon = "person", IsNavigation = false, EditMode = false, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Register, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Register", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
- SiteTemplate.Add(new PageTemplate { Name = "Profile", Parent = "", Path = "profile", Order = 1, Icon = "person", IsNavigation = false, EditMode = false, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]",
- ModuleDefinitionName = "Oqtane.Modules.Admin.Profile, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "User Profile", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client" });
+ SiteTemplate.Add(new PageTemplate { Name = "Home", Parent = "", Path = "", Order = 1, Icon = "home", IsNavigation = true, EditMode = false, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", PageTemplateModules = new List {
+ new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"All Users;Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Welcome To Oqtane", Pane = "top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client",
+ Content = "
Oqtane is an open source modular application framework built from the ground up using modern .NET Core technology. It leverages the revolutionary new Blazor component model to create a fully dynamic web development experience which can be executed on a client or server. Whether you are looking for a platform to accelerate your web development efforts, or simply interested in exploring the anatomy of a large-scale Blazor application, Oqtane provides a solid foundation based on proven enterprise architectural principles.
Blazor is a single-page app framework that lets you build interactive web applications using C# instead of JavaScript. Client-side Blazor relies on WebAssembly, an open web standard that does not require plugins or code transpilation in order to run natively in a web browser. Server-side Blazor uses SignalR to host your application on a web server and provide a responsive and robust debugging experience. Blazor applications works in all modern web browsers, including mobile browsers.
" +
+ "
Blazor is a feature ofASP.NET Core 3.0, the popular cross platform web development framework from Microsoft that extends the .NET developer platform with tools and libraries for building web apps.