Files: added share pagination for room

This commit is contained in:
Maksim Chegulov 2023-07-13 17:48:56 +03:00
parent 5957d130a9
commit 09ed128fd0
6 changed files with 221 additions and 11 deletions

View File

@ -194,6 +194,51 @@ internal abstract class SecurityBaseDao<T> : AbstractDao
return InternalGetPureShareRecordsAsync(entry);
}
public async IAsyncEnumerable<FileShareRecord> GetRoomSharesAsync(Folder<T> room, ShareFilterType filterType, int offset = 0, int count = -1)
{
if (room == null || !DocSpaceHelper.IsRoom(room.FolderType) || count == 0)
{
yield break;
}
await using var filesDbContext = _dbContextFactory.CreateDbContext();
var q = await GetPureSharesQuery(room, filterType, filesDbContext);
if (filterType == ShareFilterType.User)
{
q = q.Join(filesDbContext.Users, s => s.Subject, u => u.Id, (s, u) => new { s, u })
.OrderBy(r => r.u.ActivationStatus)
.ThenBy(r => r.s.Share == FileShare.RoomAdmin ? 0 :
r.s.Share == FileShare.Collaborator ? 1 :
r.s.Share == FileShare.Editing ? 2 :
r.s.Share == FileShare.FillForms ? 3 :
r.s.Share == FileShare.Review ? 4 :
r.s.Share == FileShare.Comment ? 5 :
r.s.Share == FileShare.Read ? 6 : 7)
.Select(r => r.s);
}
else
{
q = q.OrderBy(s => s.Share);
}
if (offset > 0)
{
q = q.Skip(offset);
}
if (count > 0)
{
q = q.Take(count);
}
await foreach (var r in q.ToAsyncEnumerable())
{
yield return await ToFileShareRecordAsync(r);
}
}
internal async IAsyncEnumerable<FileShareRecord> InternalGetPureShareRecordsAsync(FileEntry<T> entry)
{
@ -288,6 +333,32 @@ internal abstract class SecurityBaseDao<T> : AbstractDao
return result;
}
private async Task<IQueryable<DbFilesSecurity>> GetPureSharesQuery(FileEntry<T> entry, ShareFilterType filterType, FilesDbContext filesDbContext)
{
var entryId = await MappingIDAsync(entry.Id);
var q = filesDbContext.Security.AsNoTracking()
.Where(s => s.TenantId == TenantID && s.EntryId == entryId.ToString() && s.EntryType == entry.FileEntryType);
switch (filterType)
{
case ShareFilterType.User:
q = q.Where(s => s.SubjectType == SubjectType.UserOrGroup);
break;
case ShareFilterType.InvitationLink:
q = q.Where(s => s.SubjectType == SubjectType.InvitationLink);
break;
case ShareFilterType.ExternalLink:
q = q.Where(s => s.SubjectType == SubjectType.ExternalLink);
break;
case ShareFilterType.Link:
q = q.Where(s => s.SubjectType == SubjectType.InvitationLink || s.SubjectType == SubjectType.ExternalLink);
break;
}
return q;
}
}
[Scope]

View File

@ -2420,6 +2420,16 @@ public class FileStorageService //: IFileStorageService
return await _fileSharing.GetSharedInfoShortFolderAsync(folderId);
}
public async IAsyncEnumerable<AceWrapper> GetRoomSharedInfoAsync<T>(T roomId, ShareFilterType filterType, int offset, int count)
{
var room = await GetFolderDao<T>().GetFolderAsync(roomId).NotFoundIfNull();
await foreach (var ace in _fileSharing.GetRoomSharedInfoAsync(room, filterType, offset, count))
{
yield return ace;
}
}
public async Task<string> SetAceObjectAsync<T>(AceCollection<T> aceCollection, bool notify)
{
var fileDao = GetFileDao<T>();

View File

@ -1118,6 +1118,11 @@ public class FileSecurity : IFileSecurity
return await _daoFactory.GetSecurityDao<T>().GetSharesAsync(entry);
}
public IAsyncEnumerable<FileShareRecord> GetRoomSharesAsync<T>(Folder<T> room, ShareFilterType filterType, int offset, int count)
{
return _daoFactory.GetSecurityDao<T>().GetRoomSharesAsync(room, filterType, offset, count);
}
public async IAsyncEnumerable<FileEntry> GetSharesForMeAsync(FilterType filterType, bool subjectGroup, Guid subjectID, string searchText = "", bool searchInContent = false, bool withSubfolders = false)
{
var securityDao = _daoFactory.GetSecurityDao<int>();

View File

@ -30,7 +30,7 @@ namespace ASC.Files.Core.Security;
public interface ISecurityDao<T>
{
Task SetShareAsync(FileShareRecord r);
IAsyncEnumerable<FileShareRecord> GetShareForEntryIdsAsync(Guid subject, IEnumerable<string> roomIds);
IAsyncEnumerable<FileShareRecord> GetShareForEntryIdsAsync(Guid subject, IEnumerable<string> roomIds);
IAsyncEnumerable<FileShareRecord> GetSharesAsync(IEnumerable<Guid> subjects);
Task<IEnumerable<FileShareRecord>> GetSharesAsync(FileEntry<T> entry);
Task RemoveSubjectAsync(Guid subject);
@ -38,4 +38,5 @@ public interface ISecurityDao<T>
IAsyncEnumerable<FileShareRecord> GetPureShareRecordsAsync(FileEntry<T> entry);
Task DeleteShareRecordsAsync(IEnumerable<FileShareRecord> records);
Task<bool> IsSharedAsync(T entryId, FileEntryType type);
}
IAsyncEnumerable<FileShareRecord> GetRoomSharesAsync(Folder<T> room, ShareFilterType filterType, int offset, int count);
}

View File

@ -464,6 +464,68 @@ public class FileSharing
return await _fileSharingHelper.CanSetAccessAsync(entry);
}
public async IAsyncEnumerable<AceWrapper> GetRoomSharedInfoAsync<T>(Folder<T> room, ShareFilterType filterType, int offset, int count)
{
if (room == null || !DocSpaceHelper.IsRoom(room.FolderType))
{
throw new ArgumentNullException(FilesCommonResource.ErrorMassage_BadRequest);
}
if (!await _fileSecurity.CanReadAsync(room))
{
_logger.ErrorUserCanTGetSharedInfo(_authContext.CurrentAccount.ID, room.FileEntryType, room.Id.ToString()!);
yield break;
}
var canEditAccess = await _fileSecurity.CanEditAccessAsync(room);
var defaultAces = await GetDefaultRoomAcesAsync(room, filterType).Skip(offset).Take(count).ToListAsync();
offset = offset == 0 ? offset : offset - defaultAces.Count;
count -= defaultAces.Count;
var records = _fileSecurity.GetRoomSharesAsync(room, filterType, offset, count);
foreach (var record in defaultAces)
{
yield return record;
}
await foreach (var record in records)
{
var w = new AceWrapper
{
Id = record.Subject,
SubjectGroup = false,
Access = record.Share,
FileShareOptions = record.FileShareOptions,
SubjectType = record.SubjectType
};
w.CanEditAccess = _authContext.CurrentAccount.ID != w.Id && w.SubjectType == SubjectType.UserOrGroup && canEditAccess;
if (record.IsLink)
{
w.Link = _invitationLinkService.GetInvitationLink(record.Subject, _authContext.CurrentAccount.ID);
w.SubjectGroup = true;
w.CanEditAccess = false;
}
else
{
var user = await _userManager.GetUsersAsync(record.Subject);
w.SubjectName = user.DisplayUserName(false, _displayUserSettingsHelper);
w.Owner = room.RootFolderType == FolderType.USER
? room.RootCreateBy == record.Subject
: room.CreateBy == record.Subject;
w.LockedRights = record.Subject == _authContext.CurrentAccount.ID;
}
yield return w;
}
}
public async Task<List<AceWrapper>> GetSharedInfoAsync<T>(FileEntry<T> entry)
{
if (entry == null)
@ -791,4 +853,41 @@ public class FileSharing
.Where(aceWrapper => !aceWrapper.Id.Equals(FileConstant.ShareLinkId) || aceWrapper.Access != FileShare.Restrict)
.Select(aceWrapper => new AceShortWrapper(aceWrapper)));
}
private async IAsyncEnumerable<AceWrapper> GetDefaultRoomAcesAsync<T>(Folder<T> room, ShareFilterType filterType)
{
switch (filterType)
{
case ShareFilterType.InvitationLink or ShareFilterType.Link:
{
var id = Guid.NewGuid();
var w = new AceWrapper
{
Id = id,
Link = _invitationLinkService.GetInvitationLink(id, _authContext.CurrentAccount.ID),
SubjectGroup = true,
Access = FileShare.Read,
Owner = false
};
yield return w;
break;
}
case ShareFilterType.User:
{
var w = new AceWrapper
{
Id = room.CreateBy,
SubjectName = await _global.GetUserNameAsync(room.CreateBy),
SubjectGroup = false,
Access = FileShare.ReadWrite,
Owner = true,
CanEditAccess = false,
};
yield return w;
break;
}
}
}
}

View File

@ -40,7 +40,8 @@ public class VirtualRoomsInternalController : VirtualRoomsController<int>
FileDtoHelper fileDtoHelper,
FileShareDtoHelper fileShareDtoHelper,
IMapper mapper,
SocketManager socketManager) : base(
SocketManager socketManager,
ApiContext apiContext) : base(
globalFolderHelper,
fileOperationDtoHelper,
coreBaseSettings,
@ -51,7 +52,8 @@ public class VirtualRoomsInternalController : VirtualRoomsController<int>
fileDtoHelper,
fileShareDtoHelper,
mapper,
socketManager)
socketManager,
apiContext)
{
}
@ -94,7 +96,8 @@ public class VirtualRoomsThirdPartyController : VirtualRoomsController<string>
FileDtoHelper fileDtoHelper,
FileShareDtoHelper fileShareDtoHelper,
IMapper mapper,
SocketManager socketManager) : base(
SocketManager socketManager,
ApiContext apiContext) : base(
globalFolderHelper,
fileOperationDtoHelper,
coreBaseSettings,
@ -105,7 +108,8 @@ public class VirtualRoomsThirdPartyController : VirtualRoomsController<string>
fileDtoHelper,
fileShareDtoHelper,
mapper,
socketManager)
socketManager,
apiContext)
{
}
@ -149,6 +153,7 @@ public abstract class VirtualRoomsController<T> : ApiControllerBase
private readonly FileShareDtoHelper _fileShareDtoHelper;
private readonly IMapper _mapper;
private readonly SocketManager _socketManager;
private readonly ApiContext _apiContext;
protected VirtualRoomsController(
GlobalFolderHelper globalFolderHelper,
@ -161,7 +166,8 @@ public abstract class VirtualRoomsController<T> : ApiControllerBase
FileDtoHelper fileDtoHelper,
FileShareDtoHelper fileShareDtoHelper,
IMapper mapper,
SocketManager socketManager) : base(folderDtoHelper, fileDtoHelper)
SocketManager socketManager,
ApiContext apiContext) : base(folderDtoHelper, fileDtoHelper)
{
_globalFolderHelper = globalFolderHelper;
_fileOperationDtoHelper = fileOperationDtoHelper;
@ -172,6 +178,7 @@ public abstract class VirtualRoomsController<T> : ApiControllerBase
_fileShareDtoHelper = fileShareDtoHelper;
_mapper = mapper;
_socketManager = socketManager;
_apiContext = apiContext;
}
/// <summary>
@ -356,16 +363,33 @@ public abstract class VirtualRoomsController<T> : ApiControllerBase
/// <param name="id">
/// Room ID
/// </param>
/// <param name="filterType">
/// Share type filter
/// </param>
/// <returns>Room security info</returns>
[HttpGet("rooms/{id}/share")]
public async IAsyncEnumerable<FileShareDto> GetRoomSecurityInfoAsync(T id)
public async IAsyncEnumerable<FileShareDto> GetRoomSecurityInfoAsync(T id, ShareFilterType filterType = ShareFilterType.User)
{
var fileShares = await _fileStorageService.GetSharedInfoAsync(Array.Empty<T>(), new[] { id });
const int margin = 1;
var offset = Convert.ToInt32(_apiContext.StartIndex);
var count = Convert.ToInt32(_apiContext.Count);
var counter = 0;
foreach (var fileShareDto in fileShares)
await foreach (var ace in _fileStorageService.GetRoomSharedInfoAsync(id, filterType, offset, count + margin))
{
yield return await _fileShareDtoHelper.Get(fileShareDto);
counter++;
if (counter > count)
{
_apiContext.Next = true;
yield break;
}
yield return await _fileShareDtoHelper.Get(ace);
}
_apiContext.Next = false;
}
/// <summary>