public async Task <ThreadPostCreateResultDto> CreateThreadPostAsync(IFormFileCollection attachments, ThreadPostCreateDto dto, bool createNewThread) { await using var transaction = await _context.Database.BeginTransactionAsync(); if (createNewThread) { var thread = MapDtoToNewEntity <ThreadDto, Thread>(dto.Thread); thread.Category = _context.GetLocalOrAttach <Category>(dto.Category.Id); await _context.Threads.AddAsync(thread); await _context.SaveChangesAsync(); dto.Post.ThreadId = thread.Id; } var postingPermissionDto = await _banService.IsPostingAllowedAsync(dto.Post.ThreadId, dto.Post.UserIpAddress); if (!postingPermissionDto.IsPostingAllowed) { throw new HttpResponseException(HttpStatusCode.Forbidden, postingPermissionDto.Ban?.Reason); } else { var postEntity = MapDtoToNewEntity <PostDto, Post>(dto.Post); postEntity.Thread = _context.GetLocalOrAttach <Thread>(dto.Post.ThreadId); await _context.Posts.AddAsync(postEntity); await _context.SaveChangesAsync(); var containerName = dto.Post.ThreadId.ToString(); if (string.IsNullOrWhiteSpace(containerName)) { throw new Exception($"{nameof(containerName)} is null or whitespace"); } if (attachments != null && attachments.Any()) { await CreateAttachmentsAsync(containerName, postEntity, attachments); } await transaction.CommitAsync(); return(new ThreadPostCreateResultDto { PostId = postEntity.Id, ThreadId = dto.Post.ThreadId, }); } }
public async Task <TPrimaryKey> CreateAsync(IFormFileCollection attachments, PostDto dto) { var isPostingAllowed = await _banService.IsPostingAllowedAsync(dto.ThreadId, dto.UserIpAddress); if (!isPostingAllowed.Item1) { throw new HttpResponseException(HttpStatusCode.Forbidden, isPostingAllowed.Item2); } else if (attachments == null) { return(await CreateAsync(dto, (post) => { post.Thread = Context.Threads.FirstOrDefault(thread => thread.Id == dto.ThreadId); })); } else { var postId = await CreateAsync(dto, (post) => { post.Thread = Context.Threads.FirstOrDefault(thread => thread.Id == dto.ThreadId); }); try { var containerName = dto.ThreadId.ToString(); if (string.IsNullOrWhiteSpace(containerName)) { throw new Exception($"{nameof(containerName)} is null or whitespace"); } foreach (var attachment in attachments) { string blobName; var attachmentParentDto = _attachmentCategorizer.CreateAttachmentDto(attachment.FileName); attachmentParentDto.PostId = postId; attachmentParentDto.FileExtension = Path.GetExtension(attachment.FileName)?.TrimStart('.'); attachmentParentDto.FileName = Path.GetFileNameWithoutExtension(attachment.FileName); attachmentParentDto.Size = attachment.Length; attachmentParentDto.Hash = _cryptoService.HashHex(attachment.OpenReadStream()); if (attachmentParentDto is AudioDto audioDto) { blobName = (await _audioService.CreateAsync(audioDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); } else if (attachmentParentDto is PictureDto pictureDto) { if (_attachmentCategorizer.IsPictureExtensionSupported(pictureDto.FileExtension)) { // generate thumbnail if such file extension is supported var image = Image.Load(attachment.OpenReadStream()); pictureDto.Width = image.Width; pictureDto.Height = image.Height; blobName = (await _pictureService.CreateAsync(pictureDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); var thumbnail = _thumbnailGenerator.GenerateThumbnail( image, _hikkabaConfiguration.ThumbnailsMaxWidth, _hikkabaConfiguration.ThumbnailsMaxHeight); await _storageProvider.SaveBlobStreamAsync( containerName + Defaults.ThumbnailPostfix, blobName, thumbnail.Image); } else { // otherwise save the same image as thumbnail blobName = (await _pictureService.CreateAsync(pictureDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); await _storageProvider.SaveBlobStreamAsync( containerName + Defaults.ThumbnailPostfix, blobName, attachment.OpenReadStream()); } } else if (attachmentParentDto is VideoDto videoDto) { blobName = (await _videoService.CreateAsync(videoDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); } else if (attachmentParentDto is DocumentDto documentDto) { blobName = (await _documentService.CreateAsync(documentDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); } else { throw new Exception($"Unknown attachment type: {attachmentParentDto.GetType().Name}"); } if (string.IsNullOrWhiteSpace(blobName)) { throw new Exception($"{nameof(blobName)} is null or whitespace"); } await _storageProvider.SaveBlobStreamAsync(containerName, blobName, attachment.OpenReadStream()); } } catch (Exception ex) { _logger.LogError(ex + $" Post {postId} will be deleted."); await DeleteAsync(postId); throw; } return(postId); } }