validate folder names, handle missing files more gracefully

This commit is contained in:
Shaun Walker 2020-05-12 13:24:51 -04:00
parent c83496d814
commit 6f3fe8d933
7 changed files with 99 additions and 30 deletions

View File

@ -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);
} }

View File

@ -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
@ -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");
} }
} }

View File

@ -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()));
}
} }
} }

View File

@ -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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -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) {

View File

@ -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";
} }
} }