diff --git a/products/ASC.Files/Core/Core/Dao/Interfaces/IFolderDao.cs b/products/ASC.Files/Core/Core/Dao/Interfaces/IFolderDao.cs index 728470057e..a103328cbd 100644 --- a/products/ASC.Files/Core/Core/Dao/Interfaces/IFolderDao.cs +++ b/products/ASC.Files/Core/Core/Dao/Interfaces/IFolderDao.cs @@ -57,12 +57,19 @@ public interface IFolderDao /// root folder Task> GetRootFolderByFileAsync(T fileId); - IAsyncEnumerable> GetRoomsAsync(T parentId, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, + IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds); IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds); + IAsyncEnumerable> GetFakeRoomsAsync(IEnumerable parentsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, + bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds); + + IAsyncEnumerable> GetFakeRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, + Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, + IEnumerable subjectEntriesIds); + /// /// Get a list of folders in current folder. /// diff --git a/products/ASC.Files/Core/Core/Dao/Interfaces/IProviderDao.cs b/products/ASC.Files/Core/Core/Dao/Interfaces/IProviderDao.cs index 57ca6a72fd..b9e16abd46 100644 --- a/products/ASC.Files/Core/Core/Dao/Interfaces/IProviderDao.cs +++ b/products/ASC.Files/Core/Core/Dao/Interfaces/IProviderDao.cs @@ -36,7 +36,7 @@ public interface IProviderDao Task SaveProviderInfoAsync(string providerKey, string customerTitle, AuthData authData, FolderType folderType); Task UpdateProviderInfoAsync(int linkId, FolderType rootFolderType); Task UpdateProviderInfoAsync(int linkId, bool hasLogo); - Task UpdateProviderInfoAsync(int linkId, string folderId, FolderType folderType, bool @private); + Task UpdateProviderInfoAsync(int linkId, string title, string folderId, FolderType folderType, bool @private); Task UpdateProviderInfoAsync(int linkId, string customerTitle, AuthData authData, FolderType folderType, Guid? userId = null); Task UpdateBackupProviderInfoAsync(string providerKey, string customerTitle, AuthData authData); Task RemoveProviderInfoAsync(int linkId); diff --git a/products/ASC.Files/Core/Core/Dao/Interfaces/IProviderInfo.cs b/products/ASC.Files/Core/Core/Dao/Interfaces/IProviderInfo.cs index 9a3fdb5220..5b1fedfbe9 100644 --- a/products/ASC.Files/Core/Core/Dao/Interfaces/IProviderInfo.cs +++ b/products/ASC.Files/Core/Core/Dao/Interfaces/IProviderInfo.cs @@ -38,6 +38,7 @@ public interface IProviderInfo : IDisposable string RootFolderId { get; } string FolderId { get; set; } bool Private { get; } + bool HasLogo { get; } Task CheckAccessAsync(); Task InvalidateStorageAsync(); diff --git a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs index 04c98aea5f..13d02c0a9a 100644 --- a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs +++ b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs @@ -159,13 +159,13 @@ internal class FolderDao : AbstractDao, IFolderDao return _mapper.Map>(dbFolder); } - + public IAsyncEnumerable> GetFoldersAsync(int parentId) { return GetFoldersAsync(parentId, default, FilterType.None, false, default, string.Empty); } - public async IAsyncEnumerable> GetRoomsAsync(int parentId, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, + public async IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) { if (CheckInvalidFilter(filterType) || provider != ProviderFilter.None) @@ -178,11 +178,11 @@ internal class FolderDao : AbstractDao, IFolderDao var searchByTags = tags != null && tags.Any() && !withoutTags; var searchByTypes = filterType != FilterType.None && filterType != FilterType.FoldersOnly; - var filesDbContext = _dbContextFactory.CreateDbContext(); - var q = GetFolderQuery(filesDbContext, r => r.ParentId == parentId).AsNoTracking(); + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); + var q = GetFolderQuery(filesDbContext, r => parentsIds.Contains(r.ParentId)).AsNoTracking(); q = !withSubfolders ? BuildRoomsQuery(filesDbContext, q, filter, tags, subjectId, searchByTags, withoutTags, searchByTypes, false, excludeSubject, subjectFilter, subjectEntriesIds) - : BuildRoomsWithSubfoldersQuery(filesDbContext, parentId, filter, tags, searchByTags, searchByTypes, withoutTags, excludeSubject, subjectId, subjectFilter, subjectEntriesIds); + : BuildRoomsWithSubfoldersQuery(filesDbContext, parentsIds, filter, tags, searchByTags, searchByTypes, withoutTags, excludeSubject, subjectId, subjectFilter, subjectEntriesIds); if (!string.IsNullOrEmpty(searchText)) { @@ -208,7 +208,7 @@ internal class FolderDao : AbstractDao, IFolderDao var searchByTags = tags != null && tags.Any() && !withoutTags; var searchByTypes = filterType != FilterType.None && filterType != FilterType.FoldersOnly; - var filesDbContext = _dbContextFactory.CreateDbContext(); + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); var q = GetFolderQuery(filesDbContext, f => roomsIds.Contains(f.Id) || (f.CreateBy == _authContext.CurrentAccount.ID && parentsIds.Contains(f.ParentId))).AsNoTracking(); q = !withSubfolders ? BuildRoomsQuery(filesDbContext, q, filter, tags, subjectId, searchByTags, withoutTags, searchByTypes, false, excludeSubject, subjectFilter, subjectEntriesIds) @@ -1465,6 +1465,18 @@ internal class FolderDao : AbstractDao, IFolderDao yield return q; } } + + public IAsyncEnumerable> GetFakeRoomsAsync(IEnumerable parentsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, + bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + { + return AsyncEnumerable.Empty>(); + } + + public IAsyncEnumerable> GetFakeRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, + string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + { + return AsyncEnumerable.Empty>(); + } private async IAsyncEnumerable GetTenantsWithFeeds(DateTime fromTime, Expression> filter, bool includeSecurity) { diff --git a/products/ASC.Files/Core/Core/FileStorageService.cs b/products/ASC.Files/Core/Core/FileStorageService.cs index a7f51e55fa..13fc0c6d2c 100644 --- a/products/ASC.Files/Core/Core/FileStorageService.cs +++ b/products/ASC.Files/Core/Core/FileStorageService.cs @@ -560,7 +560,7 @@ public class FileStorageService //: IFileStorageService await SetAcesForPrivateRoomAsync(result.Item1, aces, notify, sharingMessage); } - await providerDao.UpdateProviderInfoAsync(providerInfo.ID, result.Item1.Id.ToString(), result.Item2, @private); + await providerDao.UpdateProviderInfoAsync(providerInfo.ID, title, result.Item1.Id.ToString(), result.Item2, @private); return result.Item1; } diff --git a/products/ASC.Files/Core/Core/Security/FileSecurity.cs b/products/ASC.Files/Core/Core/Security/FileSecurity.cs index 6e420aefca..365d110271 100644 --- a/products/ASC.Files/Core/Core/Security/FileSecurity.cs +++ b/products/ASC.Files/Core/Core/Security/FileSecurity.cs @@ -1015,221 +1015,172 @@ public class FileSecurity : IFileSecurity if (_fileSecurityCommon.IsDocSpaceAdministrator(_authContext.CurrentAccount.ID)) { - return await GetVirtualRoomsForDocSpaceAdminAsync(filterType, subjectId, searchText, searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider, subjectFilter, subjectEntries); + return await GetAllVirtualRoomsAsync(filterType, subjectId, searchText, searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider, subjectFilter, subjectEntries); } - var currentUserSubjects = GetUserSubjects(_authContext.CurrentAccount.ID); - var currentUsersRecords = await securityDao.GetSharesAsync(currentUserSubjects).ToListAsync(); - var thirdpartyIds = await GetThirdpartyRoomsIdsAsync(searchArea); - var entries = new List(); - - var rooms = await GetVirtualRoomsForUserAsync(currentUsersRecords.Where(r => r.EntryId is int), Array.Empty(), currentUserSubjects, filterType, subjectId, searchText, searchInContent, - withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider, subjectFilter, subjectEntries); - var thirdPartyRooms = await GetVirtualRoomsForUserAsync(currentUsersRecords.Where(r => r.EntryId is string), thirdpartyIds, currentUserSubjects, filterType, subjectId, searchText, - searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider, subjectFilter, subjectEntries); - - entries.AddRange(rooms); - entries.AddRange(thirdPartyRooms); - - return entries; + return await GetVirtualRoomsForMeAsync(filterType, subjectId, searchText, searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider, subjectFilter, subjectEntries); } - private async Task> GetThirdpartyRoomsIdsAsync(SearchArea searchArea) - { - var result = new List(); - - if (_userManager.IsUser(_authContext.CurrentAccount.ID)) - { - return Array.Empty(); - } - - if (searchArea == SearchArea.Active || searchArea == SearchArea.Any) - { - var ids = await _daoFactory.ProviderDao.GetProvidersInfoAsync(FolderType.VirtualRooms) - .Where(p => p.Owner == _authContext.CurrentAccount.ID).Select(p => p.FolderId).ToListAsync(); - - result.AddRange(ids); - } - if (searchArea == SearchArea.Archive || searchArea == SearchArea.Any) - { - var ids = await _daoFactory.ProviderDao.GetProvidersInfoAsync(FolderType.Archive) - .Where(p => p.Owner == _authContext.CurrentAccount.ID).Select(p => p.FolderId).ToListAsync(); - - result.AddRange(ids); - } - - return result; - } - - private async Task> GetVirtualRoomsForDocSpaceAdminAsync(FilterType filterType, Guid subjectId, string search, bool searchInContent, bool withSubfolders, - SearchArea searchArea, bool withoutTags, IEnumerable tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntries) + private async Task> GetAllVirtualRoomsAsync(FilterType filterType, Guid subjectId, string search, bool searchInContent, bool withSubfolders, + SearchArea searchArea, bool withoutTags, IEnumerable tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, + IEnumerable subjectEntries) { var folderDao = _daoFactory.GetFolderDao(); var folderThirdPartyDao = _daoFactory.GetFolderDao(); var fileDao = _daoFactory.GetFileDao(); var fileThirdPartyDao = _daoFactory.GetFileDao(); - var providerDao = _daoFactory.ProviderDao; var entries = new List(); - var foldersInt = new List>(); - var foldersString = new List>(); - - if (searchArea is SearchArea.Any or SearchArea.Active) + var rootFoldersIds = searchArea switch { - var roomsFolderId = await _globalFolder.GetFolderVirtualRoomsAsync(_daoFactory); - var thirdPartyRoomsIds = await providerDao.GetProvidersInfoAsync(FolderType.VirtualRooms).Select(p => p.FolderId).ToListAsync(); + SearchArea.Active => new[] { await _globalFolder.GetFolderVirtualRoomsAsync(_daoFactory) }, + SearchArea.Archive => new[] { await _globalFolder.GetFolderArchiveAsync(_daoFactory) }, + _ => new[] { await _globalFolder.GetFolderVirtualRoomsAsync(_daoFactory), await _globalFolder.GetFolderArchiveAsync(_daoFactory) } + }; + + var roomsEntries = await folderDao.GetRoomsAsync(rootFoldersIds, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, + provider, subjectFilter, subjectEntries).ToListAsync(); + var thirdPartyRoomsEntries = await folderThirdPartyDao.GetFakeRoomsAsync(rootFoldersIds.Select(id => id.ToString()), filterType, tagNames, subjectId, search, + withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries).ToListAsync(); + + entries.AddRange(roomsEntries); + entries.AddRange(thirdPartyRoomsEntries); - var roomsEntries = await folderDao.GetRoomsAsync(roomsFolderId, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries).ToListAsync(); - var thirdPartyRoomsEntries = await folderThirdPartyDao.GetRoomsAsync(Array.Empty(), thirdPartyRoomsIds, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries) - .ToListAsync(); - - foldersInt.AddRange(roomsEntries); - foldersString.AddRange(thirdPartyRoomsEntries); - - if (withSubfolders && filterType != FilterType.FoldersOnly) - { - List> files; - List> thirdPartyFiles; - - if (!string.IsNullOrEmpty(search)) - { - files = await fileDao.GetFilesAsync(roomsFolderId, null, FilterType.None, false, Guid.Empty, search, searchInContent, true).ToListAsync(); - thirdPartyFiles = await fileThirdPartyDao.GetFilesAsync(thirdPartyRoomsIds, FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); - } - else - { - files = await fileDao.GetFilesAsync(roomsEntries.Where(r => DocSpaceHelper.IsRoom(r.FolderType)).Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); - thirdPartyFiles = await fileThirdPartyDao.GetFilesAsync(thirdPartyRoomsEntries.Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); - } - - entries.AddRange(files); - entries.AddRange(thirdPartyFiles); - } - } - if (searchArea is SearchArea.Any or SearchArea.Archive) + if (withSubfolders && filterType != FilterType.FoldersOnly) { - var archiveFolderId = await _globalFolder.GetFolderArchiveAsync(_daoFactory); - var thirdPartyRoomsIds = await providerDao.GetProvidersInfoAsync(FolderType.Archive).Select(p => p.FolderId).ToListAsync(); - - var roomsEntries = await folderDao.GetRoomsAsync(archiveFolderId, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries).ToListAsync(); - var thirdPartyRoomsEntries = await folderThirdPartyDao.GetRoomsAsync(Array.Empty(), thirdPartyRoomsIds, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries) - .ToListAsync(); - - foldersInt.AddRange(roomsEntries); - foldersString.AddRange(thirdPartyRoomsEntries); - - if (withSubfolders && filterType != FilterType.FoldersOnly) + List> files; + List> thirdPartyFiles; + + if (!string.IsNullOrEmpty(search)) { - List> files; - List> thirdPartyFiles; - - if (!string.IsNullOrEmpty(search)) - { - files = await fileDao.GetFilesAsync(archiveFolderId, null, FilterType.None, false, Guid.Empty, search, searchInContent, true).ToListAsync(); - thirdPartyFiles = await fileThirdPartyDao.GetFilesAsync(thirdPartyRoomsIds, FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); - } - else - { - files = await fileDao.GetFilesAsync(roomsEntries.Where(r => DocSpaceHelper.IsRoom(r.FolderType)).Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); - thirdPartyFiles = await fileThirdPartyDao.GetFilesAsync(thirdPartyRoomsEntries.Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); - } - - entries.AddRange(files); - entries.AddRange(thirdPartyFiles); + files = await fileDao.GetFilesAsync(roomsEntries.Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); + thirdPartyFiles = await fileThirdPartyDao.GetFilesAsync(thirdPartyRoomsEntries.Select(f => f.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); } + else + { + files = await fileDao.GetFilesAsync(roomsEntries.Where(r => DocSpaceHelper.IsRoom(r.FolderType)).Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); + thirdPartyFiles = await fileThirdPartyDao.GetFilesAsync(thirdPartyRoomsEntries.Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); + } + + entries.AddRange(files); + entries.AddRange(thirdPartyFiles); } - await SetTagsAsync(foldersInt); - await SetTagsAsync(foldersString); - await SetPinAsync(foldersInt); - await SetPinAsync(foldersString); - - entries.AddRange(foldersInt); - entries.AddRange(foldersString); - + await SetTagsAsync(roomsEntries); + await SetTagsAsync(thirdPartyRoomsEntries); + await SetPinAsync(roomsEntries); + await SetPinAsync(thirdPartyRoomsEntries); + return entries; } - private async Task> GetVirtualRoomsForUserAsync(IEnumerable records, IEnumerable proivdersIds, List subjects, FilterType filterType, Guid subjectId, string search, - bool searchInContent, bool withSubfolders, SearchArea searchArea, bool withoutTags, IEnumerable tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntries) + private async Task> GetVirtualRoomsForMeAsync(FilterType filterType, Guid subjectId, string search, bool searchInContent, bool withSubfolders, + SearchArea searchArea, bool withoutTags, IEnumerable tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntries) { - var folderDao = _daoFactory.GetFolderDao(); - var fileDao = _daoFactory.GetFileDao(); + var folderDao = _daoFactory.GetFolderDao(); + var folderThirdPartyDao = _daoFactory.GetFolderDao(); + var fileDao = _daoFactory.GetFileDao(); + var thirdPartyFileDao = _daoFactory.GetFileDao(); + var securityDao = _daoFactory.GetSecurityDao(); + var entries = new List(); - var rootFoldersIds = searchArea == SearchArea.Active ? new[] { await _globalFolder.GetFolderVirtualRoomsAsync(_daoFactory) } : - searchArea == SearchArea.Archive ? new[] { await _globalFolder.GetFolderArchiveAsync(_daoFactory) } : - new[] { await _globalFolder.GetFolderVirtualRoomsAsync(_daoFactory), await _globalFolder.GetFolderArchiveAsync(_daoFactory) }; + var currentUserSubjects = GetUserSubjects(_authContext.CurrentAccount.ID); + var currentUsersRecords = await securityDao.GetSharesAsync(currentUserSubjects).ToListAsync(); - var roomsIds = new Dictionary(); - var recordGroup = records.GroupBy(r => new { r.EntryId, r.EntryType }, (key, group) => new + var roomsIds = new Dictionary(); + var thirdPartyRoomsIds = new Dictionary(); + + var recordGroup = currentUsersRecords.GroupBy(r => new { r.EntryId, r.EntryType }, (key, group) => new { - firstRecord = group.OrderBy(r => r, new SubjectComparer(subjects)) + firstRecord = group.OrderBy(r => r, new SubjectComparer(currentUserSubjects)) .ThenByDescending(r => r.Share, new FileShareRecord.ShareComparer()) .First() }); - if (proivdersIds.Any()) - { - foreach (var id in proivdersIds) - { - roomsIds.Add(id, FileShare.None); - } - } - foreach (var record in recordGroup.Where(r => r.firstRecord.Share != FileShare.Restrict)) { - if (!roomsIds.ContainsKey((T)record.firstRecord.EntryId) && record.firstRecord.EntryType == FileEntryType.Folder) + if (record.firstRecord.EntryType != FileEntryType.Folder) { - roomsIds.Add((T)record.firstRecord.EntryId, record.firstRecord.Share); + continue; + } + + switch (record.firstRecord.EntryId) + { + case int roomId when !roomsIds.ContainsKey(roomId): + roomsIds.Add(roomId, record.firstRecord.Share); + break; + case string thirdPartyRoomId when !thirdPartyRoomsIds.ContainsKey(thirdPartyRoomId): + thirdPartyRoomsIds.Add(thirdPartyRoomId, record.firstRecord.Share); + break; } } - Func, bool> filter = f => + var rootFoldersIds = searchArea switch { - var id = f.FileEntryType == FileEntryType.Folder ? f.Id : f.ParentId; - - if (searchArea == SearchArea.Archive && f.RootFolderType == FolderType.Archive) - { - f.Access = roomsIds.TryGetValue(id, out var share) ? share : FileShare.None; - return true; - } - if (searchArea == SearchArea.Active && f.RootFolderType == FolderType.VirtualRooms) - { - f.Access = roomsIds.TryGetValue(id, out var share) ? share : FileShare.None; - return true; - } - if (searchArea == SearchArea.Any && (f.RootFolderType == FolderType.VirtualRooms || f.RootFolderType == FolderType.Archive)) - { - f.Access = roomsIds.TryGetValue(id, out var share) ? share : FileShare.None; - return true; - } - - return false; + SearchArea.Active => new[] { await _globalFolder.GetFolderVirtualRoomsAsync(_daoFactory) }, + SearchArea.Archive => new[] { await _globalFolder.GetFolderArchiveAsync(_daoFactory) }, + _ => new[] { await _globalFolder.GetFolderVirtualRoomsAsync(_daoFactory), await _globalFolder.GetFolderArchiveAsync(_daoFactory) } }; - var fileEntries = await folderDao.GetRoomsAsync(rootFoldersIds, roomsIds.Keys, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries) - .Where(filter).ToListAsync(); - - await SetTagsAsync(fileEntries); - await SetPinAsync(fileEntries); - - entries.AddRange(fileEntries); - + var rooms = await folderDao.GetRoomsAsync(rootFoldersIds, roomsIds.Keys, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries) + .Where(r => Filter(r, roomsIds)).ToListAsync(); + var thirdPartyRooms = await folderThirdPartyDao.GetFakeRoomsAsync(rootFoldersIds.Select(id => id.ToString()), thirdPartyRoomsIds.Keys, filterType, + tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries) + .Where(r => Filter(r, thirdPartyRoomsIds)).ToListAsync(); + if (withSubfolders && filterType != FilterType.FoldersOnly) { - List> files; + List> files; + List> thirdPartyFiles; if (!string.IsNullOrEmpty(search)) { - files = await fileDao.GetFilesAsync(roomsIds.Keys, FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); + files = await fileDao.GetFilesAsync(rooms.Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); + thirdPartyFiles = await thirdPartyFileDao.GetFilesAsync(thirdPartyRooms.Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); } else { - files = await fileDao.GetFilesAsync(fileEntries.OfType>().Where(f => DocSpaceHelper.IsRoom(f.FolderType)).Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); + files = await fileDao.GetFilesAsync(rooms.Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); + thirdPartyFiles = await thirdPartyFileDao.GetFilesAsync(thirdPartyRooms.Select(r => r.Id), FilterType.None, false, Guid.Empty, search, searchInContent).ToListAsync(); } - entries.AddRange(files.Where(filter)); + entries.AddRange(files.Where(f => Filter(f, roomsIds))); + entries.AddRange(thirdPartyFiles.Where(f => Filter(f, thirdPartyRoomsIds))); + } + + await SetTagsAsync(rooms); + await SetTagsAsync(thirdPartyRooms); + await SetPinAsync(rooms); + await SetPinAsync(thirdPartyRooms); + + entries.AddRange(rooms); + entries.AddRange(thirdPartyRooms); + + bool Filter(FileEntry entry, IReadOnlyDictionary accesses) + { + var id = entry.FileEntryType == FileEntryType.Folder ? entry.Id : entry.ParentId; + + switch (searchArea) + { + case SearchArea.Archive when entry.RootFolderType == FolderType.Archive: + { + entry.Access = accesses.TryGetValue(id, out var share) ? share : FileShare.None; + return true; + } + case SearchArea.Active when entry.RootFolderType == FolderType.VirtualRooms: + { + entry.Access = accesses.TryGetValue(id, out var share) ? share : FileShare.None; + return true; + } + case SearchArea.Any when (entry.RootFolderType == FolderType.VirtualRooms || entry.RootFolderType == FolderType.Archive): + { + entry.Access = accesses.TryGetValue(id, out var share) ? share : FileShare.None; + return true; + } + default: + return false; + } } return entries; @@ -1555,11 +1506,16 @@ public class FileSecurity : IFileSecurity { if (!isUser) { - if (isDocSpaceAdmin || (isRoom && entry.CreateBy == userId)) + if (isDocSpaceAdmin) { return true; } + if (isRoom) + { + return entry.CreateBy == userId; + } + var myRoom = await _daoFactory.GetFolderDao().GetParentFoldersAsync(entry.ParentId) .Where(f => DocSpaceHelper.IsRoom(f.FolderType) && f.CreateBy == userId).FirstOrDefaultAsync(); diff --git a/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFolderDao.cs index 57f44f2d8b..3344be42c6 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFolderDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/Box/BoxFolderDao.cs @@ -74,15 +74,15 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao return GetRootFolderAsync(fileId); } - public IAsyncEnumerable> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, - bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + public async IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, + bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) { if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.Box)) { - return AsyncEnumerable.Empty>(); + yield break; } - var rooms = GetFoldersAsync(parentId); + var rooms = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); rooms = FilterByRoomType(rooms, filterType); rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); @@ -92,32 +92,13 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao rooms = rooms.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); } - rooms = FilterByTags(rooms, withoutTags, tags); + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); + rooms = FilterByTags(rooms, withoutTags, tags, filesDbContext); - return rooms; - } - - public IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, - bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) - { - if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.Box)) + await foreach (var room in rooms) { - return AsyncEnumerable.Empty>(); + yield return room; } - - var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); - - folders = FilterByRoomType(folders, filterType); - folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); - - if (!string.IsNullOrEmpty(searchText)) - { - folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); - } - - folders = FilterByTags(folders, withoutTags, tags); - - return folders; } public async IAsyncEnumerable> GetFoldersAsync(string parentId) @@ -466,6 +447,11 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao } else { + if (DocSpaceHelper.IsRoom(folder.FolderType)) + { + await DaoSelector.RenameProviderAsync(ProviderInfo, newTitle); + } + newTitle = await GetAvailableTitleAsync(newTitle, parentFolderId, IsExistAsync); //rename folder @@ -529,4 +515,4 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize); } -} +} diff --git a/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFolderDao.cs index 895460458d..e5296c5985 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFolderDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFolderDao.cs @@ -77,14 +77,14 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao return GetRootFolderAsync(fileId); } - public IAsyncEnumerable> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + public async IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) { if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.DropBox)) { - return AsyncEnumerable.Empty>(); + yield break; } - var rooms = GetFoldersAsync(parentId); + var rooms = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); rooms = FilterByRoomType(rooms, filterType); rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); @@ -94,31 +94,13 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao rooms = rooms.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); } - rooms = FilterByTags(rooms, withoutTags, tags); + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); + rooms = FilterByTags(rooms, withoutTags, tags, filesDbContext); - return rooms; - } - - public IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) - { - if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.DropBox)) + await foreach (var room in rooms) { - return AsyncEnumerable.Empty>(); + yield return room; } - - var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); - - folders = FilterByRoomType(folders, filterType); - folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); - - if (!string.IsNullOrEmpty(searchText)) - { - folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); - } - - folders = FilterByTags(folders, withoutTags, tags); - - return folders; } public async IAsyncEnumerable> GetFoldersAsync(string parentId) @@ -459,6 +441,11 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao } else { + if (DocSpaceHelper.IsRoom(folder.FolderType)) + { + await DaoSelector.RenameProviderAsync(ProviderInfo, newTitle); + } + newTitle = await GetAvailableTitleAsync(newTitle, parentFolderPath, IsExistAsync); //rename folder @@ -519,4 +506,4 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize); } -} +} diff --git a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs index 5a4cf25c1d..f6f7bec8de 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs @@ -74,14 +74,15 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao return GetRootFolderAsync(""); } - public IAsyncEnumerable> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + public async IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, + IEnumerable subjectEntriesIds) { if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.GoogleDrive)) { - return AsyncEnumerable.Empty>(); + yield break; } - var rooms = GetFoldersAsync(parentId); + var rooms = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); rooms = FilterByRoomType(rooms, filterType); rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); @@ -91,32 +92,13 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao rooms = rooms.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); } - rooms = FilterByTags(rooms, withoutTags, tags); + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); + rooms = FilterByTags(rooms, withoutTags, tags, filesDbContext); - return rooms; - } - - public IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, - IEnumerable subjectEntriesIds) - { - if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.GoogleDrive)) + await foreach (var room in rooms) { - return AsyncEnumerable.Empty>(); + yield return room; } - - var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); - - folders = FilterByRoomType(folders, filterType); - folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); - - if (!string.IsNullOrEmpty(searchText)) - { - folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); - } - - folders = FilterByTags(folders, withoutTags, tags); - - return folders; } public async IAsyncEnumerable> GetFoldersAsync(string parentId) @@ -458,6 +440,11 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao } else { + if (DocSpaceHelper.IsRoom(folder.FolderType)) + { + await DaoSelector.RenameProviderAsync(ProviderInfo, newTitle); + } + //rename folder driveFolder.Name = newTitle; var storage = await ProviderInfo.StorageAsync; @@ -521,4 +508,4 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize); } -} +} diff --git a/products/ASC.Files/Core/Core/Thirdparty/IThirdPartyProviderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/IThirdPartyProviderDao.cs index b2417cb427..a5d73a7a73 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/IThirdPartyProviderDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/IThirdPartyProviderDao.cs @@ -108,7 +108,7 @@ internal abstract class ThirdPartyProviderDao { return null; } - + public string GetUniqFilePath(File file, string fileTitle) { throw new NotImplementedException(); @@ -189,7 +189,7 @@ internal abstract class ThirdPartyProviderDao { return null; } - + public string GetFolderIDPhotos(bool createIfNotExists) { return null; @@ -246,6 +246,136 @@ internal abstract class ThirdPartyProviderDao throw new NotImplementedException(); } + public IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, + bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + { + return AsyncEnumerable.Empty>(); + } + + public virtual IAsyncEnumerable> GetFakeRoomsAsync(IEnumerable parentsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, + bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + { + return AsyncEnumerable.Empty>(); + } + + public virtual IAsyncEnumerable> GetFakeRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, + Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, + IEnumerable subjectEntriesIds) + { + return AsyncEnumerable.Empty>(); + } + + protected static IAsyncEnumerable> FilterRoomsAsync(IAsyncEnumerable> rooms, ProviderFilter provider, FilterType filterType, Guid subjectId, + bool excludeSubject, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds, string searchText, bool withoutTags, IEnumerable tags, + FilesDbContext filesDbContext) + { + rooms = FilterByProvidersAsync(rooms, provider); + rooms = FilterByRoomType(rooms, filterType); + rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); + rooms = FilterByTitle(rooms, searchText); + rooms = FilterByTags(rooms, withoutTags, tags, filesDbContext); + + return rooms; + } + + protected static IAsyncEnumerable> FilterByTags(IAsyncEnumerable> rooms, bool withoutTags, IEnumerable tags, FilesDbContext filesDbContext) + { + if (withoutTags) + { + return rooms.Join(filesDbContext.ThirdpartyIdMapping.ToAsyncEnumerable(), f => f.Id, m => m.Id, (folder, map) => new { folder, map.HashId }) + .WhereAwait(async r => !await filesDbContext.TagLink.Join(filesDbContext.Tag, l => l.TagId, t => t.Id, (link, tag) => new { link.EntryId, tag }) + .Where(r => r.tag.Type == TagType.Custom).ToAsyncEnumerable().AnyAsync(t => t.EntryId == r.HashId)) + .Select(r => r.folder); + } + + if (tags == null || !tags.Any()) + { + return rooms; + } + + var filtered = rooms.Join(filesDbContext.ThirdpartyIdMapping.ToAsyncEnumerable(), f => f.Id, m => m.Id, (folder, map) => new { folder, map.HashId }) + .Join(filesDbContext.TagLink.ToAsyncEnumerable(), r => r.HashId, t => t.EntryId, (result, tag) => new { result.folder, tag.TagId }) + .Join(filesDbContext.Tag.ToAsyncEnumerable(), r => r.TagId, t => t.Id, (result, tagInfo) => new { result.folder, tagInfo.Name }) + .Where(r => tags.Contains(r.Name)) + .Select(r => r.folder); + + return filtered; + } + + protected static IAsyncEnumerable> FilterByProvidersAsync(IAsyncEnumerable> rooms, ProviderFilter providerFilter) + { + if (providerFilter == ProviderFilter.None) + { + return rooms; + } + + var filter = providerFilter switch + { + ProviderFilter.WebDav => new[] { ProviderTypes.WebDav.ToStringFast() }, + ProviderFilter.GoogleDrive => new[] { ProviderTypes.GoogleDrive.ToStringFast() }, + ProviderFilter.OneDrive => new[] { ProviderTypes.OneDrive.ToStringFast() }, + ProviderFilter.DropBox => new[] { ProviderTypes.DropBox.ToStringFast(), ProviderTypes.DropboxV2.ToStringFast() }, + ProviderFilter.kDrive => new[] { ProviderTypes.kDrive.ToStringFast() }, + ProviderFilter.Yandex => new[] { ProviderTypes.Yandex.ToStringFast() }, + ProviderFilter.SharePoint => new[] { ProviderTypes.SharePoint.ToStringFast() }, + ProviderFilter.Box => new[] { ProviderTypes.Box.ToStringFast() }, + _ => throw new NotImplementedException() + }; + + return rooms.Where(f => filter.Contains(f.ProviderKey)); + } + + protected static IAsyncEnumerable> FilterByRoomType(IAsyncEnumerable> rooms, FilterType filterType) + { + if (filterType is FilterType.None or FilterType.FoldersOnly) + { + return rooms; + } + + var typeFilter = filterType switch + { + FilterType.FillingFormsRooms => FolderType.FillingFormsRoom, + FilterType.EditingRooms => FolderType.EditingRoom, + FilterType.ReviewRooms => FolderType.ReviewRoom, + FilterType.ReadOnlyRooms => FolderType.ReadOnlyRoom, + FilterType.CustomRooms => FolderType.CustomRoom, + _ => FolderType.DEFAULT, + }; + + return rooms.Where(f => f.FolderType == typeFilter); + } + + protected static IAsyncEnumerable> FilterBySubject(IAsyncEnumerable> rooms, Guid subjectId, bool excludeSubject, SubjectFilter subjectFilter, + IEnumerable subjectEntriesIds) + { + if (subjectId == Guid.Empty) + { + return rooms; + } + + if (subjectFilter == SubjectFilter.Owner) + { + return excludeSubject ? rooms.Where(f => f != null && f.CreateBy != subjectId) : rooms.Where(f => f != null && f.CreateBy == subjectId); + } + if (subjectFilter == SubjectFilter.Member) + { + return excludeSubject ? rooms.Where(f => f != null && f.CreateBy != subjectId && !subjectEntriesIds.Contains(f.Id)) + : rooms.Where(f => f != null && (f.CreateBy == subjectId || subjectEntriesIds.Contains(f.Id))); + } + + return rooms; + } + + protected static IAsyncEnumerable> FilterByTitle(IAsyncEnumerable> rooms, string text) + { + if (string.IsNullOrEmpty(text)) + { + return rooms; + } + + return rooms.Where(x => x.Title.IndexOf(text, StringComparison.OrdinalIgnoreCase) != -1); + } + #endregion } @@ -264,7 +394,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo protected RegexDaoSelectorBase DaoSelector { get; set; } protected T ProviderInfo { get; set; } protected string PathPrefix { get; private set; } - + protected abstract string Id { get; } protected ThirdPartyProviderDao( @@ -290,14 +420,14 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo TenantID = tenantManager.GetCurrentTenant().Id; _authContext = authContext; } - + public void Init(BaseProviderInfo providerInfo, RegexDaoSelectorBase selectorBase) { ProviderInfo = providerInfo.ProviderInfo; PathPrefix = providerInfo.PathPrefix; DaoSelector = selectorBase; } - + protected IQueryable Query(DbSet set) where TSet : class, IDbFile { return set.Where(r => r.TenantId == TenantID); @@ -309,7 +439,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo { return null; } - + return InternalMappingIDAsync(id, saveIfNotExist); } @@ -337,52 +467,52 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo HashId = result, TenantId = TenantID }; - + await filesDbContext.ThirdpartyIdMapping.AddAsync(newMapping); await filesDbContext.SaveChangesAsync(); } return result; } - + protected Folder GetFolder() { var folder = _serviceProvider.GetService>(); - + InitFileEntry(folder); - + folder.FolderType = FolderType.DEFAULT; folder.Shareable = false; folder.FilesCount = 0; folder.FoldersCount = 0; - + return folder; } - + protected Folder GetErrorFolder(ErrorEntry entry) { var folder = GetFolder(); - + InitFileEntryError(folder, entry); - + folder.ParentId = null; - + return folder; } - + protected File GetFile() { var file = _serviceProvider.GetService>(); - + InitFileEntry(file); - + file.Access = FileShare.None; file.Shared = false; file.Version = 1; - + return file; } - + protected File GetErrorFile(ErrorEntry entry) { var file = GetFile(); @@ -390,7 +520,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo return file; } - + protected void InitFileEntry(FileEntry fileEntry) { fileEntry.CreateBy = ProviderInfo.Owner; @@ -401,7 +531,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo fileEntry.RootFolderType = ProviderInfo.RootFolderType; fileEntry.RootId = MakeId(); } - + protected void InitFileEntryError(FileEntry fileEntry, ErrorEntry entry) { fileEntry.Id = MakeId(entry.ErrorId); @@ -422,70 +552,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo folder.FolderType = ProviderInfo.FolderType; } } - - protected IAsyncEnumerable> FilterByTags(IAsyncEnumerable> folders, bool withoutTags, IEnumerable tagNames) - { - var filesDbContext = _dbContextFactory.CreateDbContext(); - if (withoutTags) - { - return folders.Join(filesDbContext.ThirdpartyIdMapping.ToAsyncEnumerable(), f => f.Id, m => m.Id, (folder, map) => new { folder, map.HashId }) - .WhereAwait(async r => !await filesDbContext.TagLink.Join(filesDbContext.Tag, l => l.TagId, t => t.Id, (link, tag) => new { link.EntryId, tag }) - .Where(r => r.tag.Type == TagType.Custom).ToAsyncEnumerable().AnyAsync(t => t.EntryId == r.HashId)) - .Select(r => r.folder); - } - if (tagNames == null || !tagNames.Any()) - { - return folders; - } - - var filtered = folders.Join(filesDbContext.ThirdpartyIdMapping.ToAsyncEnumerable(), f => f.Id, m => m.Id, (folder, map) => new { folder, map.HashId }) - .Join(filesDbContext.TagLink.ToAsyncEnumerable(), r => r.HashId, t => t.EntryId, (result, tag) => new { result.folder, tag.TagId }) - .Join(filesDbContext.Tag.ToAsyncEnumerable(), r => r.TagId, t => t.Id, (result, tagInfo) => new { result.folder, tagInfo.Name }) - .Where(r => tagNames.Contains(r.Name)) - .Select(r => r.folder); - - return filtered; - } - - protected IAsyncEnumerable> FilterByRoomType(IAsyncEnumerable> rooms, FilterType filterType) - { - if (filterType == FilterType.None || filterType == FilterType.FoldersOnly) - { - return rooms; - } - - var filter = filterType switch - { - FilterType.FillingFormsRooms => FolderType.FillingFormsRoom, - FilterType.EditingRooms => FolderType.EditingRoom, - FilterType.ReviewRooms => FolderType.ReviewRoom, - FilterType.ReadOnlyRooms => FolderType.ReadOnlyRoom, - FilterType.CustomRooms => FolderType.CustomRoom, - _ => FolderType.DEFAULT, - }; - - return rooms.Where(f => f != null && (f.FolderType == filter || filter == FolderType.DEFAULT)); - } - - protected IAsyncEnumerable> FilterBySubject(IAsyncEnumerable> rooms, Guid subjectId, bool excludeSubject, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds = null) - { - if (subjectId != Guid.Empty) - { - if (subjectFilter == SubjectFilter.Owner) - { - rooms = excludeSubject ? rooms.Where(f => f != null && f.CreateBy != subjectId) : rooms.Where(f => f != null && f.CreateBy == subjectId); - } - else if (subjectFilter == SubjectFilter.Member) - { - rooms = excludeSubject ? rooms.Where(f => f != null && f.CreateBy != subjectId && !subjectEntriesIds.Contains(f.Id)) - : rooms.Where(f => f != null && (f.CreateBy == subjectId || subjectEntriesIds.Contains(f.Id))); - } - } - - return rooms; - } - protected bool CheckInvalidFilter(FilterType filterType) { return filterType is @@ -500,7 +567,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo FilterType.ArchiveOnly or FilterType.MediaOnly; } - + protected abstract string MakeId(string path = null); @@ -529,7 +596,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo { return null; } - + public IAsyncEnumerable GetPureShareRecordsAsync(FileEntry entry) { return null; @@ -598,7 +665,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo { return AsyncEnumerable.Empty(); } - + public IAsyncEnumerable GetTagsInfoAsync(string searchText, TagType tagType, bool byName, int from = 0, int count = 0) { return AsyncEnumerable.Empty(); @@ -613,27 +680,27 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo { return Task.FromResult(tagInfo); } - + public Task> SaveTags(IEnumerable tag, Guid createdBy = default) { return Task.FromResult(Enumerable.Empty()); } - + public Task> SaveTags(Tag tag) { return Task.FromResult(Enumerable.Empty()); } - + public Task UpdateNewTags(IEnumerable tag, Guid createdBy = default) { return Task.CompletedTask; } - + public Task UpdateNewTags(Tag tag) { return Task.CompletedTask; } - + public Task RemoveTagsAsync(FileEntry entry, IEnumerable tagsIds) { return Task.CompletedTask; @@ -643,12 +710,12 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo { return Task.CompletedTask; } - + public Task RemoveTags(IEnumerable tag) { return Task.CompletedTask; } - + public Task RemoveTags(Tag tag) { return Task.CompletedTask; @@ -658,7 +725,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo { return AsyncEnumerable.Empty(); } - + public void MarkAsNew(Guid subject, FileEntry fileEntry) { } @@ -666,23 +733,23 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo public async IAsyncEnumerable GetNewTagsAsync(Guid subject, Folder parentFolder, bool deepSearch) { var folderId = DaoSelector.ConvertId(parentFolder.Id); - + var filesDbContext = _dbContextFactory.CreateDbContext(); var entryIDs = await filesDbContext.ThirdpartyIdMapping .Where(r => r.Id.StartsWith(PathPrefix)) .Select(r => r.HashId) .ToListAsync(); - + if (!entryIDs.Any()) { yield break; } - + var q = from r in filesDbContext.Tag from l in filesDbContext.TagLink.Where(a => a.TenantId == r.TenantId && a.TagId == r.Id).DefaultIfEmpty() where r.TenantId == TenantID && l.TenantId == TenantID && r.Type == TagType.New && entryIDs.Contains(l.EntryId) select new { tag = r, tagLink = l }; - + if (subject != Guid.Empty) { q = q.Where(r => r.tag.Owner == subject); @@ -692,7 +759,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo .Distinct() .AsAsyncEnumerable() .ToListAsync(); - + var tags = new List(); foreach (var r in qList) @@ -700,7 +767,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo tags.Add(new Tag { Name = r.tag.Name, - Type = r.tag.Type, + Type = r.tag.Type, Owner = r.tag.Owner, EntryId = await MappingIDAsync(r.tagLink.EntryId), EntryType = r.tagLink.EntryType, @@ -709,16 +776,16 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo }); } - + if (deepSearch) { foreach (var e in tags) { yield return e; - } + } yield break; } - + var folderFileIds = new[] { parentFolder.Id } .Concat(await GetChildrenAsync(folderId)); @@ -731,7 +798,7 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo protected abstract Task> GetChildrenAsync(string folderId); #endregion - + public void Dispose() { if (ProviderInfo != null) @@ -741,12 +808,12 @@ internal abstract class ThirdPartyProviderDao : ThirdPartyProviderDao, IDispo } } } - + internal class ErrorEntry { public string Error { get; set; } public string ErrorId { get; set; } - + public ErrorEntry(string error, string errorId) { Error = error; @@ -759,16 +826,16 @@ public class TagLink public int TenantId { get; set; } public int Id { get; set; } } - + public class TagLinkComparer : IEqualityComparer { public bool Equals([AllowNull] TagLink x, [AllowNull] TagLink y) { return x.Id == y.Id && x.TenantId == y.TenantId; } - + public int GetHashCode([DisallowNull] TagLink obj) { return obj.Id.GetHashCode() + obj.TenantId.GetHashCode(); } -} +} diff --git a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs index ce31ffa72a..828aacb26f 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs @@ -73,15 +73,15 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao { return GetRootFolderAsync(fileId); } - - public IAsyncEnumerable> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + + public async IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) { if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.OneDrive)) { - return AsyncEnumerable.Empty>(); + yield break; } - var rooms = GetFoldersAsync(parentId); + var rooms = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); rooms = FilterByRoomType(rooms, filterType); rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); @@ -91,31 +91,13 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao rooms = rooms.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); } - rooms = FilterByTags(rooms, withoutTags, tags); + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); + rooms = FilterByTags(rooms, withoutTags, tags, filesDbContext); - return rooms; - } - - public IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) - { - if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.OneDrive)) + await foreach (var room in rooms) { - return AsyncEnumerable.Empty>(); + yield return room; } - - var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); - - folders = FilterByRoomType(folders, filterType); - folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); - - if (!string.IsNullOrEmpty(searchText)) - { - folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); - } - - folders = FilterByTags(folders, withoutTags, tags); - - return folders; } public async IAsyncEnumerable> GetFoldersAsync(string parentId) @@ -464,6 +446,11 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao } else { + if (DocSpaceHelper.IsRoom(folder.FolderType)) + { + await DaoSelector.RenameProviderAsync(ProviderInfo, newTitle); + } + newTitle = await GetAvailableTitleAsync(newTitle, parentFolderId, IsExistAsync); //rename folder @@ -532,4 +519,4 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize); } -} +} diff --git a/products/ASC.Files/Core/Core/Thirdparty/ProviderAccountDao.cs b/products/ASC.Files/Core/Core/Thirdparty/ProviderAccountDao.cs index 8f43e934ac..450257f233 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/ProviderAccountDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/ProviderAccountDao.cs @@ -47,9 +47,9 @@ public enum ProviderTypes internal class ProviderAccountDao : IProviderDao { private int _tenantID; - protected int TenantID - { - get + protected int TenantID + { + get { if (_tenantID == 0) { @@ -80,7 +80,7 @@ internal class ProviderAccountDao : IProviderDao ConsumerFactory consumerFactory, ThirdpartyConfiguration thirdpartyConfiguration, IDbContextFactory dbContextFactory, - OAuth20TokenHelper oAuth20TokenHelper, + OAuth20TokenHelper oAuth20TokenHelper, ILoggerProvider options) { _logger = options.CreateLogger("ASC.Files"); @@ -94,24 +94,24 @@ internal class ProviderAccountDao : IProviderDao _dbContextFactory = dbContextFactory; _oAuth20TokenHelper = oAuth20TokenHelper; } - + public virtual Task GetProviderInfoAsync(int linkId) { var providersInfo = GetProvidersInfoInternalAsync(linkId); return providersInfo.SingleAsync().AsTask(); } - + public virtual IAsyncEnumerable GetProvidersInfoAsync() { return GetProvidersInfoInternalAsync(); } - + public virtual IAsyncEnumerable GetProvidersInfoAsync(FolderType folderType, string searchText = null) { return GetProvidersInfoInternalAsync(folderType: folderType, searchText: searchText); } - + public virtual IAsyncEnumerable GetProvidersInfoAsync(Guid userId) { try @@ -121,7 +121,7 @@ internal class ProviderAccountDao : IProviderDao .Where(r => r.TenantId == TenantID) .Where(r => r.UserId == userId) .AsAsyncEnumerable(); - + return thirdpartyAccounts.Select(ToProviderInfo); } catch (Exception e) @@ -141,7 +141,7 @@ internal class ProviderAccountDao : IProviderDao .Where(r => linkId == -1 || r.Id == linkId) .Where(r => folderType == FolderType.DEFAULT && !(r.FolderType == FolderType.ThirdpartyBackup && linkId == -1) || r.FolderType == folderType) .Where(r => searchText == "" || r.Title.ToLower().Contains(searchText))); - + private IAsyncEnumerable GetProvidersInfoInternalAsync(int linkId = -1, FolderType folderType = FolderType.DEFAULT, string searchText = null) { try @@ -156,7 +156,7 @@ internal class ProviderAccountDao : IProviderDao return new List().ToAsyncEnumerable(); } } - + public virtual Task SaveProviderInfoAsync(string providerKey, string customerTitle, AuthData authData, FolderType folderType) { ProviderTypes prKey; @@ -168,14 +168,14 @@ internal class ProviderAccountDao : IProviderDao { throw new ArgumentException("Unrecognize ProviderType"); } - + return InternalSaveProviderInfoAsync(providerKey, customerTitle, authData, folderType, prKey); } private async Task InternalSaveProviderInfoAsync(string providerKey, string customerTitle, AuthData authData, FolderType folderType, ProviderTypes prKey) { authData = GetEncodedAccesToken(authData, prKey); - + if (!await CheckProviderInfoAsync(ToProviderInfo(0, prKey, customerTitle, authData, _securityContext.CurrentAccount.ID, folderType, _tenantUtil.DateTimeToUtc(_tenantUtil.DateTimeNow())))) { throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, providerKey)); @@ -195,14 +195,14 @@ internal class ProviderAccountDao : IProviderDao Token = EncryptPassword(authData.Token ?? ""), Url = authData.Url ?? "" }; - + using var filesDbContext = _dbContextFactory.CreateDbContext(); var res = await filesDbContext.AddOrUpdateAsync(r => r.ThirdpartyAccount, dbFilesThirdpartyAccount); await filesDbContext.SaveChangesAsync(); return res.Id; } - + public async Task CheckProviderInfoAsync(IProviderInfo providerInfo) { return providerInfo != null && await providerInfo.CheckAccessAsync(); @@ -249,7 +249,7 @@ internal class ProviderAccountDao : IProviderDao return true; } - public async Task UpdateProviderInfoAsync(int linkId, string folderId, FolderType roomType, bool @private) + public async Task UpdateProviderInfoAsync(int linkId, string title, string folderId, FolderType roomType, bool @private) { using var filesDbContext = _dbContextFactory.CreateDbContext(); var forUpdate = await filesDbContext.ThirdpartyAccount @@ -266,12 +266,13 @@ internal class ProviderAccountDao : IProviderDao forUpdate.FolderId = folderId; forUpdate.FolderType = FolderType.VirtualRooms; forUpdate.Private = @private; + forUpdate.Title = title; await filesDbContext.SaveChangesAsync(); return true; } - + public virtual async Task UpdateProviderInfoAsync(int linkId, AuthData authData) { using var filesDbContext = _dbContextFactory.CreateDbContext(); @@ -280,7 +281,7 @@ internal class ProviderAccountDao : IProviderDao .Where(r => r.Id == linkId) .Where(r => r.TenantId == TenantID) .ToListAsync(); - + foreach (var f in forUpdate) { f.UserName = authData.Login ?? ""; @@ -288,12 +289,12 @@ internal class ProviderAccountDao : IProviderDao f.Token = EncryptPassword(authData.Token ?? ""); f.Url = authData.Url ?? ""; } - + await filesDbContext.SaveChangesAsync(); - + return forUpdate.Count == 1 ? linkId : default; } - + public virtual async Task UpdateProviderInfoAsync(int linkId, string customerTitle, AuthData newAuthData, FolderType folderType, Guid? userId = null) { using var filesDbContext = _dbContextFactory.CreateDbContext(); @@ -305,7 +306,7 @@ internal class ProviderAccountDao : IProviderDao filesDbContext.ThirdpartyAccount .Where(r => r.TenantId == TenantID) .Where(r => r.Id == linkId); - + DbFilesThirdpartyAccount input; try { @@ -316,51 +317,51 @@ internal class ProviderAccountDao : IProviderDao _logger.ErrorUpdateProviderInfo(linkId, _securityContext.CurrentAccount.ID, e); throw; } - + if (!ProviderTypesExtensions.TryParse(input.Provider, true, out var key)) { throw new ArgumentException("Unrecognize ProviderType"); } - + authData = new AuthData( !string.IsNullOrEmpty(newAuthData.Url) ? newAuthData.Url : input.Url, input.UserName, !string.IsNullOrEmpty(newAuthData.Password) ? newAuthData.Password : DecryptPassword(input.Password, linkId), newAuthData.Token); - + if (!string.IsNullOrEmpty(newAuthData.Token)) { authData = GetEncodedAccesToken(authData, key); } - + if (!await CheckProviderInfoAsync(ToProviderInfo(0, key, customerTitle, authData, _securityContext.CurrentAccount.ID, folderType, _tenantUtil.DateTimeToUtc(_tenantUtil.DateTimeNow())))) { throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, key)); - } + } } - + var toUpdate = await filesDbContext.ThirdpartyAccount .Where(r => r.Id == linkId) .Where(r => r.TenantId == TenantID) .ToListAsync(); - + foreach (var t in toUpdate) { if (!string.IsNullOrEmpty(customerTitle)) { t.Title = customerTitle; } - + if (folderType != FolderType.DEFAULT) { t.FolderType = folderType; } - + if (userId.HasValue) { t.UserId = userId.Value; } - + if (!authData.IsEmpty()) { t.UserName = authData.Login ?? ""; @@ -369,7 +370,7 @@ internal class ProviderAccountDao : IProviderDao t.Url = authData.Url ?? ""; } } - + await filesDbContext.SaveChangesAsync(); return toUpdate.Count == 1 ? linkId : default; @@ -402,16 +403,16 @@ internal class ProviderAccountDao : IProviderDao } if (newAuthData != null && !newAuthData.IsEmpty()) - { + { if (!string.IsNullOrEmpty(newAuthData.Token)) { newAuthData = GetEncodedAccesToken(newAuthData, key); } - + if (!await CheckProviderInfoAsync(ToProviderInfo(0, key, customerTitle, newAuthData, _securityContext.CurrentAccount.ID, FolderType.ThirdpartyBackup, _tenantUtil.DateTimeToUtc(_tenantUtil.DateTimeNow()))).ConfigureAwait(false)) { throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, key)); - } + } } if (!string.IsNullOrEmpty(customerTitle)) @@ -429,12 +430,12 @@ internal class ProviderAccountDao : IProviderDao thirdparty.Token = EncryptPassword(newAuthData.Token ?? ""); thirdparty.Url = newAuthData.Url ?? ""; } - + await filesDbContext.SaveChangesAsync().ConfigureAwait(false); return thirdparty.Id; } - + public virtual async Task RemoveProviderInfoAsync(int linkId) { using var filesDbContext = _dbContextFactory.CreateDbContext(); @@ -479,7 +480,7 @@ internal class ProviderAccountDao : IProviderDao await tx.CommitAsync(); }); } - + private IProviderInfo ToProviderInfo(int id, ProviderTypes providerKey, string customerTitle, AuthData authData, Guid owner, FolderType type, DateTime createOn) { var dbFilesThirdpartyAccount = new DbFilesThirdpartyAccount @@ -495,17 +496,17 @@ internal class ProviderAccountDao : IProviderDao CreateOn = createOn, Provider = providerKey.ToString() }; - + return ToProviderInfo(dbFilesThirdpartyAccount); } - + private IProviderInfo ToProviderInfo(DbFilesThirdpartyAccount input) { if (!ProviderTypesExtensions.TryParse(input.Provider, true, out var key)) { return null; } - + var id = input.Id; var providerTitle = input.Title ?? string.Empty; var token = DecryptToken(input.Token, id); @@ -517,14 +518,14 @@ internal class ProviderAccountDao : IProviderDao var createOn = _tenantUtil.DateTimeFromUtc(input.CreateOn); var authData = new AuthData(input.Url, input.UserName, DecryptPassword(input.Password, id), token); var hasLogo = input.HasLogo; - + if (key == ProviderTypes.Box) { if (string.IsNullOrEmpty(token)) { throw new ArgumentException("Token can't be null"); } - + var box = _serviceProvider.GetService(); box.ID = id; box.CustomerTitle = providerTitle; @@ -540,14 +541,14 @@ internal class ProviderAccountDao : IProviderDao return box; } - + if (key == ProviderTypes.DropboxV2) { if (string.IsNullOrEmpty(token)) { throw new ArgumentException("Token can't be null"); } - + var drop = _serviceProvider.GetService(); drop.ID = id; drop.CustomerTitle = providerTitle; @@ -560,17 +561,17 @@ internal class ProviderAccountDao : IProviderDao drop.FolderId = folderId; drop.Private = privateRoom; drop.HasLogo = hasLogo; - + return drop; } - + if (key == ProviderTypes.SharePoint) { if (!string.IsNullOrEmpty(authData.Login) && string.IsNullOrEmpty(authData.Password)) { throw new ArgumentNullException("password", "Password can't be null"); } - + var sh = _serviceProvider.GetService(); sh.ID = id; sh.CustomerTitle = providerTitle; @@ -586,14 +587,14 @@ internal class ProviderAccountDao : IProviderDao return sh; } - + if (key == ProviderTypes.GoogleDrive) { if (string.IsNullOrEmpty(token)) { throw new ArgumentException("Token can't be null"); } - + var gd = _serviceProvider.GetService(); gd.ID = id; gd.CustomerTitle = providerTitle; @@ -606,17 +607,17 @@ internal class ProviderAccountDao : IProviderDao gd.FolderId = folderId; gd.Private = privateRoom; gd.HasLogo = hasLogo; - + return gd; } - + if (key == ProviderTypes.OneDrive) { if (string.IsNullOrEmpty(token)) { throw new ArgumentException("Token can't be null"); } - + var od = _serviceProvider.GetService(); od.ID = id; od.CustomerTitle = providerTitle; @@ -629,10 +630,10 @@ internal class ProviderAccountDao : IProviderDao od.FolderId = folderId; od.Private = privateRoom; od.HasLogo = hasLogo; - + return od; } - + if (string.IsNullOrEmpty(input.Provider)) { throw new ArgumentNullException("providerKey"); @@ -647,7 +648,7 @@ internal class ProviderAccountDao : IProviderDao { throw new ArgumentNullException("password", "Password can't be null"); } - + var sharpBoxProviderInfo = _serviceProvider.GetService(); sharpBoxProviderInfo.ID = id; sharpBoxProviderInfo.CustomerTitle = providerTitle; @@ -660,116 +661,116 @@ internal class ProviderAccountDao : IProviderDao sharpBoxProviderInfo.FolderId = folderId; sharpBoxProviderInfo.Private = privateRoom; sharpBoxProviderInfo.HasLogo = hasLogo; - + return sharpBoxProviderInfo; } - + private AuthData GetEncodedAccesToken(AuthData authData, ProviderTypes provider) { string code; OAuth20Token token; - + switch (provider) { case ProviderTypes.GoogleDrive: code = authData.Token; - token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); - + token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); + if (token == null) { throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider)); } - + return new AuthData(token: token.ToJson()); - + case ProviderTypes.Box: code = authData.Token; - token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); - + token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); + if (token == null) { throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider)); } - + return new AuthData(token: token.ToJson()); - + case ProviderTypes.DropboxV2: code = authData.Token; - token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); - + token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); + if (token == null) { throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider)); } - + return new AuthData(token: token.ToJson()); - + case ProviderTypes.DropBox: - + var dropBoxRequestToken = DropBoxRequestToken.Parse(authData.Token); - + var config = CloudStorage.GetCloudConfigurationEasy(nSupportedCloudConfigurations.DropBox); var accessToken = DropBoxStorageProviderTools.ExchangeDropBoxRequestTokenIntoAccessToken(config as DropBoxConfiguration, _thirdpartyConfiguration.DropboxAppKey, _thirdpartyConfiguration.DropboxAppSecret, dropBoxRequestToken); - + var base64Token = new CloudStorage().SerializeSecurityTokenToBase64Ex(accessToken, config.GetType(), new Dictionary()); - + return new AuthData(token: base64Token); - + case ProviderTypes.OneDrive: code = authData.Token; - token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); - + token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); + if (token == null) { throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider)); } - + return new AuthData(token: token.ToJson()); - + case ProviderTypes.SkyDrive: - + code = authData.Token; - - token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); - + + token = _oAuth20TokenHelper.GetAccessToken(_consumerFactory, code); + if (token == null) { throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider)); } - + accessToken = AppLimit.CloudComputing.SharpBox.Common.Net.oAuth20.OAuth20Token.FromJson(token.ToJson()); - + if (accessToken == null) { throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider)); } - + config = CloudStorage.GetCloudConfigurationEasy(nSupportedCloudConfigurations.SkyDrive); var storage = new CloudStorage(); base64Token = storage.SerializeSecurityTokenToBase64Ex(accessToken, config.GetType(), new Dictionary()); - + return new AuthData(token: base64Token); - + case ProviderTypes.SharePoint: case ProviderTypes.WebDav: break; - + default: authData.Url = null; break; } - + return authData; } - + private string EncryptPassword(string password) { return string.IsNullOrEmpty(password) ? string.Empty : _instanceCrypto.Encrypt(password); } - + private string DecryptPassword(string password, int id) { try @@ -782,7 +783,7 @@ internal class ProviderAccountDao : IProviderDao return null; } } - + private string DecryptToken(string token, int id) { try @@ -808,4 +809,4 @@ public static class ProviderAccountDaoExtension services.TryAdd(); services.TryAdd(); } -} +} diff --git a/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs index b5d638499e..0a549341a8 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs @@ -30,6 +30,10 @@ namespace ASC.Files.Thirdparty.ProviderDao; internal class ProviderFolderDao : ProviderDaoBase, IFolderDao { private readonly SetupInfo _setupInfo; + private readonly GlobalFolderHelper _globalFolderHelper; + private readonly IProviderDao _providerDao; + private readonly IDbContextFactory _dbContextFactory; + private readonly AuthContext _authContext; public ProviderFolderDao( SetupInfo setupInfo, @@ -37,10 +41,18 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao TenantManager tenantManager, SecurityDao securityDao, TagDao tagDao, - CrossDao crossDao) + CrossDao crossDao, + GlobalFolderHelper globalFolderHelper, + IProviderDao providerDao, + IDbContextFactory dbContextFactory, + AuthContext authContext) : base(serviceProvider, tenantManager, securityDao, tagDao, crossDao) { _setupInfo = setupInfo; + _globalFolderHelper = globalFolderHelper; + _providerDao = providerDao; + _dbContextFactory = dbContextFactory; + _authContext = authContext; } public Task> GetFolderAsync(string folderId) @@ -85,20 +97,6 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao return folderDao.GetRootFolderByFileAsync(selector.ConvertId(fileId)); } - public async IAsyncEnumerable> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) - { - var selector = GetSelector(parentId); - var folderDao = selector.GetFolderDao(parentId); - var rooms = folderDao.GetRoomsAsync(selector.ConvertId(parentId), filterType, tags, subjectId, searchText, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntriesIds); - - var result = await FilterByProvider(rooms.Where(r => r != null), provider).ToListAsync(); - - foreach (var r in result) - { - yield return r; - } - } - public IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) { var result = AsyncEnumerable.Empty>(); @@ -108,10 +106,10 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao var selectorLocal = selector; var matchedIds = roomsIds.Where(selectorLocal.IsMatch).ToList(); - if (matchedIds.Count == 0) - { - continue; - } + if (matchedIds.Count == 0) + { + continue; + } result = result.Concat(matchedIds.GroupBy(selectorLocal.GetIdCode) .ToAsyncEnumerable() @@ -129,6 +127,51 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao return result.Distinct(); } + public override async IAsyncEnumerable> GetFakeRoomsAsync(IEnumerable parentsIds, FilterType filterType, IEnumerable tags, Guid subjectId, + string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + { + var virtualRoomsFolderId = await _globalFolderHelper.GetFolderVirtualRooms(); + var archiveFolderId = await _globalFolderHelper.GetFolderArchive(); + + var rooms = GetProvidersAsync(parentsIds, virtualRoomsFolderId, archiveFolderId).Where(p => !string.IsNullOrEmpty(p.FolderId)) + .Select(r => ToFakeRoom(r, virtualRoomsFolderId, archiveFolderId)); + + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); + + rooms = FilterRoomsAsync(rooms, provider, filterType, subjectId, excludeSubject, subjectFilter, subjectEntriesIds, searchText, withoutTags, tags, filesDbContext); + + await foreach (var room in rooms) + { + yield return room; + } + } + + public override async IAsyncEnumerable> GetFakeRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, + Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, + IEnumerable subjectEntriesIds) + { + if (!roomsIds.Any()) + { + yield break; + } + + var virtualRoomsFolderId = await _globalFolderHelper.GetFolderVirtualRooms(); + var archiveFolderId = await _globalFolderHelper.GetFolderArchive(); + + var rooms = GetProvidersAsync(parentsIds, virtualRoomsFolderId, archiveFolderId) + .Where(p => !string.IsNullOrEmpty(p.FolderId) && (p.Owner == _authContext.CurrentAccount.ID || roomsIds.Contains(p.FolderId))) + .Select(r => ToFakeRoom(r, virtualRoomsFolderId, archiveFolderId)); + + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); + + rooms = FilterRoomsAsync(rooms, provider, filterType, subjectId, excludeSubject, subjectFilter, subjectEntriesIds, searchText, withoutTags, tags, filesDbContext); + + await foreach (var room in rooms) + { + yield return room; + } + } + public IAsyncEnumerable> GetFoldersAsync(string parentId) { var selector = GetSelector(parentId); @@ -160,10 +203,10 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao var selectorLocal = selector; var matchedIds = folderIds.Where(selectorLocal.IsMatch).ToList(); - if (matchedIds.Count == 0) - { - continue; - } + if (matchedIds.Count == 0) + { + continue; + } result = result.Concat(matchedIds.GroupBy(selectorLocal.GetIdCode) .ToAsyncEnumerable() @@ -321,18 +364,18 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao public Task> CanMoveOrCopyAsync(string[] folderIds, string to) { - if (folderIds.Length == 0) - { - return Task.FromResult>(new Dictionary()); - } + if (folderIds.Length == 0) + { + return Task.FromResult>(new Dictionary()); + } var selector = GetSelector(to); var matchedIds = folderIds.Where(selector.IsMatch).ToArray(); - if (matchedIds.Length == 0) - { - return Task.FromResult>(new Dictionary()); - } + if (matchedIds.Length == 0) + { + return Task.FromResult>(new Dictionary()); + } return InternalCanMoveOrCopyAsync(to, matchedIds, selector); } @@ -447,4 +490,52 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao return folders.Where(x => providerKey == x.ProviderKey); } -} + + private async IAsyncEnumerable GetProvidersAsync(IEnumerable parentsIds, string virtualRoomsFolderId, string archiveFolderId) + { + IAsyncEnumerable providers; + + if (parentsIds.Count() > 1) + { + providers = _providerDao.GetProvidersInfoAsync(FolderType.VirtualRooms); + providers = providers.Concat(_providerDao.GetProvidersInfoAsync(FolderType.Archive)); + } + else if (parentsIds.FirstOrDefault() == virtualRoomsFolderId) + { + providers = _providerDao.GetProvidersInfoAsync(FolderType.VirtualRooms); + } + else + { + providers = _providerDao.GetProvidersInfoAsync(FolderType.Archive); + } + + await foreach (var provider in providers) + { + yield return provider; + } + } + + private Folder ToFakeRoom(IProviderInfo providerInfo, string roomsFolderId, string archiveFolderId) + { + var rootId = providerInfo.RootFolderType == FolderType.VirtualRooms ? roomsFolderId : archiveFolderId; + + var folder = _serviceProvider.GetRequiredService>(); + folder.Id = providerInfo.FolderId; + folder.ParentId = rootId; + folder.RootCreateBy = providerInfo.Owner; + folder.CreateBy = providerInfo.Owner; + folder.ProviderKey = providerInfo.ProviderKey; + folder.RootId = rootId; + folder.Title = providerInfo.CustomerTitle; + folder.CreateOn = providerInfo.CreateOn; + folder.FileEntryType = FileEntryType.Folder; + folder.FolderType = providerInfo.FolderType; + folder.ProviderId = providerInfo.ID; + folder.RootFolderType = providerInfo.RootFolderType; + folder.HasLogo = providerInfo.HasLogo; + folder.ModifiedBy = providerInfo.Owner; + folder.ModifiedOn = providerInfo.CreateOn; + + return folder; + } +} diff --git a/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs b/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs index ce1cd4f79f..9c91aa9d52 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs @@ -159,7 +159,7 @@ internal abstract class RegexDaoSelectorBase : IDaoSelector where T : clas public async Task UpdateProviderFolderId(T provider, string id) { var dbDao = _serviceProvider.GetService(); - await dbDao.UpdateProviderInfoAsync(provider.ID, id, provider.FolderType, provider.Private); + await dbDao.UpdateProviderInfoAsync(provider.ID, provider.CustomerTitle, id, provider.FolderType, provider.Private); provider.FolderId = id; } diff --git a/products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointFolderDao.cs index d5b26d0ca6..cb18e56852 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointFolderDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointFolderDao.cs @@ -80,14 +80,14 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao return Task.FromResult(ProviderInfo.ToFolder(ProviderInfo.RootFolder)); } - public IAsyncEnumerable> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) - { + public async IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + { if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.SharePoint)) { - return AsyncEnumerable.Empty>(); + yield break; } - var rooms = GetFoldersAsync(parentId); + var rooms = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); rooms = FilterByRoomType(rooms, filterType); rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); @@ -97,31 +97,13 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao rooms = rooms.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); } - rooms = FilterByTags(rooms, withoutTags, tags); + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); + rooms = FilterByTags(rooms, withoutTags, tags, filesDbContext); - return rooms; - } - - public IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) - { - if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.SharePoint)) + await foreach (var room in rooms) { - return AsyncEnumerable.Empty>(); + yield return room; } - - var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); - - folders = FilterByRoomType(folders, filterType); - folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); - - if (!string.IsNullOrEmpty(searchText)) - { - folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); - } - - folders = FilterByTags(folders, withoutTags, tags); - - return folders; } public async IAsyncEnumerable> GetFoldersAsync(string parentId) @@ -402,9 +384,14 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao { newFolderId = (string)await ProviderInfo.RenameFolderAsync(folder.Id, newTitle); - if (DocSpaceHelper.IsRoom(ProviderInfo.FolderType) && ProviderInfo.FolderId != null && ProviderInfo.FolderId == oldId) + if (DocSpaceHelper.IsRoom(ProviderInfo.FolderType) && ProviderInfo.FolderId != null) { - await DaoSelector.UpdateProviderFolderId(ProviderInfo, newFolderId); + await DaoSelector.RenameProviderAsync(ProviderInfo, newTitle); + + if (ProviderInfo.FolderId == oldId) + { + await DaoSelector.UpdateProviderFolderId(ProviderInfo, newFolderId); + } } } @@ -455,4 +442,4 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao { return Task.FromResult(2L * 1024L * 1024L * 1024L); } -} +} diff --git a/products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFolderDao.cs b/products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFolderDao.cs index fdadca38d5..ee76538fd8 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFolderDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFolderDao.cs @@ -78,15 +78,16 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao { return Task.FromResult(ToFolder(RootFolder())); } - - public IAsyncEnumerable> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) + + public async IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, + SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) { if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.kDrive && provider != ProviderFilter.WebDav && provider != ProviderFilter.Yandex)) { - return AsyncEnumerable.Empty>(); + yield break; } - var rooms = GetFoldersAsync(parentId); + var rooms = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); rooms = FilterByRoomType(rooms, filterType); rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); @@ -96,32 +97,13 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao rooms = rooms.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); } - rooms = FilterByTags(rooms, withoutTags, tags); + var filesDbContext = await _dbContextFactory.CreateDbContextAsync(); + rooms = FilterByTags(rooms, withoutTags, tags, filesDbContext); - return rooms; - } - - public IAsyncEnumerable> GetRoomsAsync(IEnumerable parentsIds, IEnumerable roomsIds, FilterType filterType, IEnumerable tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, - SubjectFilter subjectFilter, IEnumerable subjectEntriesIds) - { - if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.kDrive && provider != ProviderFilter.WebDav && provider != ProviderFilter.Yandex)) + await foreach (var room in rooms) { - return AsyncEnumerable.Empty>(); + yield return room; } - - var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false)); - - folders = FilterByRoomType(folders, filterType); - folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds); - - if (!string.IsNullOrEmpty(searchText)) - { - folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1); - } - - folders = FilterByTags(folders, withoutTags, tags); - - return folders; } public IAsyncEnumerable> GetFoldersAsync(string parentId) @@ -461,9 +443,14 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao //var newFolder = SharpBoxProviderInfo.Storage.GetFileSystemObject(newTitle, folder.Parent); newId = MakeId(entry); - if (DocSpaceHelper.IsRoom(ProviderInfo.FolderType) && ProviderInfo.FolderId != null && ProviderInfo.FolderId == oldId) + if (DocSpaceHelper.IsRoom(ProviderInfo.FolderType) && ProviderInfo.FolderId != null) { - await DaoSelector.UpdateProviderFolderId(ProviderInfo, newId); + await DaoSelector.RenameProviderAsync(ProviderInfo, newTitle); + + if (ProviderInfo.FolderId == oldId) + { + await DaoSelector.UpdateProviderFolderId(ProviderInfo, newId); + } } } } @@ -522,4 +509,4 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao return Task.FromResult(chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize)); } -} +} diff --git a/products/ASC.Files/Core/Core/VirtualRooms/RoomLogoManager.cs b/products/ASC.Files/Core/Core/VirtualRooms/RoomLogoManager.cs index 0772559555..c04b7c48ab 100644 --- a/products/ASC.Files/Core/Core/VirtualRooms/RoomLogoManager.cs +++ b/products/ASC.Files/Core/Core/VirtualRooms/RoomLogoManager.cs @@ -1,334 +1,344 @@ -// (c) Copyright Ascensio System SIA 2010-2022 -// -// This program is a free software product. -// You can redistribute it and/or modify it under the terms -// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software -// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended -// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of -// any third-party rights. -// -// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see -// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html -// -// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. -// -// The interactive user interfaces in modified source and object code versions of the Program must -// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. -// -// Pursuant to Section 7(b) of the License you must retain the original Product logo when -// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under -// trademark law for use of our trademarks. -// -// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing -// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 -// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - -using Image = SixLabors.ImageSharp.Image; - -namespace ASC.Files.Core.VirtualRooms; - -[Scope] -public class RoomLogoManager -{ - private const string LogosPath = "{0}_{1}.png"; - private const string ModuleName = "room_logos"; - private const string TempDomainPath = "logos_temp"; - - private static (SizeName, Size) _originalLogoSize = (SizeName.Original, new Size(1280, 1280)); - private static (SizeName, Size) _largeLogoSize = (SizeName.Large, new Size(96, 96)); - private static (SizeName, Size) _mediumLogoSize = (SizeName.Medium, new Size(32, 32)); - private static (SizeName, Size) _smallLogoSize = (SizeName.Small, new Size(16, 16)); - - private readonly IDaoFactory _daoFactory; - private readonly FileSecurity _fileSecurity; +// (c) Copyright Ascensio System SIA 2010-2022 +// +// This program is a free software product. +// You can redistribute it and/or modify it under the terms +// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software +// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended +// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of +// any third-party rights. +// +// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see +// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html +// +// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. +// +// The interactive user interfaces in modified source and object code versions of the Program must +// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. +// +// Pursuant to Section 7(b) of the License you must retain the original Product logo when +// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under +// trademark law for use of our trademarks. +// +// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing +// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 +// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + +using Image = SixLabors.ImageSharp.Image; + +namespace ASC.Files.Core.VirtualRooms; + +[Scope] +public class RoomLogoManager +{ + private const string LogosPath = "{0}_{1}.png"; + private const string ModuleName = "room_logos"; + private const string TempDomainPath = "logos_temp"; + + private static (SizeName, Size) _originalLogoSize = (SizeName.Original, new Size(1280, 1280)); + private static (SizeName, Size) _largeLogoSize = (SizeName.Large, new Size(96, 96)); + private static (SizeName, Size) _mediumLogoSize = (SizeName.Medium, new Size(32, 32)); + private static (SizeName, Size) _smallLogoSize = (SizeName.Small, new Size(16, 16)); + + private readonly IDaoFactory _daoFactory; + private readonly FileSecurity _fileSecurity; private readonly ILogger _logger; - private readonly StorageFactory _storageFactory; - private readonly TenantManager _tenantManager; - private IDataStore _dataStore; - private readonly FilesMessageService _filesMessageService; - private readonly IHttpContextAccessor _httpContextAccessor; - - public RoomLogoManager( - StorageFactory storageFactory, - TenantManager tenantManager, - IDaoFactory daoFactory, - FileSecurity fileSecurity, - ILogger logger, - FilesMessageService filesMessageService, - IHttpContextAccessor httpContextAccessor) + private readonly StorageFactory _storageFactory; + private readonly TenantManager _tenantManager; + private IDataStore _dataStore; + private readonly FilesMessageService _filesMessageService; + private readonly IHttpContextAccessor _httpContextAccessor; + + public RoomLogoManager( + StorageFactory storageFactory, + TenantManager tenantManager, + IDaoFactory daoFactory, + FileSecurity fileSecurity, + ILogger logger, + FilesMessageService filesMessageService, + IHttpContextAccessor httpContextAccessor) { - _storageFactory = storageFactory; - _tenantManager = tenantManager; - _daoFactory = daoFactory; - _fileSecurity = fileSecurity; - _logger = logger; - _filesMessageService = filesMessageService; - _httpContextAccessor = httpContextAccessor; - } - - public bool EnableAudit { get; set; } = true; - private IDataStore DataStore => _dataStore ??= _storageFactory.GetStorage(TenantId, ModuleName); - private int TenantId => _tenantManager.GetCurrentTenant().Id; - private IDictionary Headers => _httpContextAccessor?.HttpContext?.Request?.Headers; - - public async Task> CreateAsync(T id, string tempFile, int x, int y, int width, int height) - { - var folderDao = _daoFactory.GetFolderDao(); - var room = await folderDao.GetFolderAsync(id); - - if (string.IsNullOrEmpty(tempFile)) - { - return room; - } - - if (room == null || !DocSpaceHelper.IsRoom(room.FolderType)) - { - throw new ItemNotFoundException("Virtual room not found"); - } - - if (room.RootFolderType == FolderType.Archive || !await _fileSecurity.CanEditRoomAsync(room)) - { - throw new InvalidOperationException("You don't have permission to edit the room"); - } - - var fileName = Path.GetFileName(tempFile); - var data = await GetTempAsync(fileName); - - id = GetId(room); - - await SaveWithProcessAsync(id, data, -1, new Point(x, y), new Size(width, height)); - await RemoveTempAsync(fileName); - - room.HasLogo = true; - - if (room.ProviderEntry) - { - await _daoFactory.ProviderDao.UpdateProviderInfoAsync(room.ProviderId, true); - } - else - { - await folderDao.SaveFolderAsync(room); + _storageFactory = storageFactory; + _tenantManager = tenantManager; + _daoFactory = daoFactory; + _fileSecurity = fileSecurity; + _logger = logger; + _filesMessageService = filesMessageService; + _httpContextAccessor = httpContextAccessor; + } + + public bool EnableAudit { get; set; } = true; + private IDataStore DataStore => _dataStore ??= _storageFactory.GetStorage(TenantId, ModuleName); + private int TenantId => _tenantManager.GetCurrentTenant().Id; + private IDictionary Headers => _httpContextAccessor?.HttpContext?.Request?.Headers; + + public async Task> CreateAsync(T id, string tempFile, int x, int y, int width, int height) + { + var folderDao = _daoFactory.GetFolderDao(); + var room = await folderDao.GetFolderAsync(id); + + if (string.IsNullOrEmpty(tempFile)) + { + return room; } - - if (EnableAudit) - { - _filesMessageService.Send(room, Headers, MessageAction.RoomLogoCreated); - } - - return room; - } - - public async Task> DeleteAsync(T id, bool checkPermissions = true) - { - var folderDao = _daoFactory.GetFolderDao(); - var room = await folderDao.GetFolderAsync(id); - - if (checkPermissions && !await _fileSecurity.CanEditRoomAsync(room)) - { - throw new InvalidOperationException("You don't have permission to edit the room"); - } - - id = GetId(room); - - try - { - await DataStore.DeleteFilesAsync(string.Empty, $"{ProcessFolderId(id)}*.*", false); - room.HasLogo = false; - - if (room.ProviderEntry) - { - await _daoFactory.ProviderDao.UpdateProviderInfoAsync(room.ProviderId, false); - } - else - { - await folderDao.SaveFolderAsync(room); + + if (room == null || !DocSpaceHelper.IsRoom(room.FolderType)) + { + throw new ItemNotFoundException("Virtual room not found"); + } + + if (room.RootFolderType == FolderType.Archive || !await _fileSecurity.CanEditRoomAsync(room)) + { + throw new InvalidOperationException("You don't have permission to edit the room"); + } + + var fileName = Path.GetFileName(tempFile); + var data = await GetTempAsync(fileName); + + var stringId = GetId(room); + + await SaveWithProcessAsync(stringId, data, -1, new Point(x, y), new Size(width, height)); + await RemoveTempAsync(fileName); + + room.HasLogo = true; + + if (room.ProviderEntry) + { + await _daoFactory.ProviderDao.UpdateProviderInfoAsync(room.ProviderId, true); + } + else + { + await folderDao.SaveFolderAsync(room); + } + + if (EnableAudit) + { + _filesMessageService.Send(room, Headers, MessageAction.RoomLogoCreated); + } + + return room; + } + + public async Task> DeleteAsync(T id, bool checkPermissions = true) + { + var folderDao = _daoFactory.GetFolderDao(); + var room = await folderDao.GetFolderAsync(id); + + if (checkPermissions && !await _fileSecurity.CanEditRoomAsync(room)) + { + throw new InvalidOperationException("You don't have permission to edit the room"); + } + + var stringId = GetId(room); + + try + { + await DataStore.DeleteFilesAsync(string.Empty, $"{ProcessFolderId(stringId)}*.*", false); + room.HasLogo = false; + + if (room.ProviderEntry) + { + await _daoFactory.ProviderDao.UpdateProviderInfoAsync(room.ProviderId, false); } - - if (EnableAudit) - { - _filesMessageService.Send(room, Headers, MessageAction.RoomLogoDeleted); - } - } - catch (Exception e) - { - _logger.ErrorRemoveRoomLogo(e); - } - - return room; - } - - public async ValueTask GetLogoAsync(Folder room) - { - if (!room.HasLogo) - { - return new Logo - { - Original = string.Empty, - Large = string.Empty, - Medium = string.Empty, + else + { + await folderDao.SaveFolderAsync(room); + } + + if (EnableAudit) + { + _filesMessageService.Send(room, Headers, MessageAction.RoomLogoDeleted); + } + } + catch (Exception e) + { + _logger.ErrorRemoveRoomLogo(e); + } + + return room; + } + + public async ValueTask GetLogoAsync(Folder room) + { + if (!room.HasLogo) + { + return new Logo + { + Original = string.Empty, + Large = string.Empty, + Medium = string.Empty, Small = string.Empty, - }; - } - - var id = GetId(room); - - var cacheKey = Math.Abs(room.ModifiedOn.GetHashCode()); - - return new Logo() - { - Original = await GetLogoPathAsync(id, SizeName.Original) + $"?_={cacheKey}", - Large = await GetLogoPathAsync(id, SizeName.Large) + $"?_={cacheKey}", - Medium = await GetLogoPathAsync(id, SizeName.Medium) + $"?_={cacheKey}", - Small = await GetLogoPathAsync(id, SizeName.Small) + $"?_={cacheKey}" - }; - } - - public async Task SaveTempAsync(byte[] data, long maxFileSize) - { - data = UserPhotoThumbnailManager.TryParseImage(data, maxFileSize, _originalLogoSize.Item2, out _, out _, out _); - - var fileName = $"{Guid.NewGuid()}.png"; - - using var stream = new MemoryStream(data); - var path = await DataStore.SaveAsync(TempDomainPath, fileName, stream); - - var pathAsString = path.ToString(); - - var pathWithoutQuery = pathAsString; - - if (pathAsString.IndexOf('?') > 0) - { - pathWithoutQuery = pathAsString.Substring(0, pathAsString.IndexOf('?')); - } - - return pathWithoutQuery; - } - - public async Task RemoveTempAsync(string fileName) - { - var index = fileName.LastIndexOf('.'); - var fileNameWithoutExt = (index != -1) ? fileName.Substring(0, index) : fileName; - - try - { - await DataStore.DeleteFilesAsync(TempDomainPath, "", fileNameWithoutExt + "*.*", false); - } - catch (Exception e) - { - _logger.ErrorRemoveTempPhoto(e); - } - } - - private async Task SaveWithProcessAsync(T id, byte[] imageData, long maxFileSize, Point position, Size cropSize) - { - imageData = UserPhotoThumbnailManager.TryParseImage(imageData, maxFileSize, _originalLogoSize.Item2, out var _, out var _, out var _); - - var fileName = string.Format(LogosPath, ProcessFolderId(id), SizeName.Original.ToStringLowerFast()); - - if (imageData == null || imageData.Length == 0) - { - return string.Empty; - } - - using var stream = new MemoryStream(imageData); - var path = await DataStore.SaveAsync(fileName, stream); - - await ResizeAndSaveAsync(id, imageData, maxFileSize, _mediumLogoSize, position, cropSize); - await ResizeAndSaveAsync(id, imageData, maxFileSize, _smallLogoSize, position, cropSize); - await ResizeAndSaveAsync(id, imageData, maxFileSize, _largeLogoSize, position, cropSize); - - return path.ToString(); - } - - private async Task ResizeAndSaveAsync(T id, byte[] data, long maxFileSize, (SizeName, Size) size, Point position, Size cropSize) - { - if (data == null || data.Length <= 0) - { - throw new Web.Core.Users.UnknownImageFormatException(); - } - if (maxFileSize != -1 && data.Length > maxFileSize) - { - throw new ImageWeightLimitException(); - } - - try - { - using var stream = new MemoryStream(data); - using var img = Image.Load(stream, out var format); - var imgFormat = format; - - if (size.Item2 != img.Size()) - { - using var img2 = UserPhotoThumbnailManager.GetImage(img, size.Item2, new UserPhotoThumbnailSettings(position, cropSize)); - data = CommonPhotoManager.SaveToBytes(img2); - } - else - { - data = CommonPhotoManager.SaveToBytes(img); - } - - var extension = CommonPhotoManager.GetImgFormatName(imgFormat); - var fileName = string.Format(LogosPath, ProcessFolderId(id), size.Item1.ToStringLowerFast()); - - using var stream2 = new MemoryStream(data); - await DataStore.SaveAsync(fileName, stream2); - } - catch (ArgumentException error) - { - throw new Web.Core.Users.UnknownImageFormatException(error); - } - } - - private async ValueTask GetLogoPathAsync(T id, SizeName size) - { - var fileName = string.Format(LogosPath, ProcessFolderId(id), size.ToStringLowerFast()); - var uri = await DataStore.GetUriAsync(fileName); - - return uri.ToString(); - } - - private async Task GetTempAsync(string fileName) - { - using var stream = await DataStore.GetReadStreamAsync(TempDomainPath, fileName); - - var data = new MemoryStream(); - var buffer = new byte[1024 * 10]; - while (true) - { - var count = await stream.ReadAsync(buffer, 0, buffer.Length); - if (count == 0) - { - break; - } - - data.Write(buffer, 0, count); - } - - return data.ToArray(); - } - - private string ProcessFolderId(T id) - { - ArgumentNullException.ThrowIfNull(id, nameof(id)); - - return id.GetType() != typeof(string) - ? id.ToString() - : id.ToString()?.Replace("-", "").Replace("|", ""); - } - - private T GetId(Folder room) - { - return room.ProviderEntry && (room.RootId.ToString().Contains("sbox") - || room.RootId.ToString().Contains("spoint")) ? room.RootId : room.Id; - } -} - -[EnumExtensions] -public enum SizeName -{ - Original = 0, - Large = 1, - Medium = 2, - Small = 3, + }; + } + + var id = GetId(room); + + var cacheKey = Math.Abs(room.ModifiedOn.GetHashCode()); + + return new Logo + { + Original = await GetLogoPathAsync(id, SizeName.Original) + $"?_={cacheKey}", + Large = await GetLogoPathAsync(id, SizeName.Large) + $"?_={cacheKey}", + Medium = await GetLogoPathAsync(id, SizeName.Medium) + $"?_={cacheKey}", + Small = await GetLogoPathAsync(id, SizeName.Small) + $"?_={cacheKey}" + }; + } + + public async Task SaveTempAsync(byte[] data, long maxFileSize) + { + data = UserPhotoThumbnailManager.TryParseImage(data, maxFileSize, _originalLogoSize.Item2, out _, out _, out _); + + var fileName = $"{Guid.NewGuid()}.png"; + + using var stream = new MemoryStream(data); + var path = await DataStore.SaveAsync(TempDomainPath, fileName, stream); + + var pathAsString = path.ToString(); + + var pathWithoutQuery = pathAsString; + + if (pathAsString.IndexOf('?') > 0) + { + pathWithoutQuery = pathAsString.Substring(0, pathAsString.IndexOf('?')); + } + + return pathWithoutQuery; + } + + private async Task RemoveTempAsync(string fileName) + { + var index = fileName.LastIndexOf('.'); + var fileNameWithoutExt = (index != -1) ? fileName.Substring(0, index) : fileName; + + try + { + await DataStore.DeleteFilesAsync(TempDomainPath, "", fileNameWithoutExt + "*.*", false); + } + catch (Exception e) + { + _logger.ErrorRemoveTempPhoto(e); + } + } + + private async Task SaveWithProcessAsync(string id, byte[] imageData, long maxFileSize, Point position, Size cropSize) + { + imageData = UserPhotoThumbnailManager.TryParseImage(imageData, maxFileSize, _originalLogoSize.Item2, out var _, out var _, out var _); + + var fileName = string.Format(LogosPath, ProcessFolderId(id), SizeName.Original.ToStringLowerFast()); + + if (imageData == null || imageData.Length == 0) + { + return; + } + + using var stream = new MemoryStream(imageData); + await DataStore.SaveAsync(fileName, stream); + + await ResizeAndSaveAsync(id, imageData, maxFileSize, _mediumLogoSize, position, cropSize); + await ResizeAndSaveAsync(id, imageData, maxFileSize, _smallLogoSize, position, cropSize); + await ResizeAndSaveAsync(id, imageData, maxFileSize, _largeLogoSize, position, cropSize); + } + + private async Task ResizeAndSaveAsync(T id, byte[] data, long maxFileSize, (SizeName, Size) size, Point position, Size cropSize) + { + if (data is not { Length: > 0 }) + { + throw new Web.Core.Users.UnknownImageFormatException(); + } + if (maxFileSize != -1 && data.Length > maxFileSize) + { + throw new ImageWeightLimitException(); + } + + try + { + using var stream = new MemoryStream(data); + using var img = Image.Load(stream, out _); + + if (size.Item2 != img.Size()) + { + using var img2 = UserPhotoThumbnailManager.GetImage(img, size.Item2, new UserPhotoThumbnailSettings(position, cropSize)); + data = CommonPhotoManager.SaveToBytes(img2); + } + else + { + data = CommonPhotoManager.SaveToBytes(img); + } + + var fileName = string.Format(LogosPath, ProcessFolderId(id), size.Item1.ToStringLowerFast()); + + using var stream2 = new MemoryStream(data); + await DataStore.SaveAsync(fileName, stream2); + } + catch (ArgumentException error) + { + throw new Web.Core.Users.UnknownImageFormatException(error); + } + } + + private async ValueTask GetLogoPathAsync(T id, SizeName size) + { + var fileName = string.Format(LogosPath, ProcessFolderId(id), size.ToStringLowerFast()); + var uri = await DataStore.GetUriAsync(fileName); + + return uri.ToString(); + } + + private async Task GetTempAsync(string fileName) + { + await using var stream = await DataStore.GetReadStreamAsync(TempDomainPath, fileName); + + var data = new MemoryStream(); + var buffer = new byte[1024 * 10]; + while (true) + { + var count = await stream.ReadAsync(buffer); + if (count == 0) + { + break; + } + + await data.WriteAsync(buffer.AsMemory(0, count)); + } + + return data.ToArray(); + } + + private static string ProcessFolderId(T id) + { + ArgumentNullException.ThrowIfNull(id, nameof(id)); + + return id.GetType() != typeof(string) + ? id.ToString() + : id.ToString()?.Replace("-", "").Replace("|", ""); + } + + private static string GetId(Folder room) + { + if (!room.ProviderEntry) + { + return room.Id.ToString(); + } + + if (room.Id.ToString()!.Contains("sbox")) + { + return $"sbox-{room.ProviderId}"; + } + + if (room.Id.ToString()!.Contains("spoint")) + { + return $"spoint-{room.ProviderId}"; + } + + return room.Id.ToString(); + } +} + +[EnumExtensions] +public enum SizeName +{ + Original = 0, + Large = 1, + Medium = 2, + Small = 3, } \ No newline at end of file