optimized access check
This commit is contained in:
parent
e5b3d44bc3
commit
7f9286219c
@ -276,15 +276,14 @@ internal abstract class SecurityBaseDao<T> : AbstractDao
|
||||
return result;
|
||||
}
|
||||
|
||||
internal async Task<FileShareRecord> ToFileShareRecordAsync(SecurityTreeRecord r)
|
||||
protected FileShareRecord ToFileShareRecord(SecurityTreeRecord r)
|
||||
{
|
||||
var result = await ToFileShareRecordAsync(r.DbFilesSecurity);
|
||||
if (r.DbFolderTree != null)
|
||||
{
|
||||
result.EntryId = r.DbFolderTree.FolderId;
|
||||
}
|
||||
var result = _mapper.Map<SecurityTreeRecord, FileShareRecord>(r);
|
||||
|
||||
result.Level = r.DbFolderTree?.Level ?? -1;
|
||||
if (r.FolderId != default)
|
||||
{
|
||||
result.EntryId = r.FolderId;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -309,7 +308,7 @@ internal class SecurityDao : SecurityBaseDao<int>, ISecurityDao<int>
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileShareRecord>> GetSharesAsync(FileEntry<int> entry)
|
||||
public async Task<IEnumerable<FileShareRecord>> GetSharesAsync(FileEntry<int> entry, IEnumerable<Guid> subjects = null)
|
||||
{
|
||||
if (entry == null)
|
||||
{
|
||||
@ -321,30 +320,56 @@ internal class SecurityDao : SecurityBaseDao<int>, ISecurityDao<int>
|
||||
|
||||
await SelectFilesAndFoldersForShareAsync(entry, files, null, foldersInt);
|
||||
|
||||
return await SaveFilesAndFoldersForShareAsync(files, foldersInt);
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<FileShareRecord>> SaveFilesAndFoldersForShareAsync(List<string> files, List<int> folders)
|
||||
{
|
||||
await using var filesDbContext = _dbContextFactory.CreateDbContext();
|
||||
|
||||
var q = await Query(filesDbContext.Security)
|
||||
.Join(filesDbContext.Tree, r => r.EntryId, a => a.ParentId.ToString(), (security, tree) => new SecurityTreeRecord { DbFilesSecurity = security, DbFolderTree = tree })
|
||||
.Where(r => folders.Contains(r.DbFolderTree.FolderId) &&
|
||||
r.DbFilesSecurity.EntryType == FileEntryType.Folder)
|
||||
.ToListAsync();
|
||||
var q = Query(filesDbContext.Security)
|
||||
.Join(filesDbContext.Tree, r => r.EntryId, a => a.ParentId.ToString(),
|
||||
(s, t) => new SecurityTreeRecord
|
||||
{
|
||||
TenantId = s.TenantId,
|
||||
EntryId = s.EntryId,
|
||||
EntryType = s.EntryType,
|
||||
SubjectType = s.SubjectType,
|
||||
Subject = s.Subject,
|
||||
Owner = s.Owner,
|
||||
Share = s.Share,
|
||||
TimeStamp = s.TimeStamp,
|
||||
Options = s.Options,
|
||||
FolderId = t.FolderId,
|
||||
ParentId = t.ParentId,
|
||||
Level = t.Level
|
||||
})
|
||||
.Where(r => foldersInt.Contains(r.FolderId) && r.EntryType == FileEntryType.Folder);
|
||||
|
||||
if (0 < files.Count)
|
||||
if (files.Count > 0)
|
||||
{
|
||||
var q1 = await GetQuery(filesDbContext, r => files.Contains(r.EntryId) && r.EntryType == FileEntryType.File)
|
||||
.Select(r => new SecurityTreeRecord { DbFilesSecurity = r })
|
||||
.ToListAsync();
|
||||
q = q.Union(q1).ToList();
|
||||
var q1 = GetQuery(filesDbContext, r => files.Contains(r.EntryId) && r.EntryType == FileEntryType.File)
|
||||
.Select(s => new SecurityTreeRecord
|
||||
{
|
||||
TenantId = s.TenantId,
|
||||
EntryId = s.EntryId,
|
||||
EntryType = s.EntryType,
|
||||
SubjectType = s.SubjectType,
|
||||
Subject = s.Subject,
|
||||
Owner = s.Owner,
|
||||
Share = s.Share,
|
||||
TimeStamp = s.TimeStamp,
|
||||
Options = s.Options,
|
||||
FolderId = 0,
|
||||
ParentId = 0,
|
||||
Level = -1
|
||||
});
|
||||
|
||||
q = q.Concat(q1);
|
||||
}
|
||||
|
||||
var records = await q
|
||||
.ToAsyncEnumerable()
|
||||
.SelectAwait(async e => await ToFileShareRecordAsync(e))
|
||||
if (subjects != null && subjects.Any())
|
||||
{
|
||||
q = q.Where(r => subjects.Contains(r.Subject));
|
||||
}
|
||||
|
||||
var records = await q.ToAsyncEnumerable()
|
||||
.Select(ToFileShareRecord)
|
||||
.OrderBy(r => r.Level)
|
||||
.ThenByDescending(r => r.Share, new FileShareRecord.ShareComparer())
|
||||
.ToListAsync();
|
||||
@ -404,7 +429,7 @@ internal class ThirdPartySecurityDao : SecurityBaseDao<string>, ISecurityDao<str
|
||||
_selectorFactory = selectorFactory;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileShareRecord>> GetSharesAsync(FileEntry<string> entry)
|
||||
public async Task<IEnumerable<FileShareRecord>> GetSharesAsync(FileEntry<string> entry, IEnumerable<Guid> subjects = null)
|
||||
{
|
||||
var result = new List<FileShareRecord>();
|
||||
|
||||
@ -433,6 +458,11 @@ internal class ThirdPartySecurityDao : SecurityBaseDao<string>, ISecurityDao<str
|
||||
|
||||
result.AddRange(await GetShareForFoldersAsync(folders).ToListAsync());
|
||||
|
||||
if (subjects != null && subjects.Any())
|
||||
{
|
||||
result = result.Where(r => subjects.Contains(r.Subject)).ToList();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -493,12 +523,21 @@ internal class ThirdPartySecurityDao : SecurityBaseDao<string>, ISecurityDao<str
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
internal class SecurityTreeRecord
|
||||
{
|
||||
public DbFilesSecurity DbFilesSecurity { get; init; }
|
||||
public DbFolderTree DbFolderTree { get; init; }
|
||||
public int TenantId { get; set; }
|
||||
public string EntryId { get; set; }
|
||||
public FileEntryType EntryType { get; set; }
|
||||
public SubjectType SubjectType { get; set; }
|
||||
public Guid Subject { get; set; }
|
||||
public Guid Owner { get; set; }
|
||||
public FileShare Share { get; set; }
|
||||
public DateTime TimeStamp { get; set; }
|
||||
public string Options { get; set; }
|
||||
public int FolderId { get; set; }
|
||||
public int ParentId { get; set; }
|
||||
public int Level { get; set; }
|
||||
}
|
||||
|
||||
static file class Queries
|
||||
|
@ -931,10 +931,7 @@ public class FileSecurity : IFileSecurity
|
||||
if (shares == null)
|
||||
{
|
||||
subjects = await GetUserSubjectsAsync(userId);
|
||||
shares = (await GetSharesAsync(e))
|
||||
.Join(subjects, r => r.Subject, s => s, (r, s) => r)
|
||||
.ToList();
|
||||
// shares ordered by level
|
||||
shares = await GetSharesAsync(e, subjects);
|
||||
}
|
||||
|
||||
if (e.FileEntryType == FileEntryType.File)
|
||||
@ -1176,9 +1173,9 @@ public class FileSecurity : IFileSecurity
|
||||
await securityDao.SetShareAsync(r);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<FileShareRecord>> GetSharesAsync<T>(FileEntry<T> entry)
|
||||
public async Task<IEnumerable<FileShareRecord>> GetSharesAsync<T>(FileEntry<T> entry, IEnumerable<Guid> subjects = null)
|
||||
{
|
||||
return await _daoFactory.GetSecurityDao<T>().GetSharesAsync(entry);
|
||||
return await _daoFactory.GetSecurityDao<T>().GetSharesAsync(entry, subjects);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<FileEntry> GetSharesForMeAsync(FilterType filterType, bool subjectGroup, Guid subjectID, string searchText = "", bool searchInContent = false, bool withSubfolders = false)
|
||||
@ -1731,6 +1728,11 @@ public class FileSecurity : IFileSecurity
|
||||
.Where(f => DocSpaceHelper.IsRoom(f.FolderType))
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (room == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_cachedRoomOwner.TryAdd(GetCacheKey(entry.ParentId), room.CreateBy);
|
||||
|
||||
return room.CreateBy == userId;
|
||||
|
@ -30,12 +30,12 @@ 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<IEnumerable<FileShareRecord>> GetSharesAsync(FileEntry<T> entry, IEnumerable<Guid> subjects = null);
|
||||
Task RemoveSubjectAsync(Guid subject);
|
||||
IAsyncEnumerable<FileShareRecord> GetPureShareRecordsAsync(IEnumerable<FileEntry<T>> entries);
|
||||
IAsyncEnumerable<FileShareRecord> GetPureShareRecordsAsync(FileEntry<T> entry);
|
||||
Task DeleteShareRecordsAsync(IEnumerable<FileShareRecord> records);
|
||||
Task<bool> IsSharedAsync(T entryId, FileEntryType type);
|
||||
}
|
||||
}
|
||||
|
@ -59,5 +59,9 @@ public class FilesMappingProfile : AutoMapper.Profile
|
||||
CreateMap<DbFilesSecurity, FileShareRecord>()
|
||||
.ForMember(dest => dest.Options, cfg =>
|
||||
cfg.MapFrom(src => JsonSerializer.Deserialize<FileShareOptions>(src.Options, JsonSerializerOptions.Default)));
|
||||
|
||||
CreateMap<SecurityTreeRecord, FileShareRecord>()
|
||||
.ForMember(dest => dest.Options, cfg =>
|
||||
cfg.MapFrom(src => JsonSerializer.Deserialize<FileShareOptions>(src.Options, JsonSerializerOptions.Default)));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user