From 8e247cdb0d8d9fbe30b363de270c7fb1e2d92a7c Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 28 Aug 2025 12:19:17 +0300 Subject: [PATCH] v0.0.27.3 --- internal/service/post_service.go | 54 ++++++++++++-------------------- pkg/S3/s3.go | 44 ++------------------------ 2 files changed, 22 insertions(+), 76 deletions(-) diff --git a/internal/service/post_service.go b/internal/service/post_service.go index d0cd42a..960555b 100644 --- a/internal/service/post_service.go +++ b/internal/service/post_service.go @@ -45,21 +45,21 @@ func NewPostService(postRepo repository.PostRepository) PostService { return &postService{postRepo: postRepo} } -func (s *postService) CreateWithS3Upload(ctx context.Context, authorID int, title, s3TempKey string) (*domain.Post, error) { +func (s *postService) CreateWithS3Upload(ctx context.Context, authorID int, title, s3Key string) (*domain.Post, error) { const op = "service/postService.CreateWithS3Upload" // Валидация - if s3TempKey == "" { - return nil, errors.New("S3 temp key cannot be empty") + if s3Key == "" { + return nil, errors.New("S3 key cannot be empty") } - // Проверяем что ключ принадлежит пользователю (дополнительная валидация) - if !isValidUserTempKey(authorID, s3TempKey) { - return nil, errors.New("invalid temp key for user") + // Проверяем что ключ принадлежит пользователю и находится в правильной папке + if !isValidUserPostKey(authorID, s3Key) { + return nil, errors.New("invalid S3 key for user") } - // Генерируем временный URL для модерации - tempURL := fmt.Sprintf("https://s3.regru.cloud/tailly/%s", s3TempKey) + // Формируем URL для модерации + imageURL := fmt.Sprintf("https://s3.regru.cloud/tailly/%s", s3Key) // Модерация изображения по URL modClient, err := moderation.NewModerationClient("tailly_censor:50051") @@ -68,29 +68,19 @@ func (s *postService) CreateWithS3Upload(ctx context.Context, authorID int, titl } defer modClient.Close() - allowed, err := modClient.CheckImageURL(ctx, tempURL) + allowed, err := modClient.CheckImageURL(ctx, imageURL) if err != nil { - // Удаляем временный файл при ошибке модерации - S3.DeleteTempFile(s3TempKey) + // Удаляем файл при ошибке модерации + S3.DeleteFromS3(imageURL) return nil, fmt.Errorf("%s: image moderation failed: %w", op, err) } if !allowed { - // Удаляем временный файл если не прошло модерацию - S3.DeleteTempFile(s3TempKey) + // Удаляем файл если не прошло модерацию + S3.DeleteFromS3(imageURL) return nil, errors.New("image rejected by moderation service") } - // Перемещаем файл из временной папки в постоянную - permanentKey := fmt.Sprintf("posts/%d/%d_%s", authorID, time.Now().UnixNano(), getFilenameFromKey(s3TempKey)) - - err = S3.MoveFile(s3TempKey, permanentKey) - if err != nil { - S3.DeleteTempFile(s3TempKey) // Удаляем временный файл при ошибке - return nil, fmt.Errorf("%s: failed to move file to permanent location: %w", op, err) - } - - imageURL := fmt.Sprintf("https://s3.regru.cloud/tailly/%s", permanentKey) - + // Создаем пост с уже готовым URL post := &domain.Post{ Title: title, Content: imageURL, @@ -101,22 +91,18 @@ func (s *postService) CreateWithS3Upload(ctx context.Context, authorID int, titl if err := s.postRepo.Create(ctx, post); err != nil { // Если не удалось сохранить пост, удаляем файл из S3 - S3.DeleteTempFile(permanentKey) + S3.DeleteFromS3(imageURL) return nil, fmt.Errorf("%s: failed to save post: %w", op, err) } return post, nil } -func isValidUserTempKey(userID int, key string) bool { - // Проверяем что ключ принадлежит пользователю - // Формат: temp/{userID}/{timestamp}_{filename} - return strings.Contains(key, fmt.Sprintf("temp/%d/", userID)) -} - -func getFilenameFromKey(key string) string { - parts := strings.Split(key, "/") - return parts[len(parts)-1] +// Новая функция проверки ключа +func isValidUserPostKey(userID int, key string) bool { + // Проверяем что ключ принадлежит пользователю и находится в папке posts + // Формат: posts/{userID}/{timestamp}_{filename} + return strings.HasPrefix(key, fmt.Sprintf("posts/%d/", userID)) } // Создание нового поста diff --git a/pkg/S3/s3.go b/pkg/S3/s3.go index 629d47c..2ae5b1d 100644 --- a/pkg/S3/s3.go +++ b/pkg/S3/s3.go @@ -87,7 +87,8 @@ func GeneratePresignedUploadURL(userID int, filename string) (string, string, er return "", "", fmt.Errorf("%s: failed to create S3 client: %w", op, err) } - uniqueKey := fmt.Sprintf("temp/%d/%d_%s", userID, time.Now().UnixNano(), filename) + // Генерируем ключ сразу в конечной папке с уникальным именем + uniqueKey := fmt.Sprintf("posts/%d/%d_%s", userID, time.Now().UnixNano(), filename) presignClient := s3.NewPresignClient(client) @@ -105,44 +106,3 @@ func GeneratePresignedUploadURL(userID int, filename string) (string, string, er return result.URL, uniqueKey, nil } - -func MoveFile(sourceKey, destinationKey string) error { - const op = "s3.MoveFile" - - client, err := getS3Client() - if err != nil { - return fmt.Errorf("%s: failed to create S3 client: %w", op, err) - } - - // Копируем файл - _, err = client.CopyObject(context.TODO(), &s3.CopyObjectInput{ - Bucket: aws.String("tailly"), - CopySource: aws.String(fmt.Sprintf("tailly/%s", sourceKey)), - Key: aws.String(destinationKey), - }) - if err != nil { - return fmt.Errorf("%s: failed to copy file: %w", op, err) - } - - // Удаляем исходный файл - return DeleteTempFile(sourceKey) -} - -func DeleteTempFile(key string) error { - const op = "s3.DeleteTempFile" - - client, err := getS3Client() - if err != nil { - return fmt.Errorf("%s: failed to create S3 client: %w", op, err) - } - - _, err = client.DeleteObject(context.TODO(), &s3.DeleteObjectInput{ - Bucket: aws.String("tailly"), - Key: aws.String(key), - }) - if err != nil { - return fmt.Errorf("%s: failed to delete temp file: %w", op, err) - } - - return nil -}