コード例 #1
0
        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);
        }
コード例 #2
0
        /// <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);
            }
        }
コード例 #3
0
        public FileRevision(FileRevisionDto dto)
        {
            this.dto = dto;

            AccessKeys = dto.AccessKeys.ToDictionary(x => x.UserId, x => (IAccessKey) new AccessKey(x));
        }