diff --git a/src/Yavsc.Abstract/FileSystem/AbstractFileSystemHelpers.cs b/src/Yavsc.Abstract/FileSystem/AbstractFileSystemHelpers.cs index f66e88fd..1acfa340 100644 --- a/src/Yavsc.Abstract/FileSystem/AbstractFileSystemHelpers.cs +++ b/src/Yavsc.Abstract/FileSystem/AbstractFileSystemHelpers.cs @@ -60,6 +60,12 @@ namespace Yavsc.Helpers UserDirectoryInfo di = new UserDirectoryInfo(UserFilesDirName, userName, subdir); return di; } + public static bool IsRegularFile(string userName, string subdir) + { + FileInfo fi = new FileInfo( Path.Combine(Path.Combine(UserFilesDirName, userName), subdir)); + return fi.Exists; + } + // Server side only supports POSIX file systems public const char RemoteDirectorySeparator = '/'; diff --git a/src/Yavsc.Abstract/FileSystem/FsOperationInfo.cs b/src/Yavsc.Abstract/FileSystem/FsOperationInfo.cs index 5a595a07..ba748fbd 100644 --- a/src/Yavsc.Abstract/FileSystem/FsOperationInfo.cs +++ b/src/Yavsc.Abstract/FileSystem/FsOperationInfo.cs @@ -1,7 +1,18 @@ namespace Yavsc.Helpers { + public enum ErrorCode { + NotFound, + InternalError, + DestExists, + InvalidRequest + } + public class FsOperationInfo { + public bool Done { get; set; } = false; - public string Error { get; set; } + + public ErrorCode ErrorCode { get; set; } + public string ErrorMessage { get; set; } + } } diff --git a/src/Yavsc/ApiControllers/Blogspot/FileSystemApiController.cs b/src/Yavsc/ApiControllers/Blogspot/FileSystemApiController.cs index e4f4e5cb..fb77b1e4 100644 --- a/src/Yavsc/ApiControllers/Blogspot/FileSystemApiController.cs +++ b/src/Yavsc/ApiControllers/Blogspot/FileSystemApiController.cs @@ -15,13 +15,14 @@ namespace Yavsc.ApiControllers using Yavsc.Models.FileSystem; using System.ComponentModel.DataAnnotations; using Yavsc.Attributes.Validation; + using System.IO; [Authorize,Route("api/fs")] - public class FileSystemApiController : Controller + public partial class FileSystemApiController : Controller { ApplicationDbContext dbContext; private IAuthorizationService AuthorizationService; - private ILogger logger; + private ILogger _logger; public FileSystemApiController(ApplicationDbContext context, IAuthorizationService authorizationService, @@ -30,7 +31,7 @@ namespace Yavsc.ApiControllers { AuthorizationService = authorizationService; dbContext = context; - logger = loggerFactory.CreateLogger(); + _logger = loggerFactory.CreateLogger(); } [HttpGet()] @@ -61,24 +62,24 @@ namespace Yavsc.ApiControllers pathex = ex; } if (pathex!=null) { - logger.LogError($"invalid sub path: '{subdir}'."); + _logger.LogError($"invalid sub path: '{subdir}'."); return HttpBadRequest(pathex); } - logger.LogInformation($"Receiving files, saved in '{destDir}' (specified as '{subdir}')."); + _logger.LogInformation($"Receiving files, saved in '{destDir}' (specified as '{subdir}')."); var uid = User.GetUserId(); var user = dbContext.Users.Single( u => u.Id == uid ); int i=0; - logger.LogInformation($"Receiving {Request.Form.Files.Count} files."); + _logger.LogInformation($"Receiving {Request.Form.Files.Count} files."); foreach (var f in Request.Form.Files) { var item = user.ReceiveUserFile(destDir, f); dbContext.SaveChanges(User.GetUserId()); received.Add(item); - logger.LogInformation($"Received '{item.FileName}'."); + _logger.LogInformation($"Received '{item.FileName}'."); if (item.QuotaOffensed) break; i++; @@ -100,42 +101,54 @@ namespace Yavsc.ApiControllers return Ok(len); } - [Route("/api/fsc/movefile")] + [HttpPost] + [Route("/api/fsc/mvftd")] [Authorize()] - public IActionResult MoveFile([ValidRemoteUserFilePath] string from, [ValidRemoteUserFilePath] string to) + public IActionResult MoveFile([FromBody] RenameFileQuery query) { if (!ModelState.IsValid) return new BadRequestObjectResult(ModelState); var uid = User.GetUserId(); var user = dbContext.Users.Single( u => u.Id == uid ); - var info = user.MoveUserFile(from, to); - if (!info.Done) - return new BadRequestObjectResult(info); + var info = user.MoveUserFileToDir(query.id, query.to); + if (!info.Done) return new BadRequestObjectResult(info); return Ok(); } - [HttpPatch] - [Route("/api/fsc/movedir")] + [HttpPost] + [Route("/api/fsc/mvf")] [Authorize()] - public IActionResult MoveDir([ValidRemoteUserFilePath] string from,[ValidRemoteUserFilePath] string to) + public IActionResult RenameFile([FromBody] RenameFileQuery query) { - if (!ModelState.IsValid) return new BadRequestObjectResult(ModelState); + if (!ModelState.IsValid) { + var idvr = new ValidRemoteUserFilePathAttribute(); + + return this.HttpBadRequest(new { id = idvr.IsValid(query.id), to = idvr.IsValid(query.to), errors = ModelState }); + } + _logger.LogInformation($"Valid move query: {query.id} => {query.to}"); var uid = User.GetUserId(); var user = dbContext.Users.Single( u => u.Id == uid ); try { - var result = user.MoveUserDir(from, to); - if (!result.Done) - return new BadRequestObjectResult(result); + if (Startup.UserFilesOptions.FileProvider.GetFileInfo(Path.Combine(user.UserName, query.id)).Exists) + { + var result = user.MoveUserFile(query.id, query.to); + if (!result.Done) return new BadRequestObjectResult(result); + } + else { + var result = user.MoveUserDir(query.id, query.to); + if (!result.Done) return new BadRequestObjectResult(result); + } } catch (Exception ex) { return new BadRequestObjectResult( new FsOperationInfo { Done = false, - Error = ex.Message + ErrorCode = ErrorCode.InternalError, + ErrorMessage = ex.Message }); } return Ok(); @@ -161,7 +174,8 @@ namespace Yavsc.ApiControllers return new BadRequestObjectResult( new FsOperationInfo { Done = false, - Error = ex.Message + ErrorCode = ErrorCode.InternalError, + ErrorMessage = ex.Message }); } return Ok(new { deleted=id }); diff --git a/src/Yavsc/ApiControllers/Blogspot/MoveFileQuery.cs b/src/Yavsc/ApiControllers/Blogspot/MoveFileQuery.cs new file mode 100644 index 00000000..c043fa35 --- /dev/null +++ b/src/Yavsc/ApiControllers/Blogspot/MoveFileQuery.cs @@ -0,0 +1,23 @@ +using Yavsc.Attributes.Validation; +namespace Yavsc.Models.FileSystem +{ + public class RenameFileQuery { + [ValidRemoteUserFilePath] + [YaStringLength(1, 512)] + public string id { get; set; } + + [YaStringLength(0, 512)] + [ValidRemoteUserFilePath] + public string to { get; set; } + } + public class MoveFileQuery { + [ValidRemoteUserFilePath] + [YaStringLength(1, 512)] + public string id { get; set; } + + [YaStringLength(0, 512)] + [ValidRemoteUserFilePath] + public string to { get; set; } + } + +} diff --git a/src/Yavsc/Helpers/FileSystemHelpers.cs b/src/Yavsc/Helpers/FileSystemHelpers.cs index cf0a9815..3d1f60d0 100644 --- a/src/Yavsc/Helpers/FileSystemHelpers.cs +++ b/src/Yavsc/Helpers/FileSystemHelpers.cs @@ -108,18 +108,18 @@ namespace Yavsc.Helpers { var root = Path.Combine(AbstractFileSystemHelpers.UserFilesDirName, user.UserName); if (string.IsNullOrEmpty(dirName)) - return new FsOperationInfo { Done = false, Error = "specify a directory or file name"} ; + return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "specify a directory or file name"} ; var di = new DirectoryInfo(Path.Combine(root, dirName)); if (!di.Exists) { var fi = new FileInfo(Path.Combine(root, dirName)); - if (!fi.Exists) return new FsOperationInfo { Done = false, Error = "non existent"} ; + if (!fi.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.NotFound, ErrorMessage = "non existent"} ; fi.Delete(); user.DiskUsage -= fi.Length; } else { if (di.GetDirectories().Length>0 || di.GetFiles().Length>0) - return new FsOperationInfo { Done = false, Error = "not eñpty"} ; + return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "dir is not empty, refusing to remove it"} ; di.Delete(); } return new FsOperationInfo { Done = true }; @@ -129,36 +129,49 @@ namespace Yavsc.Helpers { var root = Path.Combine(AbstractFileSystemHelpers.UserFilesDirName, user.UserName); if (string.IsNullOrEmpty(fromDirName)) - return new FsOperationInfo { Done = false, Error = "fromDirName: specify a dir name "} ; + return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest , ErrorMessage = "specify a dir name "} ; var di = new DirectoryInfo(Path.Combine(root, fromDirName)); - if (!di.Exists) return new FsOperationInfo { Done = false, Error = "fromDirName: non existent"} ; + if (!di.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.NotFound, ErrorMessage = "fromDirName: non existent"} ; - if (string.IsNullOrEmpty(toDirName)) - return new FsOperationInfo { Done = false, Error = "toDirName: specify a dir name to move"} ; - + if (string.IsNullOrEmpty(toDirName)) toDirName = "."; var destPath = Path.Combine(root, toDirName); - var fo = new FileInfo(destPath); - var dout = new DirectoryInfo(destPath); - if (fo.Exists) return new FsOperationInfo { Done = false, Error = "toDirName: yet a regular file" } ; + var fout = new FileInfo(destPath); + if (fout.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "destination is a regular file" } ; + var dout = new DirectoryInfo(destPath); if (dout.Exists) { - destPath = Path.Combine(destPath, fo.Name); + destPath = Path.Combine(destPath, dout.Name); } di.MoveTo(destPath); return new FsOperationInfo { Done = true }; } + public static FsOperationInfo MoveUserFileToDir(this ApplicationUser user, string fileNameFrom, string fileNameDest) + { + var root = Path.Combine(AbstractFileSystemHelpers.UserFilesDirName, user.UserName); + var fi = new FileInfo(Path.Combine(root, fileNameFrom)); + if (!fi.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.NotFound, ErrorMessage = "no file to move" } ; + string dest; + if (!string.IsNullOrEmpty(fileNameDest)) dest = Path.Combine(root, fileNameDest); + else dest = root; + var fo = new FileInfo(dest); + if (fo.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.DestExists , ErrorMessage = "destination file name is an existing file" } ; + var dout = new DirectoryInfo(dest); + if (!dout.Exists) dout.Create(); + fi.MoveTo(Path.Combine(dout.FullName, fi.Name)); + return new FsOperationInfo { Done = true }; + } public static FsOperationInfo MoveUserFile(this ApplicationUser user, string fileNameFrom, string fileNameDest) { var root = Path.Combine(AbstractFileSystemHelpers.UserFilesDirName, user.UserName); var fi = new FileInfo(Path.Combine(root, fileNameFrom)); - if (!fi.Exists) return new FsOperationInfo { Error = "no file to move" } ; + if (!fi.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.NotFound, ErrorMessage = "no file to move" } ; var fo = new FileInfo(Path.Combine(root, fileNameDest)); - if (fo.Exists) return new FsOperationInfo { Error = "destination file name is an existing file" } ; + if (fo.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.DestExists , ErrorMessage = "destination file name is an existing file" } ; fi.MoveTo(fo.FullName); return new FsOperationInfo { Done = true }; } diff --git a/src/Yavsc/wwwroot/js/str.js b/src/Yavsc/wwwroot/js/str.js deleted file mode 100644 index 3be1e1ec..00000000 --- a/src/Yavsc/wwwroot/js/str.js +++ /dev/null @@ -1,12 +0,0 @@ -var constraints = { audio: true, video: false } - -navigator.mediaDevices.getUserMedia(constraints) - .then(function(stream) { - /* use the stream */ - console.log("got stream!"); - console.log(stream) - }) - .catch(function(err) { - /* handle the error */ - console.log(err) - }); \ No newline at end of file diff --git a/src/Yavsc/wwwroot/js/yavsc-remote-fs.js b/src/Yavsc/wwwroot/js/yavsc-remote-fs.js index 5863f4f1..6fb278bf 100644 --- a/src/Yavsc/wwwroot/js/yavsc-remote-fs.js +++ b/src/Yavsc/wwwroot/js/yavsc-remote-fs.js @@ -3,134 +3,258 @@ if (typeof window.jQuery === 'undefined') { throw new Error('yavsc-remote-fs script requires jQuery'); } +if (typeof XMLHttpRequest === 'undefined') { + throw new Error('yavsc-remote-fs script requires XMLHttpRequest'); +} (function ($) { - $.widget('psc.yarfs', { - options: { - fsnurl: '/api/fs' - }, - root: null, - rmAlert: null, - flist: null, - selection: [], - dirBar: null, - openDir: function (sub) { - var _this = this; - this.root = sub; - var owner = this.element.data('owner'); - this.selection = []; - this.dirBar.empty(); - $('').click(function() { - _this.openDir(null); - }).appendTo(this.dirBar); - var npath = null; - - if (_this.root) { - var dnames = _this.root.split('/'); - $.each(dnames, function () { - var part = this; - if (npath == null) npath = part; - else npath = npath + '/' + part; - $('') + .click(function () { + _this.openDir(null); + }) + .appendTo(this.dirBar); + var npath = null - this.ftable.find('tr.fileentry').remove(); - var fsiourl = this.root ? '/api/fs/' + this.root : '/api/fs'; - $.get(fsiourl, function(data) { - $.each(data.SubDirectories, function () { - var item = this; - var spath = (_this.root) ? _this.root + '/' + item.Name : item.Name; - $('