public static FileRevisionDto RestrictAccessKeys(this FileRevisionDto file, string userId) { var accessKeyForRequestingUser = file.AccessKeys.FirstOrDefault(x => x.UserId == userId); if (accessKeyForRequestingUser == null) { return(file); } file.AccessKeys = new[] { accessKeyForRequestingUser }; return(file); }
/// <inheritdoc /> public async Task <uint> InsertFile( string requestingUserId, string directoryId, string fileId, string blobId, string fileName, int fileSize, Dictionary <string, string> encryptedKeys, DocumentLanguage documentLanguage, ExtensionType fileExtension) { using var session = await client.StartSessionAsync(); session.StartTransaction(); try { // Find target directory var directory = await directoryCollection.AsQueryable() .Where(x => x.Id == directoryId && (x.OwnerId == requestingUserId || x.Permissions.Any(y => y.Permission.HasFlag(Permission.ReadWrite) && y.UserId == requestingUserId ))) .Select(x => new { Owner = x.OwnerId, Permissions = x.Permissions, Path = x.PathIds }) .FirstOrDefaultAsync(); // Return if the user has no permissions or the directory does not exists if (directory == null) { throw new ObjectNotResolvableException( $"Directory {directoryId} could not be found or accessed by user {requestingUserId} during file insertion"); } var newPath = directory.Path.ToList(); newPath.Add(fileId); // Insert new file var file = new FileDto { Id = fileId, Language = documentLanguage, Extension = fileExtension, OwnerId = directory.Owner, ObjectName = fileName, ParentDirectoryId = directoryId, PathIds = newPath.ToArray(), RevisionIds = new[] { blobId }, Permissions = directory.Permissions, Tags = new ITag[0], }; var insertFileTask = filesCollection.InsertOneAsync(session, file); // Update directory var updateFiles = Builders <DirectoryDto> .Update.Push(e => e.FileIds, fileId); var updateDirectoryTask = directoryCollection.UpdateOneAsync(session, x => x.Id == directoryId, updateFiles); // Get user information var ownerId = directory.Owner; var userIds = new HashSet <string>(directory.Permissions.Select(x => x.UserId)); // Ensure all keys are delivered if (userIds.Count != encryptedKeys.Count || !encryptedKeys.Keys.All(x => userIds.Contains(x))) { throw new InvalidParameterException( "Number of given keys does not match the number of required keys during file insertion"); } var userInfo = await userCollection .AsQueryable() .Where(x => x.Id == ownerId) .Select(x => new { UserId = x.Id, QuickNumber = x.QuickNumber, }).FirstOrDefaultAsync(); // Update quick number var newQuickNumber = userInfo.QuickNumber + 1; var updateQuickNumber = Builders <UserDto> .Update.Set(x => x.QuickNumber, newQuickNumber); var updateUserTask = userCollection.UpdateOneAsync(session, x => x.Id == ownerId, updateQuickNumber); // Update revision var accessKeys = new List <AccessKeyDto>(); foreach (var kv in encryptedKeys) { var userId = kv.Key; var encryptedKey = kv.Value; accessKeys.Add(new AccessKeyDto { SymmetricEncryptedFileKey = encryptedKey, IssuerId = requestingUserId, UserId = userId }); } var revision = new FileRevisionDto { Id = blobId, File = fileId, OwnerId = directory.Owner, SizeInBytes = (uint)fileSize, ChangeDate = DateTime.UtcNow, QuickNumber = newQuickNumber, AccessKeys = accessKeys.ToArray() }; var insertRevisionTask = fileRevisionCollection.InsertOneAsync(session, revision); // Wait for completion await Task.WhenAll(insertRevisionTask, updateDirectoryTask, updateUserTask, insertFileTask); await session.CommitTransactionAsync(); return(newQuickNumber); } catch (ObjectNotResolvableException) { await session.AbortTransactionAsync(); throw; } catch (InvalidParameterException) { await session.AbortTransactionAsync(); throw; } catch (MongoException e) { await session.AbortTransactionAsync(); throw new DatabaseException("Database error during file inserting. See inner exception.", e); } catch (Exception e) { await session.AbortTransactionAsync(); throw new Exception("Unknown error during file inserting. See inner exception.", e); } }
public FileRevision(FileRevisionDto dto) { this.dto = dto; AccessKeys = dto.AccessKeys.ToDictionary(x => x.UserId, x => (IAccessKey) new AccessKey(x)); }