Files: optimized getting thirdparty rooms

This commit is contained in:
Maksim Chegulov 2023-01-29 23:43:52 +03:00
parent a2ee750e45
commit ce8d3b3471
17 changed files with 977 additions and 911 deletions

View File

@ -57,12 +57,19 @@ public interface IFolderDao<T>
/// <returns>root folder</returns>
Task<Folder<T>> GetRootFolderByFileAsync(T fileId);
IAsyncEnumerable<Folder<T>> GetRoomsAsync(T parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders,
IAsyncEnumerable<Folder<T>> GetRoomsAsync(IEnumerable<T> parentsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders,
bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds);
IAsyncEnumerable<Folder<T>> GetRoomsAsync(IEnumerable<T> parentsIds, IEnumerable<T> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders,
bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds);
IAsyncEnumerable<Folder<T>> GetFakeRoomsAsync(IEnumerable<T> parentsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText,
bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds);
IAsyncEnumerable<Folder<T>> GetFakeRoomsAsync(IEnumerable<T> parentsIds, IEnumerable<T> roomsIds, FilterType filterType, IEnumerable<string> tags,
Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
IEnumerable<string> subjectEntriesIds);
/// <summary>
/// Get a list of folders in current folder.
/// </summary>

View File

@ -36,7 +36,7 @@ public interface IProviderDao
Task<int> SaveProviderInfoAsync(string providerKey, string customerTitle, AuthData authData, FolderType folderType);
Task<bool> UpdateProviderInfoAsync(int linkId, FolderType rootFolderType);
Task<bool> UpdateProviderInfoAsync(int linkId, bool hasLogo);
Task<bool> UpdateProviderInfoAsync(int linkId, string folderId, FolderType folderType, bool @private);
Task<bool> UpdateProviderInfoAsync(int linkId, string title, string folderId, FolderType folderType, bool @private);
Task<int> UpdateProviderInfoAsync(int linkId, string customerTitle, AuthData authData, FolderType folderType, Guid? userId = null);
Task<int> UpdateBackupProviderInfoAsync(string providerKey, string customerTitle, AuthData authData);
Task RemoveProviderInfoAsync(int linkId);

View File

@ -38,6 +38,7 @@ public interface IProviderInfo : IDisposable
string RootFolderId { get; }
string FolderId { get; set; }
bool Private { get; }
bool HasLogo { get; }
Task<bool> CheckAccessAsync();
Task InvalidateStorageAsync();

View File

@ -159,13 +159,13 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
return _mapper.Map<DbFolderQuery, Folder<int>>(dbFolder);
}
public IAsyncEnumerable<Folder<int>> GetFoldersAsync(int parentId)
{
return GetFoldersAsync(parentId, default, FilterType.None, false, default, string.Empty);
}
public async IAsyncEnumerable<Folder<int>> GetRoomsAsync(int parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
public async IAsyncEnumerable<Folder<int>> GetRoomsAsync(IEnumerable<int> parentsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || provider != ProviderFilter.None)
@ -178,11 +178,11 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
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<int>
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<int>
yield return q;
}
}
public IAsyncEnumerable<Folder<int>> GetFakeRoomsAsync(IEnumerable<int> parentsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText,
bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
return AsyncEnumerable.Empty<Folder<int>>();
}
public IAsyncEnumerable<Folder<int>> GetFakeRoomsAsync(IEnumerable<int> parentsIds, IEnumerable<int> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId,
string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
return AsyncEnumerable.Empty<Folder<int>>();
}
private async IAsyncEnumerable<int> GetTenantsWithFeeds(DateTime fromTime, Expression<Func<DbFolder, bool>> filter, bool includeSecurity)
{

View File

@ -560,7 +560,7 @@ public class FileStorageService<T> //: 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;
}

View File

@ -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<FileEntry>();
var rooms = await GetVirtualRoomsForUserAsync(currentUsersRecords.Where(r => r.EntryId is int), Array.Empty<int>(), 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<IEnumerable<string>> GetThirdpartyRoomsIdsAsync(SearchArea searchArea)
{
var result = new List<string>();
if (_userManager.IsUser(_authContext.CurrentAccount.ID))
{
return Array.Empty<string>();
}
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<List<FileEntry>> GetVirtualRoomsForDocSpaceAdminAsync(FilterType filterType, Guid subjectId, string search, bool searchInContent, bool withSubfolders,
SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntries)
private async Task<List<FileEntry>> GetAllVirtualRoomsAsync(FilterType filterType, Guid subjectId, string search, bool searchInContent, bool withSubfolders,
SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
IEnumerable<string> subjectEntries)
{
var folderDao = _daoFactory.GetFolderDao<int>();
var folderThirdPartyDao = _daoFactory.GetFolderDao<string>();
var fileDao = _daoFactory.GetFileDao<int>();
var fileThirdPartyDao = _daoFactory.GetFileDao<string>();
var providerDao = _daoFactory.ProviderDao;
var entries = new List<FileEntry>();
var foldersInt = new List<FileEntry<int>>();
var foldersString = new List<FileEntry<string>>();
if (searchArea is SearchArea.Any or SearchArea.Active)
var rootFoldersIds = searchArea switch
{
var roomsFolderId = await _globalFolder.GetFolderVirtualRoomsAsync<int>(_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<string>(), thirdPartyRoomsIds, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries)
.ToListAsync();
foldersInt.AddRange(roomsEntries);
foldersString.AddRange(thirdPartyRoomsEntries);
if (withSubfolders && filterType != FilterType.FoldersOnly)
{
List<File<int>> files;
List<File<string>> 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<int>(_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<string>(), thirdPartyRoomsIds, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries)
.ToListAsync();
foldersInt.AddRange(roomsEntries);
foldersString.AddRange(thirdPartyRoomsEntries);
if (withSubfolders && filterType != FilterType.FoldersOnly)
List<File<int>> files;
List<File<string>> thirdPartyFiles;
if (!string.IsNullOrEmpty(search))
{
List<File<int>> files;
List<File<string>> 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<List<FileEntry>> GetVirtualRoomsForUserAsync<T>(IEnumerable<FileShareRecord> records, IEnumerable<T> proivdersIds, List<Guid> subjects, FilterType filterType, Guid subjectId, string search,
bool searchInContent, bool withSubfolders, SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntries)
private async Task<List<FileEntry>> GetVirtualRoomsForMeAsync(FilterType filterType, Guid subjectId, string search, bool searchInContent, bool withSubfolders,
SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntries)
{
var folderDao = _daoFactory.GetFolderDao<T>();
var fileDao = _daoFactory.GetFileDao<T>();
var folderDao = _daoFactory.GetFolderDao<int>();
var folderThirdPartyDao = _daoFactory.GetFolderDao<string>();
var fileDao = _daoFactory.GetFileDao<int>();
var thirdPartyFileDao = _daoFactory.GetFileDao<string>();
var securityDao = _daoFactory.GetSecurityDao<int>();
var entries = new List<FileEntry>();
var rootFoldersIds = searchArea == SearchArea.Active ? new[] { await _globalFolder.GetFolderVirtualRoomsAsync<T>(_daoFactory) } :
searchArea == SearchArea.Archive ? new[] { await _globalFolder.GetFolderArchiveAsync<T>(_daoFactory) } :
new[] { await _globalFolder.GetFolderVirtualRoomsAsync<T>(_daoFactory), await _globalFolder.GetFolderArchiveAsync<T>(_daoFactory) };
var currentUserSubjects = GetUserSubjects(_authContext.CurrentAccount.ID);
var currentUsersRecords = await securityDao.GetSharesAsync(currentUserSubjects).ToListAsync();
var roomsIds = new Dictionary<T, FileShare>();
var recordGroup = records.GroupBy(r => new { r.EntryId, r.EntryType }, (key, group) => new
var roomsIds = new Dictionary<int, FileShare>();
var thirdPartyRoomsIds = new Dictionary<string, FileShare>();
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<FileEntry<T>, 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<File<T>> files;
List<File<int>> files;
List<File<string>> 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<Folder<T>>().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<T>(FileEntry<T> entry, IReadOnlyDictionary<T, FileShare> 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<T>().GetParentFoldersAsync(entry.ParentId)
.Where(f => DocSpaceHelper.IsRoom(f.FolderType) && f.CreateBy == userId).FirstOrDefaultAsync();

View File

@ -74,15 +74,15 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
return GetRootFolderAsync(fileId);
}
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders,
bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
public async IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText,
bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.Box))
{
return AsyncEnumerable.Empty<Folder<string>>();
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<string>
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<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText,
bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.Box))
await foreach (var room in rooms)
{
return AsyncEnumerable.Empty<Folder<string>>();
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<Folder<string>> GetFoldersAsync(string parentId)
@ -466,6 +447,11 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
}
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<string>
return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize);
}
}
}

View File

@ -77,14 +77,14 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
return GetRootFolderAsync(fileId);
}
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
public async IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.DropBox))
{
return AsyncEnumerable.Empty<Folder<string>>();
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<string>
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<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.DropBox))
await foreach (var room in rooms)
{
return AsyncEnumerable.Empty<Folder<string>>();
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<Folder<string>> GetFoldersAsync(string parentId)
@ -459,6 +441,11 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
}
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<string>
return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize);
}
}
}

View File

@ -74,14 +74,15 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
return GetRootFolderAsync("");
}
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
public async IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.GoogleDrive))
{
return AsyncEnumerable.Empty<Folder<string>>();
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<string>
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<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.GoogleDrive))
await foreach (var room in rooms)
{
return AsyncEnumerable.Empty<Folder<string>>();
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<Folder<string>> GetFoldersAsync(string parentId)
@ -458,6 +440,11 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
}
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<string>
return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize);
}
}
}

View File

@ -108,7 +108,7 @@ internal abstract class ThirdPartyProviderDao
{
return null;
}
public string GetUniqFilePath(File<string> 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<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText,
bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
return AsyncEnumerable.Empty<Folder<string>>();
}
public virtual IAsyncEnumerable<Folder<string>> GetFakeRoomsAsync(IEnumerable<string> parentsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText,
bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
return AsyncEnumerable.Empty<Folder<string>>();
}
public virtual IAsyncEnumerable<Folder<string>> GetFakeRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags,
Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
IEnumerable<string> subjectEntriesIds)
{
return AsyncEnumerable.Empty<Folder<string>>();
}
protected static IAsyncEnumerable<Folder<string>> FilterRoomsAsync(IAsyncEnumerable<Folder<string>> rooms, ProviderFilter provider, FilterType filterType, Guid subjectId,
bool excludeSubject, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds, string searchText, bool withoutTags, IEnumerable<string> 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<Folder<string>> FilterByTags(IAsyncEnumerable<Folder<string>> rooms, bool withoutTags, IEnumerable<string> 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<Folder<string>> FilterByProvidersAsync(IAsyncEnumerable<Folder<string>> 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<Folder<string>> FilterByRoomType(IAsyncEnumerable<Folder<string>> 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<Folder<string>> FilterBySubject(IAsyncEnumerable<Folder<string>> rooms, Guid subjectId, bool excludeSubject, SubjectFilter subjectFilter,
IEnumerable<string> 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<Folder<string>> FilterByTitle(IAsyncEnumerable<Folder<string>> 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<T> : ThirdPartyProviderDao, IDispo
protected RegexDaoSelectorBase<T> 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<T> : ThirdPartyProviderDao, IDispo
TenantID = tenantManager.GetCurrentTenant().Id;
_authContext = authContext;
}
public void Init(BaseProviderInfo<T> providerInfo, RegexDaoSelectorBase<T> selectorBase)
{
ProviderInfo = providerInfo.ProviderInfo;
PathPrefix = providerInfo.PathPrefix;
DaoSelector = selectorBase;
}
protected IQueryable<TSet> Query<TSet>(DbSet<TSet> set) where TSet : class, IDbFile
{
return set.Where(r => r.TenantId == TenantID);
@ -309,7 +439,7 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
{
return null;
}
return InternalMappingIDAsync(id, saveIfNotExist);
}
@ -337,52 +467,52 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
HashId = result,
TenantId = TenantID
};
await filesDbContext.ThirdpartyIdMapping.AddAsync(newMapping);
await filesDbContext.SaveChangesAsync();
}
return result;
}
protected Folder<string> GetFolder()
{
var folder = _serviceProvider.GetService<Folder<string>>();
InitFileEntry(folder);
folder.FolderType = FolderType.DEFAULT;
folder.Shareable = false;
folder.FilesCount = 0;
folder.FoldersCount = 0;
return folder;
}
protected Folder<string> GetErrorFolder(ErrorEntry entry)
{
var folder = GetFolder();
InitFileEntryError(folder, entry);
folder.ParentId = null;
return folder;
}
protected File<string> GetFile()
{
var file = _serviceProvider.GetService<File<string>>();
InitFileEntry(file);
file.Access = FileShare.None;
file.Shared = false;
file.Version = 1;
return file;
}
protected File<string> GetErrorFile(ErrorEntry entry)
{
var file = GetFile();
@ -390,7 +520,7 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
return file;
}
protected void InitFileEntry(FileEntry<string> fileEntry)
{
fileEntry.CreateBy = ProviderInfo.Owner;
@ -401,7 +531,7 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
fileEntry.RootFolderType = ProviderInfo.RootFolderType;
fileEntry.RootId = MakeId();
}
protected void InitFileEntryError(FileEntry<string> fileEntry, ErrorEntry entry)
{
fileEntry.Id = MakeId(entry.ErrorId);
@ -422,70 +552,7 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
folder.FolderType = ProviderInfo.FolderType;
}
}
protected IAsyncEnumerable<Folder<string>> FilterByTags(IAsyncEnumerable<Folder<string>> folders, bool withoutTags, IEnumerable<string> 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<Folder<string>> FilterByRoomType(IAsyncEnumerable<Folder<string>> 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<Folder<string>> FilterBySubject(IAsyncEnumerable<Folder<string>> rooms, Guid subjectId, bool excludeSubject, SubjectFilter subjectFilter, IEnumerable<string> 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<T> : ThirdPartyProviderDao, IDispo
FilterType.ArchiveOnly or
FilterType.MediaOnly;
}
protected abstract string MakeId(string path = null);
@ -529,7 +596,7 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
{
return null;
}
public IAsyncEnumerable<FileShareRecord> GetPureShareRecordsAsync(FileEntry<string> entry)
{
return null;
@ -598,7 +665,7 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
{
return AsyncEnumerable.Empty<Tag>();
}
public IAsyncEnumerable<TagInfo> GetTagsInfoAsync(string searchText, TagType tagType, bool byName, int from = 0, int count = 0)
{
return AsyncEnumerable.Empty<TagInfo>();
@ -613,27 +680,27 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
{
return Task.FromResult(tagInfo);
}
public Task<IEnumerable<Tag>> SaveTags(IEnumerable<Tag> tag, Guid createdBy = default)
{
return Task.FromResult(Enumerable.Empty<Tag>());
}
public Task<IEnumerable<Tag>> SaveTags(Tag tag)
{
return Task.FromResult(Enumerable.Empty<Tag>());
}
public Task UpdateNewTags(IEnumerable<Tag> tag, Guid createdBy = default)
{
return Task.CompletedTask;
}
public Task UpdateNewTags(Tag tag)
{
return Task.CompletedTask;
}
public Task RemoveTagsAsync(FileEntry<string> entry, IEnumerable<int> tagsIds)
{
return Task.CompletedTask;
@ -643,12 +710,12 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
{
return Task.CompletedTask;
}
public Task RemoveTags(IEnumerable<Tag> tag)
{
return Task.CompletedTask;
}
public Task RemoveTags(Tag tag)
{
return Task.CompletedTask;
@ -658,7 +725,7 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
{
return AsyncEnumerable.Empty<Tag>();
}
public void MarkAsNew(Guid subject, FileEntry<string> fileEntry)
{
}
@ -666,23 +733,23 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
public async IAsyncEnumerable<Tag> GetNewTagsAsync(Guid subject, Folder<string> 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<T> : ThirdPartyProviderDao, IDispo
.Distinct()
.AsAsyncEnumerable()
.ToListAsync();
var tags = new List<Tag>();
foreach (var r in qList)
@ -700,7 +767,7 @@ internal abstract class ThirdPartyProviderDao<T> : 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<T> : 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<T> : ThirdPartyProviderDao, IDispo
protected abstract Task<IEnumerable<string>> GetChildrenAsync(string folderId);
#endregion
public void Dispose()
{
if (ProviderInfo != null)
@ -741,12 +808,12 @@ internal abstract class ThirdPartyProviderDao<T> : 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<TagLink>
{
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();
}
}
}

View File

@ -73,15 +73,15 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
{
return GetRootFolderAsync(fileId);
}
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
public async IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.OneDrive))
{
return AsyncEnumerable.Empty<Folder<string>>();
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<string>
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<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.OneDrive))
await foreach (var room in rooms)
{
return AsyncEnumerable.Empty<Folder<string>>();
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<Folder<string>> GetFoldersAsync(string parentId)
@ -464,6 +446,11 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
}
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<string>
return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize);
}
}
}

View File

@ -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<FilesDbContext> 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<IProviderInfo> GetProviderInfoAsync(int linkId)
{
var providersInfo = GetProvidersInfoInternalAsync(linkId);
return providersInfo.SingleAsync().AsTask();
}
public virtual IAsyncEnumerable<IProviderInfo> GetProvidersInfoAsync()
{
return GetProvidersInfoInternalAsync();
}
public virtual IAsyncEnumerable<IProviderInfo> GetProvidersInfoAsync(FolderType folderType, string searchText = null)
{
return GetProvidersInfoInternalAsync(folderType: folderType, searchText: searchText);
}
public virtual IAsyncEnumerable<IProviderInfo> 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<IProviderInfo> GetProvidersInfoInternalAsync(int linkId = -1, FolderType folderType = FolderType.DEFAULT, string searchText = null)
{
try
@ -156,7 +156,7 @@ internal class ProviderAccountDao : IProviderDao
return new List<IProviderInfo>().ToAsyncEnumerable();
}
}
public virtual Task<int> 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<int> 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<bool> CheckProviderInfoAsync(IProviderInfo providerInfo)
{
return providerInfo != null && await providerInfo.CheckAccessAsync();
@ -249,7 +249,7 @@ internal class ProviderAccountDao : IProviderDao
return true;
}
public async Task<bool> UpdateProviderInfoAsync(int linkId, string folderId, FolderType roomType, bool @private)
public async Task<bool> 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<int> 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<int> 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<BoxProviderInfo>();
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<DropboxProviderInfo>();
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<SharePointProviderInfo>();
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<GoogleDriveProviderInfo>();
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<OneDriveProviderInfo>();
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>();
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<GoogleLoginProvider>(_consumerFactory, code);
token = _oAuth20TokenHelper.GetAccessToken<GoogleLoginProvider>(_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<BoxLoginProvider>(_consumerFactory, code);
token = _oAuth20TokenHelper.GetAccessToken<BoxLoginProvider>(_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<DropboxLoginProvider>(_consumerFactory, code);
token = _oAuth20TokenHelper.GetAccessToken<DropboxLoginProvider>(_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<string, string>());
return new AuthData(token: base64Token);
case ProviderTypes.OneDrive:
code = authData.Token;
token = _oAuth20TokenHelper.GetAccessToken<OneDriveLoginProvider>(_consumerFactory, code);
token = _oAuth20TokenHelper.GetAccessToken<OneDriveLoginProvider>(_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<OneDriveLoginProvider>(_consumerFactory, code);
token = _oAuth20TokenHelper.GetAccessToken<OneDriveLoginProvider>(_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<string, string>());
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<OneDriveProviderInfo>();
services.TryAdd<SharpBoxProviderInfo>();
}
}
}

View File

@ -30,6 +30,10 @@ namespace ASC.Files.Thirdparty.ProviderDao;
internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
{
private readonly SetupInfo _setupInfo;
private readonly GlobalFolderHelper _globalFolderHelper;
private readonly IProviderDao _providerDao;
private readonly IDbContextFactory<FilesDbContext> _dbContextFactory;
private readonly AuthContext _authContext;
public ProviderFolderDao(
SetupInfo setupInfo,
@ -37,10 +41,18 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
TenantManager tenantManager,
SecurityDao<string> securityDao,
TagDao<string> tagDao,
CrossDao crossDao)
CrossDao crossDao,
GlobalFolderHelper globalFolderHelper,
IProviderDao providerDao,
IDbContextFactory<FilesDbContext> dbContextFactory,
AuthContext authContext)
: base(serviceProvider, tenantManager, securityDao, tagDao, crossDao)
{
_setupInfo = setupInfo;
_globalFolderHelper = globalFolderHelper;
_providerDao = providerDao;
_dbContextFactory = dbContextFactory;
_authContext = authContext;
}
public Task<Folder<string>> GetFolderAsync(string folderId)
@ -85,20 +97,6 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
return folderDao.GetRootFolderByFileAsync(selector.ConvertId(fileId));
}
public async IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> 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<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
var result = AsyncEnumerable.Empty<Folder<string>>();
@ -108,10 +106,10 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
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<string>
return result.Distinct();
}
public override async IAsyncEnumerable<Folder<string>> GetFakeRoomsAsync(IEnumerable<string> parentsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId,
string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
var virtualRoomsFolderId = await _globalFolderHelper.GetFolderVirtualRooms<string>();
var archiveFolderId = await _globalFolderHelper.GetFolderArchive<string>();
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<Folder<string>> GetFakeRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags,
Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
IEnumerable<string> subjectEntriesIds)
{
if (!roomsIds.Any())
{
yield break;
}
var virtualRoomsFolderId = await _globalFolderHelper.GetFolderVirtualRooms<string>();
var archiveFolderId = await _globalFolderHelper.GetFolderArchive<string>();
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<Folder<string>> GetFoldersAsync(string parentId)
{
var selector = GetSelector(parentId);
@ -160,10 +203,10 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
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<string>
public Task<IDictionary<string, string>> CanMoveOrCopyAsync(string[] folderIds, string to)
{
if (folderIds.Length == 0)
{
return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string>());
}
if (folderIds.Length == 0)
{
return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string>());
}
var selector = GetSelector(to);
var matchedIds = folderIds.Where(selector.IsMatch).ToArray();
if (matchedIds.Length == 0)
{
return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string>());
}
if (matchedIds.Length == 0)
{
return Task.FromResult<IDictionary<string, string>>(new Dictionary<string, string>());
}
return InternalCanMoveOrCopyAsync(to, matchedIds, selector);
}
@ -447,4 +490,52 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
return folders.Where(x => providerKey == x.ProviderKey);
}
}
private async IAsyncEnumerable<IProviderInfo> GetProvidersAsync(IEnumerable<string> parentsIds, string virtualRoomsFolderId, string archiveFolderId)
{
IAsyncEnumerable<IProviderInfo> 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<string> ToFakeRoom(IProviderInfo providerInfo, string roomsFolderId, string archiveFolderId)
{
var rootId = providerInfo.RootFolderType == FolderType.VirtualRooms ? roomsFolderId : archiveFolderId;
var folder = _serviceProvider.GetRequiredService<Folder<string>>();
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;
}
}

View File

@ -159,7 +159,7 @@ internal abstract class RegexDaoSelectorBase<T> : IDaoSelector<T> where T : clas
public async Task UpdateProviderFolderId(T provider, string id)
{
var dbDao = _serviceProvider.GetService<ProviderAccountDao>();
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;
}

View File

@ -80,14 +80,14 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
return Task.FromResult(ProviderInfo.ToFolder(ProviderInfo.RootFolder));
}
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
public async IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.SharePoint))
{
return AsyncEnumerable.Empty<Folder<string>>();
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<string>
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<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.SharePoint))
await foreach (var room in rooms)
{
return AsyncEnumerable.Empty<Folder<string>>();
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<Folder<string>> GetFoldersAsync(string parentId)
@ -402,9 +384,14 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
{
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<string>
{
return Task.FromResult(2L * 1024L * 1024L * 1024L);
}
}
}

View File

@ -78,15 +78,16 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
{
return Task.FromResult(ToFolder(RootFolder()));
}
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
public async IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider,
SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
{
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.kDrive && provider != ProviderFilter.WebDav && provider != ProviderFilter.Yandex))
{
return AsyncEnumerable.Empty<Folder<string>>();
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<string>
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<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider,
SubjectFilter subjectFilter, IEnumerable<string> 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<Folder<string>>();
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<Folder<string>> GetFoldersAsync(string parentId)
@ -461,9 +443,14 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
//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<string>
return Task.FromResult(chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, _setupInfo.AvailableFileSize));
}
}
}

View File

@ -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<RoomLogoManager> _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<RoomLogoManager> 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<RoomLogoManager> 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<string, StringValues> Headers => _httpContextAccessor?.HttpContext?.Request?.Headers;
public async Task<Folder<T>> CreateAsync<T>(T id, string tempFile, int x, int y, int width, int height)
{
var folderDao = _daoFactory.GetFolderDao<T>();
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<string, StringValues> Headers => _httpContextAccessor?.HttpContext?.Request?.Headers;
public async Task<Folder<T>> CreateAsync<T>(T id, string tempFile, int x, int y, int width, int height)
{
var folderDao = _daoFactory.GetFolderDao<T>();
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<Folder<T>> DeleteAsync<T>(T id, bool checkPermissions = true)
{
var folderDao = _daoFactory.GetFolderDao<T>();
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<Folder<T>> DeleteAsync<T>(T id, bool checkPermissions = true)
{
var folderDao = _daoFactory.GetFolderDao<T>();
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<Logo> GetLogoAsync<T>(Folder<T> 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<Logo> GetLogoAsync<T>(Folder<T> 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<string> 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<string> SaveWithProcessAsync<T>(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>(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<string> GetLogoPathAsync<T>(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<byte[]> 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>(T id)
{
ArgumentNullException.ThrowIfNull(id, nameof(id));
return id.GetType() != typeof(string)
? id.ToString()
: id.ToString()?.Replace("-", "").Replace("|", "");
}
private T GetId<T>(Folder<T> 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<string> 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>(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<string> GetLogoPathAsync<T>(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<byte[]> 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>(T id)
{
ArgumentNullException.ThrowIfNull(id, nameof(id));
return id.GetType() != typeof(string)
? id.ToString()
: id.ToString()?.Replace("-", "").Replace("|", "");
}
private static string GetId<T>(Folder<T> 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,
}