Folder and file management service

This commit is contained in:
Shaun Walker
2020-02-11 14:25:38 -05:00
parent ee682516c3
commit 6a92c9f764
45 changed files with 1075 additions and 421 deletions

View File

@ -3,12 +3,16 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Oqtane.Infrastructure;
using Oqtane.Repository;
using Oqtane.Models;
using Oqtane.Shared;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Oqtane.Security;
using System.Linq;
namespace Oqtane.Controllers
{
@ -16,53 +20,163 @@ namespace Oqtane.Controllers
public class FileController : Controller
{
private readonly IWebHostEnvironment environment;
private readonly IFileRepository Files;
private readonly IFolderRepository Folders;
private readonly IUserPermissions UserPermissions;
private readonly ITenantResolver Tenants;
private readonly ILogManager logger;
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, ILogManager logger)
public FileController(IWebHostEnvironment environment, IFileRepository Files, IFolderRepository Folders, IUserPermissions UserPermissions, ITenantResolver Tenants, ILogManager logger)
{
this.environment = environment;
this.Files = Files;
this.Folders = Folders;
this.UserPermissions = UserPermissions;
this.Tenants = Tenants;
this.logger = logger;
}
// GET: api/<controller>?folder=x
[HttpGet]
public IEnumerable<string> Get(string folder)
public IEnumerable<Models.File> Get(string folder)
{
List<string> files = new List<string>();
folder = GetFolder(folder);
if (Directory.Exists(folder))
List<Models.File> files = new List<Models.File>();
int folderid;
if (int.TryParse(folder, out folderid))
{
foreach (string file in Directory.GetFiles(folder))
Folder Folder = Folders.GetFolder(folderid);
if (Folder != null && UserPermissions.IsAuthorized(User, "Browse", Folder.Permissions))
{
files.Add(Path.GetFileName(file));
files = Files.GetFiles(folderid).ToList();
}
}
else
{
if (User.IsInRole(Constants.HostRole))
{
folder = GetFolderPath(folder);
if (Directory.Exists(folder))
{
foreach (string file in Directory.GetFiles(folder))
{
files.Add(new Models.File { Name = Path.GetFileName(file), Extension = Path.GetExtension(file).Replace(".","") });
}
}
}
}
return files;
}
// GET api/<controller>/5
[HttpGet("{id}")]
public Models.File Get(int id)
{
return Files.GetFile(id);
}
// PUT api/<controller>/5
[HttpPut("{id}")]
[Authorize(Roles = Constants.RegisteredRole)]
public Models.File Put(int id, [FromBody] Models.File File)
{
if (ModelState.IsValid && UserPermissions.IsAuthorized(User, "Folder", File.Folder.FolderId, "Edit"))
{
File = Files.UpdateFile(File);
logger.Log(LogLevel.Information, this, LogFunction.Update, "File Updated {File}", File);
}
return File;
}
// DELETE api/<controller>/5
[HttpDelete("{id}")]
[Authorize(Roles = Constants.RegisteredRole)]
public void Delete(int id)
{
Models.File File = Files.GetFile(id);
if (UserPermissions.IsAuthorized(User, "Folder", File.Folder.FolderId, "Edit"))
{
Files.DeleteFile(id);
string filepath = Path.Combine(GetFolderPath(File.Folder) + File.Name);
if (System.IO.File.Exists(filepath))
{
System.IO.File.Delete(filepath);
}
logger.Log(LogLevel.Information, this, LogFunction.Delete, "File Deleted {File}", File);
}
}
// GET api/<controller>/upload?url=x&folderid=y
[HttpGet("upload")]
public Models.File UploadFile(string url, string folderid)
{
Models.File file = null;
Folder folder = Folders.GetFolder(int.Parse(folderid));
if (folder != null && UserPermissions.IsAuthorized(User, "Edit", folder.Permissions))
{
string folderpath = GetFolderPath(folder);
CreateDirectory(folderpath);
string filename = url.Substring(url.LastIndexOf("/") + 1);
try
{
var client = new System.Net.WebClient();
client.DownloadFile(url, folderpath + filename);
FileInfo fileinfo = new FileInfo(folderpath + filename);
file = Files.AddFile(new Models.File { Name = filename, FolderId = folder.FolderId, Extension = fileinfo.Extension.Replace(".",""), Size = (int)fileinfo.Length });
}
catch
{
logger.Log(LogLevel.Error, this, LogFunction.Create, "File Could Not Be Downloaded From Url {Url}", url);
}
}
return file;
}
// POST api/<controller>/upload
[HttpPost("upload")]
[Authorize(Roles = Constants.AdminRole)]
public async Task UploadFile(string folder, IFormFile file)
{
if (file.Length > 0)
{
folder = GetFolder(folder);
if (!Directory.Exists(folder))
string folderpath = "";
int folderid = -1;
if (int.TryParse(folder, out folderid))
{
Directory.CreateDirectory(folder);
Folder Folder = Folders.GetFolder(folderid);
if (Folder != null && UserPermissions.IsAuthorized(User, "Edit", Folder.Permissions))
{
folderpath = GetFolderPath(Folder);
}
}
using (var stream = new FileStream(Path.Combine(folder, file.FileName), FileMode.Create))
else
{
await file.CopyToAsync(stream);
if (User.IsInRole(Constants.HostRole))
{
folderpath = GetFolderPath(folder);
}
}
if (folderpath != "")
{
CreateDirectory(folderpath);
using (var stream = new FileStream(Path.Combine(folderpath, file.FileName), FileMode.Create))
{
await file.CopyToAsync(stream);
}
string upload = await MergeFile(folderpath, file.FileName);
if (upload != "" && folderid != -1)
{
FileInfo fileinfo = new FileInfo(folderpath + upload);
Files.AddFile(new Models.File { Name = upload, FolderId = folderid, Extension = fileinfo.Extension.Replace(".", ""), Size = (int)fileinfo.Length });
}
}
await MergeFile(folder, file.FileName);
}
}
private async Task MergeFile(string folder, string filename)
private async Task<string> MergeFile(string folder, string filename)
{
string merged = "";
// parse the filename which is in the format of filename.ext.part_x_y
string token = ".part_";
string parts = Path.GetExtension(filename).Replace(token, ""); // returns "x_y"
@ -112,6 +226,7 @@ namespace Oqtane.Controllers
System.IO.File.Move(Path.Combine(folder, filename + ".tmp"), Path.Combine(folder, filename));
logger.Log(LogLevel.Information, this, LogFunction.Create, "File Uploaded {File}", Path.Combine(folder, filename));
}
merged = filename;
}
}
@ -125,6 +240,8 @@ namespace Oqtane.Controllers
System.IO.File.Delete(filepart);
}
}
return merged;
}
private bool CanAccessFiles(string[] files)
@ -164,24 +281,47 @@ namespace Oqtane.Controllers
return canaccess;
}
// DELETE api/<controller>/?folder=x&file=y
[HttpDelete]
[Authorize(Roles = Constants.AdminRole)]
public void Delete(string folder, string file)
// GET api/<controller>/download/5
[HttpGet("download/{id}")]
public IActionResult Download(int id)
{
file = Path.Combine(GetFolder(folder) + file);
if (System.IO.File.Exists(file))
Models.File file = Files.GetFile(id);
if (file != null && UserPermissions.IsAuthorized(User, "View", file.Folder.Permissions))
{
System.IO.File.Delete(file);
logger.Log(LogLevel.Information, this, LogFunction.Delete, "File Deleted {File}", file);
byte[] filebytes = System.IO.File.ReadAllBytes(GetFolderPath(file.Folder) + file.Name);
return File(filebytes, "application/octet-stream", file.Name);
}
else
{
return NotFound();
}
}
private string GetFolder(string folder)
private string GetFolderPath(Folder folder)
{
return environment.ContentRootPath + "\\Content\\Tenants\\" + Tenants.GetTenant().TenantId.ToString() + "\\Sites\\" + folder.SiteId.ToString() + "\\" + folder.Path;
}
private string GetFolderPath(string folder)
{
folder = folder.Replace("/", "\\");
if (folder.StartsWith("\\")) folder = folder.Substring(1);
return Path.Combine(environment.WebRootPath, folder);
}
private void CreateDirectory(string folderpath)
{
if (!Directory.Exists(folderpath))
{
string path = "";
string[] folders = folderpath.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string folder in folders)
{
path += folder + "\\";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
}
}
}
}

View File

@ -52,6 +52,12 @@ namespace Oqtane.Controllers
{
if (ModelState.IsValid && UserPermissions.IsAuthorized(User, "Edit", Folder.Permissions))
{
Folder.Path = "";
if (string.IsNullOrEmpty(Folder.Path) && Folder.ParentId != null)
{
Folder parent = Folders.GetFolder(Folder.ParentId.Value);
Folder.Path = parent.Path + Folder.Name + "\\";
}
Folder = Folders.AddFolder(Folder);
logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Added {Folder}", Folder);
}
@ -65,6 +71,12 @@ namespace Oqtane.Controllers
{
if (ModelState.IsValid && UserPermissions.IsAuthorized(User, "Folder", Folder.FolderId, "Edit"))
{
Folder.Path = "";
if (string.IsNullOrEmpty(Folder.Path) && Folder.ParentId != null)
{
Folder parent = Folders.GetFolder(Folder.ParentId.Value);
Folder.Path = parent.Path + Folder.Name + "\\";
}
Folder = Folders.UpdateFolder(Folder);
logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Updated {Folder}", Folder);
}

View File

@ -62,11 +62,6 @@ namespace Oqtane.Controllers
if (authorized)
{
Site = Sites.AddSite(Site);
string folder = environment.WebRootPath + "\\Tenants\\" + Tenants.GetTenant().TenantId.ToString() + "\\Sites\\" + Site.SiteId.ToString();
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
logger.Log(LogLevel.Information, this, LogFunction.Create, "Site Added {Site}", Site);
}
}

View File

@ -26,9 +26,10 @@ namespace Oqtane.Controllers
private readonly SignInManager<IdentityUser> IdentitySignInManager;
private readonly ITenantResolver Tenants;
private readonly INotificationRepository Notifications;
private readonly IFolderRepository Folders;
private readonly ILogManager logger;
public UserController(IUserRepository Users, IRoleRepository Roles, IUserRoleRepository UserRoles, UserManager<IdentityUser> IdentityUserManager, SignInManager<IdentityUser> IdentitySignInManager, ITenantResolver Tenants, INotificationRepository Notifications, ILogManager logger)
public UserController(IUserRepository Users, IRoleRepository Roles, IUserRoleRepository UserRoles, UserManager<IdentityUser> IdentityUserManager, SignInManager<IdentityUser> IdentitySignInManager, ITenantResolver Tenants, INotificationRepository Notifications, IFolderRepository Folders, ILogManager logger)
{
this.Users = Users;
this.Roles = Roles;
@ -36,12 +37,14 @@ namespace Oqtane.Controllers
this.IdentityUserManager = IdentityUserManager;
this.IdentitySignInManager = IdentitySignInManager;
this.Tenants = Tenants;
this.Folders = Folders;
this.Notifications = Notifications;
this.logger = logger;
}
// GET: api/<controller>?siteid=x
[HttpGet]
[Authorize(Roles = Constants.AdminRole)]
public IEnumerable<User> Get()
{
return Users.GetUsers();
@ -98,6 +101,8 @@ namespace Oqtane.Controllers
var result = await IdentityUserManager.CreateAsync(identityuser, User.Password);
if (result.Succeeded)
{
User.LastLoginOn = null;
User.LastIPAddress = "";
user = Users.AddUser(User);
if (!verified)
{
@ -128,6 +133,14 @@ namespace Oqtane.Controllers
userrole.ExpiryDate = null;
UserRoles.AddUserRole(userrole);
}
// add folder for user
Folder folder = Folders.GetFolder(User.SiteId, "Users\\");
if (folder != null)
{
Folders.AddFolder(new Folder { SiteId = folder.SiteId, ParentId = folder.FolderId, Name = "My Folder", Path = folder.Path + user.UserId.ToString() + "\\", Order = 1, IsSystem = true,
Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"[" + user.UserId.ToString() + "]\"},{\"PermissionName\":\"View\",\"Permissions\":\"All Users\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"[" + user.UserId.ToString() + "]\"}]" });
}
}
}
else
@ -222,6 +235,9 @@ namespace Oqtane.Controllers
if (identityuser.EmailConfirmed)
{
user.IsAuthenticated = true;
user.LastLoginOn = DateTime.Now;
user.LastIPAddress = HttpContext.Connection.RemoteIpAddress.ToString();
Users.UpdateUser(user);
logger.Log(LogLevel.Information, this, LogFunction.Security, "User Login Successful {Username}", User.Username);
if (SetCookie)
{