Example #1
0
        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,
                });
            }
        }
Example #2
0
        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);
            }
        }