Files: DI
This commit is contained in:
parent
96687f4fa6
commit
e0fc7e6f39
@ -27,20 +27,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.MessagingSystem;
|
||||
using ASC.Web.Files.Helpers;
|
||||
using ASC.Web.Files.Resources;
|
||||
using ASC.Web.Files.Utils;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
class FileDeleteOperation : FileOperation
|
||||
internal class FileDeleteOperationData : FileOperationData
|
||||
{
|
||||
public bool IgnoreException { get; }
|
||||
public bool Immediately { get; }
|
||||
public Dictionary<string, string> Headers { get; }
|
||||
|
||||
public FileDeleteOperationData(List<object> folders, List<object> files, Tenant tenant,
|
||||
bool holdResult = true, bool ignoreException = false, bool immediately = false, Dictionary<string, string> headers = null)
|
||||
: base(folders, files, tenant, holdResult)
|
||||
{
|
||||
IgnoreException = ignoreException;
|
||||
Immediately = immediately;
|
||||
Headers = headers;
|
||||
}
|
||||
}
|
||||
|
||||
class FileDeleteOperation : FileOperation<FileDeleteOperationData>
|
||||
{
|
||||
private object _trashId;
|
||||
private readonly bool _ignoreException;
|
||||
private readonly bool _immediately;
|
||||
private readonly Dictionary<string, string> _headers;
|
||||
private bool _ignoreException;
|
||||
private bool _immediately;
|
||||
private Dictionary<string, string> _headers;
|
||||
|
||||
public override FileOperationType OperationType
|
||||
{
|
||||
@ -48,18 +68,19 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
|
||||
|
||||
public FileDeleteOperation(List<object> folders, List<object> files, bool ignoreException = false, bool holdResult = true, bool immediately = false, Dictionary<string, string> headers = null)
|
||||
: base(folders, files, holdResult)
|
||||
public FileDeleteOperation(IServiceProvider serviceProvider)
|
||||
: base(serviceProvider)
|
||||
{
|
||||
_ignoreException = ignoreException;
|
||||
_immediately = immediately;
|
||||
_headers = headers;
|
||||
}
|
||||
|
||||
|
||||
protected override void Do()
|
||||
protected override void Do(FileDeleteOperationData fileOperationData, IServiceScope scope)
|
||||
{
|
||||
_trashId = FolderDao.GetFolderIDTrash(true);
|
||||
_ignoreException = fileOperationData.IgnoreException;
|
||||
_immediately = fileOperationData.Immediately;
|
||||
_headers = fileOperationData.Headers;
|
||||
|
||||
Folder root = null;
|
||||
if (0 < Folders.Count)
|
||||
{
|
||||
@ -71,15 +92,18 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
if (root != null)
|
||||
{
|
||||
Status += string.Format("folder_{0}{1}", root.ID, SPLIT_CHAR);
|
||||
Status += string.Format("folder_{0}{1}", root.ID, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
|
||||
DeleteFiles(Files);
|
||||
DeleteFolders(Folders);
|
||||
DeleteFiles(Files, scope);
|
||||
DeleteFolders(Folders, scope);
|
||||
}
|
||||
|
||||
private void DeleteFolders(IEnumerable<object> folderIds)
|
||||
private void DeleteFolders(IEnumerable<object> folderIds, IServiceScope scope)
|
||||
{
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
var filesMessageService = scope.ServiceProvider.GetService<FilesMessageService>();
|
||||
|
||||
foreach (var folderId in folderIds)
|
||||
{
|
||||
CancellationToken.ThrowIfCancellationRequested();
|
||||
@ -104,13 +128,13 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
canCalculate = FolderDao.CanCalculateSubitems(folderId) ? null : folderId;
|
||||
|
||||
FileMarker.RemoveMarkAsNewForAll(folder);
|
||||
fileMarker.RemoveMarkAsNewForAll(folder);
|
||||
if (folder.ProviderEntry && folder.ID.Equals(folder.RootFolderId))
|
||||
{
|
||||
if (ProviderDao != null)
|
||||
{
|
||||
ProviderDao.RemoveProviderInfo(folder.ProviderId);
|
||||
FilesMessageService.Send(folder, _headers, MessageAction.ThirdPartyDeleted, folder.ID.ToString(), folder.ProviderKey);
|
||||
filesMessageService.Send(folder, _headers, MessageAction.ThirdPartyDeleted, folder.ID.ToString(), folder.ProviderKey);
|
||||
}
|
||||
|
||||
ProcessedFolder(folderId);
|
||||
@ -120,13 +144,13 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
var immediately = _immediately || !FolderDao.UseTrashForRemove(folder);
|
||||
if (immediately && FolderDao.UseRecursiveOperation(folder.ID, null))
|
||||
{
|
||||
DeleteFiles(FileDao.GetFiles(folder.ID));
|
||||
DeleteFolders(FolderDao.GetFolders(folder.ID).Select(f => f.ID).ToList());
|
||||
DeleteFiles(FileDao.GetFiles(folder.ID), scope);
|
||||
DeleteFolders(FolderDao.GetFolders(folder.ID).Select(f => f.ID).ToList(), scope);
|
||||
|
||||
if (FolderDao.IsEmpty(folder.ID))
|
||||
{
|
||||
FolderDao.DeleteFolder(folder.ID);
|
||||
FilesMessageService.Send(folder, _headers, MessageAction.FolderDeleted, folder.Title);
|
||||
filesMessageService.Send(folder, _headers, MessageAction.FolderDeleted, folder.Title);
|
||||
|
||||
ProcessedFolder(folderId);
|
||||
}
|
||||
@ -134,8 +158,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
else
|
||||
{
|
||||
var files = FileDao.GetFiles(folder.ID, new OrderBy(SortedByType.AZ, true), FilterType.FilesOnly, false, Guid.Empty, string.Empty, false, true);
|
||||
string tmpError;
|
||||
if (!_ignoreException && WithError(files, true, out tmpError))
|
||||
if (!_ignoreException && WithError(scope, files, true, out var tmpError))
|
||||
{
|
||||
Error = tmpError;
|
||||
}
|
||||
@ -144,12 +167,12 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
if (immediately)
|
||||
{
|
||||
FolderDao.DeleteFolder(folder.ID);
|
||||
FilesMessageService.Send(folder, _headers, MessageAction.FolderDeleted, folder.Title);
|
||||
filesMessageService.Send(folder, _headers, MessageAction.FolderDeleted, folder.Title);
|
||||
}
|
||||
else
|
||||
{
|
||||
FolderDao.MoveFolder(folder.ID, _trashId, CancellationToken);
|
||||
FilesMessageService.Send(folder, _headers, MessageAction.FolderMovedToTrash, folder.Title);
|
||||
filesMessageService.Send(folder, _headers, MessageAction.FolderMovedToTrash, folder.Title);
|
||||
}
|
||||
|
||||
ProcessedFolder(folderId);
|
||||
@ -161,36 +184,38 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteFiles(IEnumerable<object> fileIds)
|
||||
private void DeleteFiles(IEnumerable<object> fileIds, IServiceScope scope)
|
||||
{
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
var filesMessageService = scope.ServiceProvider.GetService<FilesMessageService>();
|
||||
|
||||
foreach (var fileId in fileIds)
|
||||
{
|
||||
CancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var file = FileDao.GetFile(fileId);
|
||||
string tmpError;
|
||||
if (file == null)
|
||||
{
|
||||
Error = FilesCommonResource.ErrorMassage_FileNotFound;
|
||||
}
|
||||
else if (!_ignoreException && WithError(new[] { file }, false, out tmpError))
|
||||
else if (!_ignoreException && WithError(scope, new[] { file }, false, out var tmpError))
|
||||
{
|
||||
Error = tmpError;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileMarker.RemoveMarkAsNewForAll(file);
|
||||
fileMarker.RemoveMarkAsNewForAll(file);
|
||||
if (!_immediately && FileDao.UseTrashForRemove(file))
|
||||
{
|
||||
FileDao.MoveFile(file.ID, _trashId);
|
||||
FilesMessageService.Send(file, _headers, MessageAction.FileMovedToTrash, file.Title);
|
||||
filesMessageService.Send(file, _headers, MessageAction.FileMovedToTrash, file.Title);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
FileDao.DeleteFile(file.ID);
|
||||
FilesMessageService.Send(file, _headers, MessageAction.FileDeleted, file.Title);
|
||||
filesMessageService.Send(file, _headers, MessageAction.FileDeleted, file.Title);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -204,8 +229,10 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
}
|
||||
|
||||
private bool WithError(IEnumerable<File> files, bool folder, out string error)
|
||||
private bool WithError(IServiceScope scope, IEnumerable<File> files, bool folder, out string error)
|
||||
{
|
||||
var entryManager = scope.ServiceProvider.GetService<EntryManager>();
|
||||
|
||||
error = null;
|
||||
foreach (var file in files)
|
||||
{
|
||||
@ -214,7 +241,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
error = FilesCommonResource.ErrorMassage_SecurityException_DeleteFile;
|
||||
return true;
|
||||
}
|
||||
if (EntryManager.FileLockedForMe(file.ID))
|
||||
if (entryManager.FileLockedForMe(file.ID))
|
||||
{
|
||||
error = FilesCommonResource.ErrorMassage_LockedFile;
|
||||
return true;
|
||||
|
@ -25,7 +25,16 @@
|
||||
|
||||
|
||||
extern alias ionic;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common.Security.Authentication;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Data.Storage;
|
||||
using ASC.Files.Core;
|
||||
using ASC.MessagingSystem;
|
||||
@ -35,20 +44,30 @@ using ASC.Web.Files.Helpers;
|
||||
using ASC.Web.Files.Resources;
|
||||
using ASC.Web.Files.Utils;
|
||||
using ASC.Web.Studio.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using File = ASC.Files.Core.File;
|
||||
|
||||
namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
class FileDownloadOperation : FileOperation
|
||||
internal class FileDownloadOperationData : FileOperationData
|
||||
{
|
||||
private readonly Dictionary<object, string> files;
|
||||
private readonly Dictionary<string, string> headers;
|
||||
public Dictionary<object, string> FilesDownload { get; }
|
||||
public Dictionary<string, string> Headers { get; }
|
||||
|
||||
public FileDownloadOperationData(Dictionary<object, string> folders, Dictionary<object, string> files, Tenant tenant, Dictionary<string, string> headers, bool holdResult = true)
|
||||
: base(folders.Select(f => f.Key).ToList(), files.Select(f => f.Key).ToList(), tenant, holdResult)
|
||||
{
|
||||
FilesDownload = files;
|
||||
Headers = headers;
|
||||
}
|
||||
}
|
||||
|
||||
class FileDownloadOperation : FileOperation<FileDownloadOperationData>
|
||||
{
|
||||
private Dictionary<object, string> files;
|
||||
private Dictionary<string, string> headers;
|
||||
|
||||
public override FileOperationType OperationType
|
||||
{
|
||||
@ -56,17 +75,18 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
|
||||
|
||||
public FileDownloadOperation(Dictionary<object, string> folders, Dictionary<object, string> files, Dictionary<string, string> headers)
|
||||
: base(folders.Select(f => f.Key).ToList(), files.Select(f => f.Key).ToList())
|
||||
public FileDownloadOperation(IServiceProvider serviceProvider)
|
||||
: base(serviceProvider)
|
||||
{
|
||||
this.files = files;
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
|
||||
protected override void Do()
|
||||
protected override void Do(FileDownloadOperationData fileDownloadOperationData, IServiceScope scope)
|
||||
{
|
||||
var entriesPathId = GetEntriesPathId();
|
||||
files = fileDownloadOperationData.FilesDownload;
|
||||
headers = fileDownloadOperationData.Headers;
|
||||
|
||||
var entriesPathId = GetEntriesPathId(scope);
|
||||
if (entriesPathId == null || entriesPathId.Count == 0)
|
||||
{
|
||||
if (0 < Files.Count)
|
||||
@ -74,29 +94,31 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
throw new DirectoryNotFoundException(FilesCommonResource.ErrorMassage_FolderNotFound);
|
||||
}
|
||||
|
||||
var globalStore = scope.ServiceProvider.GetService<GlobalStore>();
|
||||
var filesLinkUtility = scope.ServiceProvider.GetService<FilesLinkUtility>();
|
||||
|
||||
ReplaceLongPath(entriesPathId);
|
||||
|
||||
using (var stream = CompressToZip(entriesPathId))
|
||||
using var stream = CompressToZip(scope, entriesPathId);
|
||||
if (stream != null)
|
||||
{
|
||||
if (stream != null)
|
||||
{
|
||||
stream.Position = 0;
|
||||
const string fileName = FileConstant.DownloadTitle + ".zip";
|
||||
var store = Global.GetStore();
|
||||
store.Save(
|
||||
FileConstant.StorageDomainTmp,
|
||||
string.Format(@"{0}\{1}", ((IAccount)Thread.CurrentPrincipal.Identity).ID, fileName),
|
||||
stream,
|
||||
"application/zip",
|
||||
"attachment; filename=\"" + fileName + "\"");
|
||||
Status = string.Format("{0}?{1}=bulk", FilesLinkUtility.FileHandlerPath, FilesLinkUtility.Action);
|
||||
}
|
||||
stream.Position = 0;
|
||||
const string fileName = FileConstant.DownloadTitle + ".zip";
|
||||
var store = globalStore.GetStore();
|
||||
store.Save(
|
||||
FileConstant.StorageDomainTmp,
|
||||
string.Format(@"{0}\{1}", ((IAccount)Thread.CurrentPrincipal.Identity).ID, fileName),
|
||||
stream,
|
||||
"application/zip",
|
||||
"attachment; filename=\"" + fileName + "\"");
|
||||
Status = string.Format("{0}?{1}=bulk", filesLinkUtility.FileHandlerPath, FilesLinkUtility.Action);
|
||||
}
|
||||
}
|
||||
|
||||
private ItemNameValueCollection ExecPathFromFile(File file, string path)
|
||||
private ItemNameValueCollection ExecPathFromFile(IServiceScope scope, File file, string path)
|
||||
{
|
||||
FileMarker.RemoveMarkAsNew(file);
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
fileMarker.RemoveMarkAsNew(file);
|
||||
|
||||
var title = file.Title;
|
||||
|
||||
@ -116,28 +138,31 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
return entriesPathId;
|
||||
}
|
||||
|
||||
private ItemNameValueCollection GetEntriesPathId()
|
||||
private ItemNameValueCollection GetEntriesPathId(IServiceScope scope)
|
||||
{
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
var entriesPathId = new ItemNameValueCollection();
|
||||
if (0 < Files.Count)
|
||||
{
|
||||
var files = FileDao.GetFiles(Files.ToArray());
|
||||
files = FilesSecurity.FilterRead(files).ToList();
|
||||
files.ForEach(file => entriesPathId.Add(ExecPathFromFile(file, string.Empty)));
|
||||
files.ForEach(file => entriesPathId.Add(ExecPathFromFile(scope, file, string.Empty)));
|
||||
}
|
||||
if (0 < Folders.Count)
|
||||
{
|
||||
FilesSecurity.FilterRead(FolderDao.GetFolders(Files.ToArray())).ToList().Cast<FileEntry>().ToList()
|
||||
.ForEach(folder => FileMarker.RemoveMarkAsNew(folder));
|
||||
.ForEach(folder => fileMarker.RemoveMarkAsNew(folder));
|
||||
|
||||
var filesInFolder = GetFilesInFolders(Folders, string.Empty);
|
||||
var filesInFolder = GetFilesInFolders(scope, Folders, string.Empty);
|
||||
entriesPathId.Add(filesInFolder);
|
||||
}
|
||||
return entriesPathId;
|
||||
}
|
||||
|
||||
private ItemNameValueCollection GetFilesInFolders(IEnumerable<object> folderIds, string path)
|
||||
private ItemNameValueCollection GetFilesInFolders(IServiceScope scope, IEnumerable<object> folderIds, string path)
|
||||
{
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
|
||||
CancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var entriesPathId = new ItemNameValueCollection();
|
||||
@ -151,9 +176,9 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
|
||||
var files = FileDao.GetFiles(folder.ID, null, FilterType.None, false, Guid.Empty, string.Empty, true);
|
||||
files = FilesSecurity.FilterRead(files).ToList();
|
||||
files.ForEach(file => entriesPathId.Add(ExecPathFromFile(file, folderPath)));
|
||||
files.ForEach(file => entriesPathId.Add(ExecPathFromFile(scope, file, folderPath)));
|
||||
|
||||
FileMarker.RemoveMarkAsNew(folder);
|
||||
fileMarker.RemoveMarkAsNew(folder);
|
||||
|
||||
var nestedFolders = FolderDao.GetFolders(folder.ID);
|
||||
nestedFolders = FilesSecurity.FilterRead(nestedFolders).ToList();
|
||||
@ -162,14 +187,18 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
entriesPathId.Add(folderPath, string.Empty);
|
||||
}
|
||||
|
||||
var filesInFolder = GetFilesInFolders(nestedFolders.ConvertAll(f => f.ID), folderPath);
|
||||
var filesInFolder = GetFilesInFolders(scope, nestedFolders.ConvertAll(f => f.ID), folderPath);
|
||||
entriesPathId.Add(filesInFolder);
|
||||
}
|
||||
return entriesPathId;
|
||||
}
|
||||
|
||||
private Stream CompressToZip(ItemNameValueCollection entriesPathId)
|
||||
private Stream CompressToZip(IServiceScope scope, ItemNameValueCollection entriesPathId)
|
||||
{
|
||||
var setupInfo = scope.ServiceProvider.GetService<SetupInfo>();
|
||||
var fileConverter = scope.ServiceProvider.GetService<FileConverter>();
|
||||
var filesMessageService = scope.ServiceProvider.GetService<FilesMessageService>();
|
||||
|
||||
var stream = TempStream.Create();
|
||||
using (var zip = new ionic::Ionic.Zip.ZipOutputStream(stream, true))
|
||||
{
|
||||
@ -205,9 +234,9 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file.ContentLength > SetupInfo.AvailableFileSize)
|
||||
if (file.ContentLength > setupInfo.AvailableFileSize)
|
||||
{
|
||||
Error = string.Format(FilesCommonResource.ErrorMassage_FileSizeZip, FileSizeComment.FilesSizeToString(SetupInfo.AvailableFileSize));
|
||||
Error = string.Format(FilesCommonResource.ErrorMassage_FileSizeZip, FileSizeComment.FilesSizeToString(setupInfo.AvailableFileSize));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -241,29 +270,27 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
try
|
||||
{
|
||||
if (FileConverter.EnableConvert(file, convertToExt))
|
||||
if (fileConverter.EnableConvert(file, convertToExt))
|
||||
{
|
||||
//Take from converter
|
||||
using (var readStream = FileConverter.Exec(file, convertToExt))
|
||||
using (var readStream = fileConverter.Exec(file, convertToExt))
|
||||
{
|
||||
readStream.StreamCopyTo(zip);
|
||||
if (!string.IsNullOrEmpty(convertToExt))
|
||||
{
|
||||
FilesMessageService.Send(file, headers, MessageAction.FileDownloadedAs, file.Title, convertToExt);
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloadedAs, file.Title, convertToExt);
|
||||
}
|
||||
else
|
||||
{
|
||||
FilesMessageService.Send(file, headers, MessageAction.FileDownloaded, file.Title);
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloaded, file.Title);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var readStream = FileDao.GetFileStream(file))
|
||||
{
|
||||
readStream.StreamCopyTo(zip);
|
||||
FilesMessageService.Send(file, headers, MessageAction.FileDownloaded, file.Title);
|
||||
}
|
||||
using var readStream = FileDao.GetFileStream(file);
|
||||
readStream.StreamCopyTo(zip);
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloaded, file.Title);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -24,16 +24,28 @@
|
||||
*/
|
||||
|
||||
|
||||
using ASC.Common.Security.Authentication;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Web.Files.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common.Security.Authentication;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Web.Files.Utils;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
class FileMarkAsReadOperation : FileOperation
|
||||
class FileMarkAsReadOperationData : FileOperationData
|
||||
{
|
||||
public FileMarkAsReadOperationData(List<object> folders, List<object> files, Tenant tenant, bool holdResult = true) : base(folders, files, tenant, holdResult)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class FileMarkAsReadOperation : FileOperation<FileMarkAsReadOperationData>
|
||||
{
|
||||
public override FileOperationType OperationType
|
||||
{
|
||||
@ -41,8 +53,8 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
|
||||
|
||||
public FileMarkAsReadOperation(List<object> folders, List<object> files)
|
||||
: base(folders, files)
|
||||
public FileMarkAsReadOperation(IServiceProvider serviceProvider)
|
||||
: base(serviceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
@ -52,8 +64,9 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
return Files.Count + Folders.Count;
|
||||
}
|
||||
|
||||
protected override void Do()
|
||||
protected override void Do(FileMarkAsReadOperationData fileOperationData, IServiceScope scope)
|
||||
{
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
var entries = new List<FileEntry>();
|
||||
if (Folders.Any())
|
||||
{
|
||||
@ -67,7 +80,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
CancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
FileMarker.RemoveMarkAsNew(x, ((IAccount)Thread.CurrentPrincipal.Identity).ID);
|
||||
fileMarker.RemoveMarkAsNew(x, ((IAccount)Thread.CurrentPrincipal.Identity).ID);
|
||||
|
||||
if (x.FileEntryType == FileEntryType.File)
|
||||
{
|
||||
@ -80,11 +93,11 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
ProgressStep();
|
||||
});
|
||||
|
||||
var newrootfolder = FileMarker
|
||||
var newrootfolder = fileMarker
|
||||
.GetRootFoldersIdMarkedAsNew()
|
||||
.Select(item => string.Format("new_{{\"key\"? \"{0}\", \"value\"? \"{1}\"}}", item.Key, item.Value));
|
||||
|
||||
Status += string.Join(SPLIT_CHAR, newrootfolder.ToArray());
|
||||
Status += string.Join(FileOperation.SPLIT_CHAR, newrootfolder.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
@ -28,6 +28,8 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.MessagingSystem;
|
||||
using ASC.Web.Core.Files;
|
||||
@ -36,34 +38,57 @@ using ASC.Web.Files.Helpers;
|
||||
using ASC.Web.Files.Resources;
|
||||
using ASC.Web.Files.Utils;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
class FileMoveCopyOperation : FileOperation
|
||||
internal class FileMoveCopyOperationData : FileOperationData
|
||||
{
|
||||
private readonly string _toFolderId;
|
||||
private readonly bool _copy;
|
||||
private readonly FileConflictResolveType _resolveType;
|
||||
public string ToFolderId { get; }
|
||||
public bool Copy { get; }
|
||||
public FileConflictResolveType ResolveType { get; }
|
||||
public Dictionary<string, string> Headers { get; }
|
||||
|
||||
public FileMoveCopyOperationData(List<object> folders, List<object> files, Tenant tenant, string toFolderId, bool copy, FileConflictResolveType resolveType, bool holdResult = true, Dictionary<string, string> headers = null)
|
||||
: base(folders, files, tenant, holdResult)
|
||||
{
|
||||
ToFolderId = toFolderId;
|
||||
Copy = copy;
|
||||
ResolveType = resolveType;
|
||||
Headers = headers;
|
||||
}
|
||||
}
|
||||
|
||||
class FileMoveCopyOperation : FileOperation<FileMoveCopyOperationData>
|
||||
{
|
||||
private string _toFolderId;
|
||||
private bool _copy;
|
||||
private FileConflictResolveType _resolveType;
|
||||
private readonly List<FileEntry> _needToMark = new List<FileEntry>();
|
||||
|
||||
private readonly Dictionary<string, string> _headers;
|
||||
private Dictionary<string, string> _headers;
|
||||
|
||||
public override FileOperationType OperationType
|
||||
{
|
||||
get { return _copy ? FileOperationType.Copy : FileOperationType.Move; }
|
||||
}
|
||||
|
||||
public FileMoveCopyOperation(List<object> folders, List<object> files, string toFolderId, bool copy, FileConflictResolveType resolveType, bool holdResult = true, Dictionary<string, string> headers = null)
|
||||
: base(folders, files, holdResult)
|
||||
public FileMoveCopyOperation(IServiceProvider serviceProvider)
|
||||
: base(serviceProvider)
|
||||
{
|
||||
_toFolderId = toFolderId;
|
||||
_copy = copy;
|
||||
_resolveType = resolveType;
|
||||
_headers = headers;
|
||||
}
|
||||
|
||||
protected override void Do()
|
||||
protected override void Do(FileMoveCopyOperationData data, IServiceScope scope)
|
||||
{
|
||||
Status += string.Format("folder_{0}{1}", _toFolderId, SPLIT_CHAR);
|
||||
_toFolderId = data.ToFolderId;
|
||||
_copy = data.Copy;
|
||||
_resolveType = data.ResolveType;
|
||||
|
||||
_headers = data.Headers;
|
||||
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
|
||||
Status += string.Format("folder_{0}{1}", _toFolderId, FileOperation.SPLIT_CHAR);
|
||||
|
||||
//TODO: check on each iteration?
|
||||
var toFolder = FolderDao.GetFolder(_toFolderId);
|
||||
@ -85,16 +110,18 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
if (toFolder.RootFolderType == FolderType.TRASH) throw new InvalidOperationException("Can not copy to Trash.");
|
||||
}
|
||||
|
||||
MoveOrCopyFolders(Folders, toFolder, _copy);
|
||||
MoveOrCopyFiles(Files, toFolder, _copy);
|
||||
MoveOrCopyFolders(scope, Folders, toFolder, _copy);
|
||||
MoveOrCopyFiles(scope, Files, toFolder, _copy);
|
||||
|
||||
_needToMark.Distinct().ToList().ForEach(x => FileMarker.MarkAsNew(x));
|
||||
_needToMark.Distinct().ToList().ForEach(x => fileMarker.MarkAsNew(x));
|
||||
}
|
||||
|
||||
private void MoveOrCopyFolders(ICollection folderIds, Folder toFolder, bool copy)
|
||||
private void MoveOrCopyFolders(IServiceScope scope, ICollection folderIds, Folder toFolder, bool copy)
|
||||
{
|
||||
if (folderIds.Count == 0) return;
|
||||
|
||||
var filesMessageService = scope.ServiceProvider.GetService<FilesMessageService>();
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
var toFolderId = toFolder.ID;
|
||||
var isToFolder = Equals(toFolderId.ToString(), _toFolderId);
|
||||
|
||||
@ -131,21 +158,21 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
else
|
||||
{
|
||||
newFolder = FolderDao.CopyFolder(folder.ID, toFolderId, CancellationToken);
|
||||
FilesMessageService.Send(newFolder, toFolder, _headers, MessageAction.FolderCopied, newFolder.Title, toFolder.Title);
|
||||
filesMessageService.Send(newFolder, toFolder, _headers, MessageAction.FolderCopied, newFolder.Title, toFolder.Title);
|
||||
|
||||
if (isToFolder)
|
||||
_needToMark.Add(newFolder);
|
||||
|
||||
if (ProcessedFolder(folderId))
|
||||
{
|
||||
Status += string.Format("folder_{0}{1}", newFolder.ID, SPLIT_CHAR);
|
||||
Status += string.Format("folder_{0}{1}", newFolder.ID, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
|
||||
if (FolderDao.UseRecursiveOperation(folder.ID, toFolderId))
|
||||
{
|
||||
MoveOrCopyFiles(FileDao.GetFiles(folder.ID), newFolder, copy);
|
||||
MoveOrCopyFolders(FolderDao.GetFolders(folder.ID).Select(f => f.ID).ToList(), newFolder, copy);
|
||||
MoveOrCopyFiles(scope, FileDao.GetFiles(folder.ID), newFolder, copy);
|
||||
MoveOrCopyFolders(scope, FolderDao.GetFolders(folder.ID).Select(f => f.ID).ToList(), newFolder, copy);
|
||||
|
||||
if (!copy)
|
||||
{
|
||||
@ -158,7 +185,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
FolderDao.DeleteFolder(folder.ID);
|
||||
if (ProcessedFolder(folderId))
|
||||
{
|
||||
Status += string.Format("folder_{0}{1}", newFolder.ID, SPLIT_CHAR);
|
||||
Status += string.Format("folder_{0}{1}", newFolder.ID, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -167,44 +194,43 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
if (conflictFolder != null)
|
||||
{
|
||||
string tmpError;
|
||||
object newFolderId;
|
||||
if (copy)
|
||||
{
|
||||
newFolder = FolderDao.CopyFolder(folder.ID, toFolderId, CancellationToken);
|
||||
newFolderId = newFolder.ID;
|
||||
FilesMessageService.Send(newFolder, toFolder, _headers, MessageAction.FolderCopiedWithOverwriting, newFolder.Title, toFolder.Title);
|
||||
filesMessageService.Send(newFolder, toFolder, _headers, MessageAction.FolderCopiedWithOverwriting, newFolder.Title, toFolder.Title);
|
||||
|
||||
if (isToFolder)
|
||||
_needToMark.Add(newFolder);
|
||||
|
||||
if (ProcessedFolder(folderId))
|
||||
{
|
||||
Status += string.Format("folder_{0}{1}", newFolderId, SPLIT_CHAR);
|
||||
Status += string.Format("folder_{0}{1}", newFolderId, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
else if (!FilesSecurity.CanDelete(folder))
|
||||
{
|
||||
Error = FilesCommonResource.ErrorMassage_SecurityException_MoveFolder;
|
||||
}
|
||||
else if (WithError(FileDao.GetFiles(folder.ID, new OrderBy(SortedByType.AZ, true), FilterType.FilesOnly, false, Guid.Empty, string.Empty, false, true), out tmpError))
|
||||
else if (WithError(scope, FileDao.GetFiles(folder.ID, new OrderBy(SortedByType.AZ, true), FilterType.FilesOnly, false, Guid.Empty, string.Empty, false, true), out var tmpError))
|
||||
{
|
||||
Error = tmpError;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileMarker.RemoveMarkAsNewForAll(folder);
|
||||
fileMarker.RemoveMarkAsNewForAll(folder);
|
||||
|
||||
newFolderId = FolderDao.MoveFolder(folder.ID, toFolderId, CancellationToken);
|
||||
newFolder = FolderDao.GetFolder(newFolderId);
|
||||
FilesMessageService.Send(folder.RootFolderType != FolderType.USER ? folder : newFolder, toFolder, _headers, MessageAction.FolderMovedWithOverwriting, folder.Title, toFolder.Title);
|
||||
filesMessageService.Send(folder.RootFolderType != FolderType.USER ? folder : newFolder, toFolder, _headers, MessageAction.FolderMovedWithOverwriting, folder.Title, toFolder.Title);
|
||||
|
||||
if (isToFolder)
|
||||
_needToMark.Add(newFolder);
|
||||
|
||||
if (ProcessedFolder(folderId))
|
||||
{
|
||||
Status += string.Format("folder_{0}{1}", newFolderId, SPLIT_CHAR);
|
||||
Status += string.Format("folder_{0}{1}", newFolderId, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -212,29 +238,28 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
else
|
||||
{
|
||||
string tmpError;
|
||||
if (!FilesSecurity.CanDelete(folder))
|
||||
{
|
||||
Error = FilesCommonResource.ErrorMassage_SecurityException_MoveFolder;
|
||||
}
|
||||
else if (WithError(FileDao.GetFiles(folder.ID, new OrderBy(SortedByType.AZ, true), FilterType.FilesOnly, false, Guid.Empty, string.Empty, false, true), out tmpError))
|
||||
else if (WithError(scope, FileDao.GetFiles(folder.ID, new OrderBy(SortedByType.AZ, true), FilterType.FilesOnly, false, Guid.Empty, string.Empty, false, true), out var tmpError))
|
||||
{
|
||||
Error = tmpError;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileMarker.RemoveMarkAsNewForAll(folder);
|
||||
fileMarker.RemoveMarkAsNewForAll(folder);
|
||||
|
||||
var newFolderId = FolderDao.MoveFolder(folder.ID, toFolderId, CancellationToken);
|
||||
newFolder = FolderDao.GetFolder(newFolderId);
|
||||
FilesMessageService.Send(folder.RootFolderType != FolderType.USER ? folder : newFolder, toFolder, _headers, MessageAction.FolderMoved, folder.Title, toFolder.Title);
|
||||
filesMessageService.Send(folder.RootFolderType != FolderType.USER ? folder : newFolder, toFolder, _headers, MessageAction.FolderMoved, folder.Title, toFolder.Title);
|
||||
|
||||
if (isToFolder)
|
||||
_needToMark.Add(newFolder);
|
||||
|
||||
if (ProcessedFolder(folderId))
|
||||
{
|
||||
Status += string.Format("folder_{0}{1}", newFolderId, SPLIT_CHAR);
|
||||
Status += string.Format("folder_{0}{1}", newFolderId, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -250,10 +275,16 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveOrCopyFiles(ICollection fileIds, Folder toFolder, bool copy)
|
||||
private void MoveOrCopyFiles(IServiceScope scope, ICollection fileIds, Folder toFolder, bool copy)
|
||||
{
|
||||
if (fileIds.Count == 0) return;
|
||||
|
||||
var filesMessageService = scope.ServiceProvider.GetService<FilesMessageService>();
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
var fileUtility = scope.ServiceProvider.GetService<FileUtility>();
|
||||
var global = scope.ServiceProvider.GetService<Global>();
|
||||
var entryManager = scope.ServiceProvider.GetService<EntryManager>();
|
||||
|
||||
var toFolderId = toFolder.ID;
|
||||
foreach (var fileId in fileIds)
|
||||
{
|
||||
@ -268,8 +299,8 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
Error = FilesCommonResource.ErrorMassage_SecurityException_ReadFile;
|
||||
}
|
||||
else if (Global.EnableUploadFilter
|
||||
&& !FileUtility.ExtsUploadable.Contains(FileUtility.GetFileExtension(file.Title)))
|
||||
else if (global.EnableUploadFilter
|
||||
&& !fileUtility.ExtsUploadable.Contains(FileUtility.GetFileExtension(file.Title)))
|
||||
{
|
||||
Error = FilesCommonResource.ErrorMassage_NotSupportedFormat;
|
||||
}
|
||||
@ -289,7 +320,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
try
|
||||
{
|
||||
newFile = FileDao.CopyFile(file.ID, toFolderId); //Stream copy will occur inside dao
|
||||
FilesMessageService.Send(newFile, toFolder, _headers, MessageAction.FileCopied, newFile.Title, parentFolder.Title, toFolder.Title);
|
||||
filesMessageService.Send(newFile, toFolder, _headers, MessageAction.FileCopied, newFile.Title, parentFolder.Title, toFolder.Title);
|
||||
|
||||
if (Equals(newFile.FolderID.ToString(), _toFolderId))
|
||||
{
|
||||
@ -298,7 +329,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
|
||||
if (ProcessedFile(fileId))
|
||||
{
|
||||
Status += string.Format("file_{0}{1}", newFile.ID, SPLIT_CHAR);
|
||||
Status += string.Format("file_{0}{1}", newFile.ID, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
catch
|
||||
@ -312,18 +343,17 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
else
|
||||
{
|
||||
string tmpError;
|
||||
if (WithError(new[] { file }, out tmpError))
|
||||
if (WithError(scope, new[] { file }, out var tmpError))
|
||||
{
|
||||
Error = tmpError;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileMarker.RemoveMarkAsNewForAll(file);
|
||||
fileMarker.RemoveMarkAsNewForAll(file);
|
||||
|
||||
var newFileId = FileDao.MoveFile(file.ID, toFolderId);
|
||||
newFile = FileDao.GetFile(newFileId);
|
||||
FilesMessageService.Send(file.RootFolderType != FolderType.USER ? file : newFile, toFolder, _headers, MessageAction.FileMoved, file.Title, parentFolder.Title, toFolder.Title);
|
||||
filesMessageService.Send(file.RootFolderType != FolderType.USER ? file : newFile, toFolder, _headers, MessageAction.FileMoved, file.Title, parentFolder.Title, toFolder.Title);
|
||||
|
||||
if (Equals(toFolderId.ToString(), _toFolderId))
|
||||
{
|
||||
@ -332,7 +362,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
|
||||
if (ProcessedFile(fileId))
|
||||
{
|
||||
Status += string.Format("file_{0}{1}", newFileId, SPLIT_CHAR);
|
||||
Status += string.Format("file_{0}{1}", newFileId, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -345,7 +375,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
Error = FilesCommonResource.ErrorMassage_SecurityException;
|
||||
}
|
||||
else if (EntryManager.FileLockedForMe(conflict.ID))
|
||||
else if (entryManager.FileLockedForMe(conflict.ID))
|
||||
{
|
||||
Error = FilesCommonResource.ErrorMassage_LockedFile;
|
||||
}
|
||||
@ -374,10 +404,10 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
|
||||
if (copy)
|
||||
{
|
||||
FilesMessageService.Send(newFile, toFolder, _headers, MessageAction.FileCopiedWithOverwriting, newFile.Title, parentFolder.Title, toFolder.Title);
|
||||
filesMessageService.Send(newFile, toFolder, _headers, MessageAction.FileCopiedWithOverwriting, newFile.Title, parentFolder.Title, toFolder.Title);
|
||||
if (ProcessedFile(fileId))
|
||||
{
|
||||
Status += string.Format("file_{0}{1}", newFile.ID, SPLIT_CHAR);
|
||||
Status += string.Format("file_{0}{1}", newFile.ID, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -386,13 +416,12 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
if (ProcessedFile(fileId))
|
||||
{
|
||||
Status += string.Format("file_{0}{1}", newFile.ID, SPLIT_CHAR);
|
||||
Status += string.Format("file_{0}{1}", newFile.ID, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string tmpError;
|
||||
if (WithError(new[] { file }, out tmpError))
|
||||
if (WithError(scope, new[] { file }, out var tmpError))
|
||||
{
|
||||
Error = tmpError;
|
||||
}
|
||||
@ -400,11 +429,11 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
FileDao.DeleteFile(file.ID);
|
||||
|
||||
FilesMessageService.Send(file.RootFolderType != FolderType.USER ? file : newFile, toFolder, _headers, MessageAction.FileMovedWithOverwriting, file.Title, parentFolder.Title, toFolder.Title);
|
||||
filesMessageService.Send(file.RootFolderType != FolderType.USER ? file : newFile, toFolder, _headers, MessageAction.FileMovedWithOverwriting, file.Title, parentFolder.Title, toFolder.Title);
|
||||
|
||||
if (ProcessedFile(fileId))
|
||||
{
|
||||
Status += string.Format("file_{0}{1}", newFile.ID, SPLIT_CHAR);
|
||||
Status += string.Format("file_{0}{1}", newFile.ID, FileOperation.SPLIT_CHAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -427,8 +456,9 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
}
|
||||
|
||||
private bool WithError(IEnumerable<File> files, out string error)
|
||||
private bool WithError(IServiceScope scope, IEnumerable<File> files, out string error)
|
||||
{
|
||||
var entryManager = scope.ServiceProvider.GetService<EntryManager>();
|
||||
error = null;
|
||||
foreach (var file in files)
|
||||
{
|
||||
@ -437,7 +467,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
error = FilesCommonResource.ErrorMassage_SecurityException_MoveFile;
|
||||
return true;
|
||||
}
|
||||
if (EntryManager.FileLockedForMe(file.ID))
|
||||
if (entryManager.FileLockedForMe(file.ID))
|
||||
{
|
||||
error = FilesCommonResource.ErrorMassage_LockedFile;
|
||||
return true;
|
||||
|
@ -32,19 +32,42 @@ using System.Security;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Common.Security.Authentication;
|
||||
using ASC.Common.Security.Authorizing;
|
||||
using ASC.Common.Threading;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Security;
|
||||
using ASC.Web.Files.Classes;
|
||||
using ASC.Web.Files.Resources;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
abstract class FileOperation
|
||||
abstract class FileOperationData
|
||||
{
|
||||
public List<object> Folders { get; private set; }
|
||||
|
||||
public List<object> Files { get; private set; }
|
||||
|
||||
public Tenant Tenant { get; }
|
||||
|
||||
public bool HoldResult { get; private set; }
|
||||
|
||||
protected FileOperationData(List<object> folders, List<object> files, Tenant tenant, bool holdResult = true)
|
||||
{
|
||||
Folders = folders ?? new List<object>();
|
||||
Files = files ?? new List<object>();
|
||||
Tenant = tenant;
|
||||
HoldResult = holdResult;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FileOperation
|
||||
{
|
||||
public const string SPLIT_CHAR = ":";
|
||||
public const string OWNER = "Owner";
|
||||
@ -56,7 +79,10 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
public const string PROCESSED = "Processed";
|
||||
public const string FINISHED = "Finished";
|
||||
public const string HOLD = "Hold";
|
||||
}
|
||||
|
||||
abstract class FileOperation<T> where T : FileOperationData
|
||||
{
|
||||
private readonly IPrincipal principal;
|
||||
private readonly string culture;
|
||||
private int total;
|
||||
@ -93,44 +119,52 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
protected bool HoldResult { get; private set; }
|
||||
|
||||
public abstract FileOperationType OperationType { get; }
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
|
||||
|
||||
protected FileOperation(List<object> folders, List<object> files, bool holdResult = true, Tenant tenant = null)
|
||||
protected FileOperation(IServiceProvider serviceProvider)
|
||||
{
|
||||
CurrentTenant = tenant ?? CoreContext.TenantManager.GetCurrentTenant();
|
||||
principal = Thread.CurrentPrincipal;
|
||||
culture = Thread.CurrentThread.CurrentCulture.Name;
|
||||
|
||||
Folders = folders ?? new List<object>();
|
||||
Files = files ?? new List<object>();
|
||||
|
||||
HoldResult = holdResult;
|
||||
|
||||
TaskInfo = new DistributedTask();
|
||||
ServiceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public void RunJob(DistributedTask _, CancellationToken cancellationToken)
|
||||
public Action<DistributedTask, CancellationToken> RunJob(T fileOperationData)
|
||||
=> (_, cancellationToken) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Files = fileOperationData.Files;
|
||||
Folders = fileOperationData.Folders;
|
||||
HoldResult = fileOperationData.HoldResult;
|
||||
CurrentTenant = fileOperationData.Tenant;
|
||||
|
||||
CancellationToken = cancellationToken;
|
||||
|
||||
CoreContext.TenantManager.SetCurrentTenant(CurrentTenant);
|
||||
using var scope = ServiceProvider.CreateScope();
|
||||
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
|
||||
tenantManager.SetCurrentTenant(CurrentTenant);
|
||||
var daoFactory = scope.ServiceProvider.GetService<IDaoFactory>();
|
||||
var fileSecurity = scope.ServiceProvider.GetService<FileSecurity>();
|
||||
var logger = scope.ServiceProvider.GetService<IOptionsMonitor<ILog>>().CurrentValue;
|
||||
|
||||
|
||||
Thread.CurrentPrincipal = principal;
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture);
|
||||
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);
|
||||
|
||||
FolderDao = Global.DaoFactory.GetFolderDao();
|
||||
FileDao = Global.DaoFactory.GetFileDao();
|
||||
TagDao = Global.DaoFactory.GetTagDao();
|
||||
ProviderDao = Global.DaoFactory.GetProviderDao();
|
||||
FilesSecurity = new FileSecurity(Global.DaoFactory);
|
||||
FolderDao = daoFactory.FolderDao;
|
||||
FileDao = daoFactory.FileDao;
|
||||
TagDao = daoFactory.TagDao;
|
||||
ProviderDao = daoFactory.ProviderDao;
|
||||
FilesSecurity = fileSecurity;
|
||||
|
||||
Logger = Global.Logger;
|
||||
Logger = logger;
|
||||
|
||||
total = InitTotalProgressSteps();
|
||||
|
||||
Do();
|
||||
Do(fileOperationData, scope);
|
||||
}
|
||||
catch (AuthorizingException authError)
|
||||
{
|
||||
@ -152,19 +186,12 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
try
|
||||
{
|
||||
TaskInfo.SetProperty(FINISHED, true);
|
||||
TaskInfo.SetProperty(FileOperation.FINISHED, true);
|
||||
PublishTaskInfo();
|
||||
|
||||
FolderDao.Dispose();
|
||||
FileDao.Dispose();
|
||||
TagDao.Dispose();
|
||||
|
||||
if (ProviderDao != null)
|
||||
ProviderDao.Dispose();
|
||||
}
|
||||
catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public virtual DistributedTask GetDistributedTask()
|
||||
{
|
||||
@ -177,14 +204,14 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
var progress = total != 0 ? 100 * processed / total : 0;
|
||||
|
||||
TaskInfo.SetProperty(SOURCE, string.Join(SPLIT_CHAR, Folders.Select(f => "folder_" + f).Concat(Files.Select(f => "file_" + f)).ToArray()));
|
||||
TaskInfo.SetProperty(OPERATION_TYPE, OperationType);
|
||||
TaskInfo.SetProperty(OWNER, ((IAccount)Thread.CurrentPrincipal.Identity).ID);
|
||||
TaskInfo.SetProperty(PROGRESS, progress < 100 ? progress : 100);
|
||||
TaskInfo.SetProperty(RESULT, Status);
|
||||
TaskInfo.SetProperty(ERROR, Error);
|
||||
TaskInfo.SetProperty(PROCESSED, successProcessed);
|
||||
TaskInfo.SetProperty(HOLD, HoldResult);
|
||||
TaskInfo.SetProperty(FileOperation.SOURCE, string.Join(FileOperation.SPLIT_CHAR, Folders.Select(f => "folder_" + f).Concat(Files.Select(f => "file_" + f)).ToArray()));
|
||||
TaskInfo.SetProperty(FileOperation.OPERATION_TYPE, OperationType);
|
||||
TaskInfo.SetProperty(FileOperation.OWNER, ((IAccount)Thread.CurrentPrincipal.Identity).ID);
|
||||
TaskInfo.SetProperty(FileOperation.PROGRESS, progress < 100 ? progress : 100);
|
||||
TaskInfo.SetProperty(FileOperation.RESULT, Status);
|
||||
TaskInfo.SetProperty(FileOperation.ERROR, Error);
|
||||
TaskInfo.SetProperty(FileOperation.PROCESSED, successProcessed);
|
||||
TaskInfo.SetProperty(FileOperation.HOLD, HoldResult);
|
||||
}
|
||||
|
||||
protected virtual int InitTotalProgressSteps()
|
||||
@ -210,7 +237,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
successProcessed++;
|
||||
if (Folders.Contains(folderId))
|
||||
{
|
||||
Status += string.Format("folder_{0}{1}", folderId, SPLIT_CHAR);
|
||||
Status += string.Format("folder_{0}{1}", folderId, FileOperation.SPLIT_CHAR);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -221,7 +248,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
successProcessed++;
|
||||
if (Files.Contains(fileId))
|
||||
{
|
||||
Status += string.Format("file_{0}{1}", fileId, SPLIT_CHAR);
|
||||
Status += string.Format("file_{0}{1}", fileId, FileOperation.SPLIT_CHAR);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -233,6 +260,6 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
TaskInfo.PublishChanges();
|
||||
}
|
||||
|
||||
protected abstract void Do();
|
||||
protected abstract void Do(T fileOperationData, IServiceScope serviceScope);
|
||||
}
|
||||
}
|
@ -39,9 +39,12 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
private readonly DistributedTaskQueue tasks;
|
||||
|
||||
public FileOperationsManager(DistributedTaskCacheNotify distributedTaskCacheNotify)
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
|
||||
public FileOperationsManager(DistributedTaskCacheNotify distributedTaskCacheNotify, IServiceProvider serviceProvider)
|
||||
{
|
||||
tasks = new DistributedTaskQueue(distributedTaskCacheNotify, "fileOperations", 10);
|
||||
ServiceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public ItemList<FileOperationResult> GetOperationResults(AuthContext authContext)
|
||||
@ -94,13 +97,13 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
}
|
||||
|
||||
|
||||
public ItemList<FileOperationResult> MarkAsRead(AuthContext authContext, List<object> folderIds, List<object> fileIds)
|
||||
public ItemList<FileOperationResult> MarkAsRead(AuthContext authContext, TenantManager tenantManager, List<object> folderIds, List<object> fileIds)
|
||||
{
|
||||
var op = new FileMarkAsReadOperation(folderIds, fileIds);
|
||||
return QueueTask(authContext, op);
|
||||
var op = new FileMarkAsReadOperation(ServiceProvider);
|
||||
return QueueTask(authContext, op, new FileMarkAsReadOperationData(folderIds, fileIds, tenantManager.GetCurrentTenant()));
|
||||
}
|
||||
|
||||
public ItemList<FileOperationResult> Download(AuthContext authContext, Dictionary<object, string> folders, Dictionary<object, string> files, Dictionary<string, string> headers)
|
||||
public ItemList<FileOperationResult> Download(AuthContext authContext, TenantManager tenantManager, Dictionary<object, string> folders, Dictionary<object, string> files, Dictionary<string, string> headers)
|
||||
{
|
||||
var operations = tasks.GetTasks()
|
||||
.Where(t => t.GetProperty<Guid>(FileOperation.OWNER) == authContext.CurrentAccount.ID)
|
||||
@ -109,28 +112,28 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
if (operations.Any(o => o.Status <= DistributedTaskStatus.Running))
|
||||
{
|
||||
throw new InvalidOperationException(FilesCommonResource.ErrorMassage_ManyDownloads);
|
||||
}
|
||||
}
|
||||
|
||||
var op = new FileDownloadOperation(folders, files, headers);
|
||||
return QueueTask(authContext, op);
|
||||
var op = new FileDownloadOperation(ServiceProvider);
|
||||
return QueueTask(authContext, op, new FileDownloadOperationData(folders, files, tenantManager.GetCurrentTenant(), headers));
|
||||
}
|
||||
|
||||
public ItemList<FileOperationResult> MoveOrCopy(AuthContext authContext, List<object> folders, List<object> files, string destFolderId, bool copy, FileConflictResolveType resolveType, bool holdResult, Dictionary<string, string> headers)
|
||||
public ItemList<FileOperationResult> MoveOrCopy(AuthContext authContext, TenantManager tenantManager, List<object> folders, List<object> files, string destFolderId, bool copy, FileConflictResolveType resolveType, bool holdResult, Dictionary<string, string> headers)
|
||||
{
|
||||
var op = new FileMoveCopyOperation(folders, files, destFolderId, copy, resolveType, holdResult, headers);
|
||||
return QueueTask(authContext, op);
|
||||
var op = new FileMoveCopyOperation(ServiceProvider);
|
||||
return QueueTask(authContext, op, new FileMoveCopyOperationData(folders, files, tenantManager.GetCurrentTenant(), destFolderId, copy, resolveType, holdResult, headers));
|
||||
}
|
||||
|
||||
public ItemList<FileOperationResult> Delete(AuthContext authContext, List<object> folders, List<object> files, bool ignoreException, bool holdResult, bool immediately, Dictionary<string, string> headers)
|
||||
public ItemList<FileOperationResult> Delete(AuthContext authContext, TenantManager tenantManager, List<object> folders, List<object> files, bool ignoreException, bool holdResult, bool immediately, Dictionary<string, string> headers)
|
||||
{
|
||||
var op = new FileDeleteOperation(folders, files, ignoreException, holdResult, immediately, headers);
|
||||
return QueueTask(authContext, op);
|
||||
var op = new FileDeleteOperation(ServiceProvider);
|
||||
return QueueTask(authContext, op, new FileDeleteOperationData(folders, files, tenantManager.GetCurrentTenant(), holdResult, ignoreException, immediately, headers));
|
||||
}
|
||||
|
||||
|
||||
private ItemList<FileOperationResult> QueueTask(AuthContext authContext, FileOperation op)
|
||||
private ItemList<FileOperationResult> QueueTask<T>(AuthContext authContext, FileOperation<T> op, T data) where T : FileOperationData
|
||||
{
|
||||
tasks.QueueTask(op.RunJob, op.GetDistributedTask());
|
||||
tasks.QueueTask(op.RunJob(data), op.GetDistributedTask());
|
||||
return GetOperationResults(authContext);
|
||||
}
|
||||
}
|
||||
@ -139,23 +142,29 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
public FileOperationsManager FileOperationsManager { get; }
|
||||
public AuthContext AuthContext { get; }
|
||||
public TenantManager TenantManager { get; }
|
||||
|
||||
public FileOperationsManagerHelper(FileOperationsManager fileOperationsManager, AuthContext authContext)
|
||||
public FileOperationsManagerHelper(
|
||||
FileOperationsManager fileOperationsManager,
|
||||
AuthContext authContext,
|
||||
TenantManager tenantManager)
|
||||
{
|
||||
FileOperationsManager = fileOperationsManager;
|
||||
AuthContext = authContext;
|
||||
TenantManager = tenantManager;
|
||||
}
|
||||
|
||||
public ItemList<FileOperationResult> GetOperationResults() => FileOperationsManager.GetOperationResults(AuthContext);
|
||||
public ItemList<FileOperationResult> CancelOperations() => FileOperationsManager.CancelOperations(AuthContext);
|
||||
public ItemList<FileOperationResult> MarkAsRead(List<object> folderIds, List<object> fileIds) => FileOperationsManager.MarkAsRead(AuthContext, folderIds, fileIds);
|
||||
public ItemList<FileOperationResult> MarkAsRead(List<object> folderIds, List<object> fileIds)
|
||||
=> FileOperationsManager.MarkAsRead(AuthContext, TenantManager, folderIds, fileIds);
|
||||
public ItemList<FileOperationResult> Download(Dictionary<object, string> folders, Dictionary<object, string> files, Dictionary<string, string> headers)
|
||||
=> FileOperationsManager.Download(AuthContext, folders, files, headers);
|
||||
=> FileOperationsManager.Download(AuthContext, TenantManager, folders, files, headers);
|
||||
|
||||
public ItemList<FileOperationResult> MoveOrCopy(List<object> folders, List<object> files, string destFolderId, bool copy, FileConflictResolveType resolveType, bool holdResult, Dictionary<string, string> headers)
|
||||
=> FileOperationsManager.MoveOrCopy(AuthContext, folders, files, destFolderId, copy, resolveType, holdResult, headers);
|
||||
=> FileOperationsManager.MoveOrCopy(AuthContext, TenantManager, folders, files, destFolderId, copy, resolveType, holdResult, headers);
|
||||
|
||||
public ItemList<FileOperationResult> Delete(List<object> folders, List<object> files, bool ignoreException, bool holdResult, bool immediately, Dictionary<string, string> headers)
|
||||
=> FileOperationsManager.Delete(AuthContext, folders, files, ignoreException, holdResult, immediately, headers);
|
||||
=> FileOperationsManager.Delete(AuthContext, TenantManager, folders, files, ignoreException, holdResult, immediately, headers);
|
||||
}
|
||||
}
|
@ -109,6 +109,7 @@ namespace ASC.Web.Files.Services.WCFService
|
||||
public FileSharing FileSharing { get; }
|
||||
public NotifyClient NotifyClient { get; }
|
||||
public FileOperationsManagerHelper FileOperationsManagerHelper { get; }
|
||||
public UrlShortener UrlShortener { get; }
|
||||
public ILog Logger { get; set; }
|
||||
|
||||
public FileStorageServiceController(
|
||||
@ -146,7 +147,8 @@ namespace ASC.Web.Files.Services.WCFService
|
||||
DocumentServiceConnector documentServiceConnector,
|
||||
FileSharing fileSharing,
|
||||
NotifyClient notifyClient,
|
||||
FileOperationsManagerHelper fileOperationsManagerHelper)
|
||||
FileOperationsManagerHelper fileOperationsManagerHelper,
|
||||
UrlShortener urlShortener)
|
||||
{
|
||||
Global = global;
|
||||
GlobalStore = globalStore;
|
||||
@ -182,6 +184,7 @@ namespace ASC.Web.Files.Services.WCFService
|
||||
FileSharing = fileSharing;
|
||||
NotifyClient = notifyClient;
|
||||
FileOperationsManagerHelper = fileOperationsManagerHelper;
|
||||
UrlShortener = urlShortener;
|
||||
Logger = optionMonitor.Get("ASC.Files");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user