diff --git a/Oqtane.Client/Modules/Admin/Files/Add.razor b/Oqtane.Client/Modules/Admin/Files/Add.razor
new file mode 100644
index 00000000..04fc81ea
--- /dev/null
+++ b/Oqtane.Client/Modules/Admin/Files/Add.razor
@@ -0,0 +1,51 @@
+@namespace Oqtane.Modules.Admin.Files
+@inherits ModuleBase
+@inject NavigationManager NavigationManager
+@inject IFileService FileService
+
+
+
+Cancel
+
+
+@code {
+ public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
+
+ FileUpload fileupload;
+
+ private async Task UploadFile()
+ {
+ string[] files = await fileupload.GetFiles();
+ if (files.Length > 0)
+ {
+ try
+ {
+ if (await FileService.UploadFilesAsync(PageState.Site.SiteRootPath, files, ""))
+ {
+ ModuleInstance.AddModuleMessage("Files Uploaded Successfully", MessageType.Success);
+ }
+ else
+ {
+ ModuleInstance.AddModuleMessage("Upload Failed", MessageType.Error);
+ }
+ }
+ catch (Exception ex)
+ {
+ ModuleInstance.AddModuleMessage("Upload Failed. " + ex.Message, MessageType.Error);
+ }
+ }
+ else
+ {
+ ModuleInstance.AddModuleMessage("You Must Select Some Files To Upload", MessageType.Warning);
+ }
+ }
+}
diff --git a/Oqtane.Client/Modules/Admin/Files/Index.razor b/Oqtane.Client/Modules/Admin/Files/Index.razor
new file mode 100644
index 00000000..5f94d0ac
--- /dev/null
+++ b/Oqtane.Client/Modules/Admin/Files/Index.razor
@@ -0,0 +1,44 @@
+@namespace Oqtane.Modules.Admin.Files
+@inherits ModuleBase
+@inject NavigationManager NavigationManager
+@inject IFileService FileService
+
+@if (Files == null)
+{
+ Loading...
+}
+else
+{
+
+
+
+
+
+ @context |
+
+
+ |
+
+
+}
+
+@code {
+ public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
+
+ List Files;
+
+ protected override async Task OnParametersSetAsync()
+ {
+ Files = await FileService.GetFilesAsync(PageState.Site.SiteRootPath);
+ }
+
+ private async Task DeleteFile(string filename)
+ {
+ await FileService.DeleteFileAsync(PageState.Site.SiteRootPath, filename);
+ Files = await FileService.GetFilesAsync(PageState.Site.SiteRootPath);
+ ModuleInstance.AddModuleMessage("File Deleted", MessageType.Success);
+ }
+}
\ No newline at end of file
diff --git a/Oqtane.Client/Modules/Admin/Users/Delete.razor b/Oqtane.Client/Modules/Admin/Users/Delete.razor
index 8e68735a..19705668 100644
--- a/Oqtane.Client/Modules/Admin/Users/Delete.razor
+++ b/Oqtane.Client/Modules/Admin/Users/Delete.razor
@@ -58,7 +58,6 @@
string username = "";
string email = "";
string displayname = "";
- string category = "";
string createdby;
DateTime createdon;
string modifiedby;
diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor
index 3e3c30b0..45ddf82e 100644
--- a/Oqtane.Client/Modules/Controls/ActionLink.razor
+++ b/Oqtane.Client/Modules/Controls/ActionLink.razor
@@ -88,5 +88,9 @@
classname = "btn btn-warning"; // alert developer of missing module comtrol
}
}
+ else
+ {
+ authorized = false;
+ }
}
}
diff --git a/Oqtane.Client/Services/FileService.cs b/Oqtane.Client/Services/FileService.cs
index eff93274..296764d1 100644
--- a/Oqtane.Client/Services/FileService.cs
+++ b/Oqtane.Client/Services/FileService.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
@@ -37,19 +38,34 @@ namespace Oqtane.Services
bool success = false;
var interop = new Interop(jsRuntime);
await interop.UploadFiles(apiurl + "/upload", Folder, FileUploadName);
- List files = await GetFilesAsync(Folder);
- if (files.Count > 0)
+
+ // uploading files is asynchronous so we need to wait for the upload to complete
+ int attempts = 0;
+ while (attempts < 5 && success == false)
{
- success = true;
- foreach (string file in Files)
+ Thread.Sleep(2000); // wait 2 seconds
+
+ List files = await GetFilesAsync(Folder);
+ if (files.Count > 0)
{
- if (!files.Contains(file))
+ success = true;
+ foreach (string file in Files)
{
- success = false;
+ if (!files.Contains(file))
+ {
+ success = false;
+ }
}
}
+ attempts += 1;
}
+
return success;
}
+
+ public async Task DeleteFileAsync(string Folder, string File)
+ {
+ await http.DeleteAsync(apiurl + "?folder=" + Folder + "&file=" + File);
+ }
}
}
diff --git a/Oqtane.Client/Services/Interfaces/IFileService.cs b/Oqtane.Client/Services/Interfaces/IFileService.cs
index 06bb5828..1cff111c 100644
--- a/Oqtane.Client/Services/Interfaces/IFileService.cs
+++ b/Oqtane.Client/Services/Interfaces/IFileService.cs
@@ -8,5 +8,6 @@ namespace Oqtane.Services
{
Task> GetFilesAsync(string Folder);
Task UploadFilesAsync(string Folder, string[] Files, string FileUploadName);
+ Task DeleteFileAsync(string Folder, string File);
}
}
diff --git a/Oqtane.Client/Themes/Controls/Logo.razor b/Oqtane.Client/Themes/Controls/Logo.razor
index 616569fb..192a0f66 100644
--- a/Oqtane.Client/Themes/Controls/Logo.razor
+++ b/Oqtane.Client/Themes/Controls/Logo.razor
@@ -6,12 +6,11 @@
@code {
string logo = "";
- protected override Task OnParametersSetAsync()
+ protected override void OnParametersSet()
{
if (PageState.Site.Logo != "")
{
- logo = "
";
+ logo = "
";
}
- return Task.CompletedTask;
}
}
\ No newline at end of file
diff --git a/Oqtane.Server/Controllers/FileController.cs b/Oqtane.Server/Controllers/FileController.cs
index 43057e6f..36e27102 100644
--- a/Oqtane.Server/Controllers/FileController.cs
+++ b/Oqtane.Server/Controllers/FileController.cs
@@ -1,6 +1,8 @@
-using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Oqtane.Shared;
using System;
using System.Collections.Generic;
using System.IO;
@@ -12,7 +14,8 @@ namespace Oqtane.Controllers
public class FileController : Controller
{
private readonly IWebHostEnvironment environment;
-
+ private readonly string WhiteList = "jpg,jpeg,jpe,gif,bmp,png,mov,wmv,avi,mp4,mp3,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,nupkg";
+
public FileController(IWebHostEnvironment environment)
{
this.environment = environment;
@@ -23,14 +26,12 @@ namespace Oqtane.Controllers
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);
+ folder = GetFolder(folder);
if (Directory.Exists(folder))
{
- foreach(string file in Directory.GetFiles(folder))
+ foreach (string file in Directory.GetFiles(folder))
{
- files.Add(file);
+ files.Add(Path.GetFileName(file));
}
}
return files;
@@ -38,16 +39,12 @@ namespace Oqtane.Controllers
// POST api//upload
[HttpPost("upload")]
+ [Authorize(Roles = Constants.AdminRole)]
public async Task UploadFile(string folder, IFormFile file)
{
if (file.Length > 0)
{
- if (!folder.Contains(":\\"))
- {
- folder = folder.Replace("/", "\\");
- if (folder.StartsWith("\\")) folder = folder.Substring(1);
- folder = Path.Combine(environment.WebRootPath, folder);
- }
+ folder = GetFolder(folder);
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
@@ -85,7 +82,7 @@ namespace Oqtane.Controllers
await chunk.CopyToAsync(stream);
}
}
- catch
+ catch
{
success = false;
}
@@ -99,6 +96,13 @@ namespace Oqtane.Controllers
{
System.IO.File.Delete(filepart);
}
+
+ // check for allowable file extensions
+ if (!WhiteList.Contains(Path.GetExtension(filename).Replace(".", "")))
+ {
+ System.IO.File.Delete(Path.Combine(folder, filename));
+ success = false;
+ }
}
}
@@ -113,5 +117,24 @@ namespace Oqtane.Controllers
}
}
}
+
+ // DELETE api//?folder=x&file=y
+ [HttpDelete]
+ [Authorize(Roles = Constants.AdminRole)]
+ public void Delete(string folder, string file)
+ {
+ file = Path.Combine(GetFolder(folder) + file);
+ if (System.IO.File.Exists(file))
+ {
+ System.IO.File.Delete(file);
+ }
+ }
+
+ private string GetFolder(string folder)
+ {
+ folder = folder.Replace("/", "\\");
+ if (folder.StartsWith("\\")) folder = folder.Substring(1);
+ return Path.Combine(environment.WebRootPath, folder);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs
index 235b5541..d649b666 100644
--- a/Oqtane.Server/Repository/SiteRepository.cs
+++ b/Oqtane.Server/Repository/SiteRepository.cs
@@ -59,11 +59,8 @@ namespace Oqtane.Repository
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\"}]", PageTemplateModules = new List {
new PageTemplateModule { 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", Content = "" }
}});
- 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\"}]", PageTemplateModules = new List {
- new PageTemplateModule { 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", Content = "" }
- }});
- 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\"}]", PageTemplateModules = new List {
- new PageTemplateModule { 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", Content = "" }
+ SiteTemplate.Add(new PageTemplate { Name = "File Management", Parent = "Admin", Path = "admin/files", Order = 1, Icon = "file", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", PageTemplateModules = new List {
+ new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.Admin.Files, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "File Management", Pane = "Top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client", Content = "" }
}});
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\"}]", PageTemplateModules = new List {
new PageTemplateModule { 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", Content = "" }
@@ -74,6 +71,12 @@ namespace Oqtane.Repository
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\"}]", PageTemplateModules = new List {
new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.Admin.Tenants, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Tenant Management", Pane = "Top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client", Content = "" }
}});
+ 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\"}]", PageTemplateModules = new List {
+ new PageTemplateModule { 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", Content = "" }
+ }});
+ 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\"}]", PageTemplateModules = new List {
+ new PageTemplateModule { 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", Content = "" }
+ }});
SiteTemplate.Add(new PageTemplate { Name = "Upgrade Service", Parent = "Admin", Path = "admin/upgrade", Order = 1, Icon = "aperture", IsNavigation = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", PageTemplateModules = new List {
new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.Admin.Upgrade, Oqtane.Client", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Title = "Upgrade Service", Pane = "Top", ContainerType = "Oqtane.Themes.Theme2.Container2, Oqtane.Client", Content = "" }
}});
diff --git a/Oqtane.Shared/Models/Alias.cs b/Oqtane.Shared/Models/Alias.cs
index 92442601..072b7e12 100644
--- a/Oqtane.Shared/Models/Alias.cs
+++ b/Oqtane.Shared/Models/Alias.cs
@@ -57,41 +57,5 @@ namespace Oqtane.Models
}
}
}
-
- [NotMapped]
- public string TenantRootPath
- {
- get
- {
- return "Tenants/" + TenantId.ToString() + "/";
- }
- }
-
- [NotMapped]
- public string TenantRootUrl
- {
- get
- {
- return BaseUrl + "/Tenants/" + TenantId.ToString() + "/";
- }
- }
-
- [NotMapped]
- public string SiteRootPath
- {
- get
- {
- return "Tenants/" + TenantId.ToString() + "/Sites/" + SiteId.ToString() + "/";
- }
- }
-
- [NotMapped]
- public string SiteRootUrl
- {
- get
- {
- return BaseUrl + "/Tenants/" + TenantId.ToString() + "/Sites/" + SiteId.ToString() + "/";
- }
- }
}
}
diff --git a/Oqtane.Shared/Models/Site.cs b/Oqtane.Shared/Models/Site.cs
index cf8d5751..81f05244 100644
--- a/Oqtane.Shared/Models/Site.cs
+++ b/Oqtane.Shared/Models/Site.cs
@@ -1,4 +1,5 @@
using System;
+using System.ComponentModel.DataAnnotations.Schema;
namespace Oqtane.Models
{
@@ -19,5 +20,23 @@ namespace Oqtane.Models
public string DeletedBy { get; set; }
public DateTime? DeletedOn { get; set; }
public bool IsDeleted { get; set; }
+
+ [NotMapped]
+ public string TenantRootPath
+ {
+ get
+ {
+ return "Tenants/" + TenantId.ToString() + "/";
+ }
+ }
+
+ [NotMapped]
+ public string SiteRootPath
+ {
+ get
+ {
+ return "Tenants/" + TenantId.ToString() + "/Sites/" + SiteId.ToString() + "/";
+ }
+ }
}
}