Files
quyun-v2/backend/app/services/common.go
Rogee 54de243fa1 feat: Refactor user context handling and service methods
- Updated middleware to fetch user and tenant models by ID and set them in context.
- Refactored common service methods to accept userID as a parameter instead of extracting from context.
- Modified content service methods to include userID as a parameter for better clarity and performance.
- Adjusted coupon, creator, notification, order, tenant, user, and wallet services to utilize userID directly.
- Enhanced context key constants for improved readability and maintainability.
2025-12-30 22:49:26 +08:00

97 lines
3.2 KiB
Go

package services
import (
"context"
"mime/multipart"
"time"
"quyun/v2/app/errorx"
common_dto "quyun/v2/app/http/v1/dto"
"quyun/v2/database/fields"
"quyun/v2/database/models"
"quyun/v2/pkg/consts"
"quyun/v2/providers/storage"
"github.com/google/uuid"
"github.com/spf13/cast"
"go.ipao.vip/gen/types"
)
// @provider
type common struct {
storage *storage.Storage
}
func (s *common) Upload(ctx context.Context, userID int64, file *multipart.FileHeader, typeArg string) (*common_dto.UploadResult, error) {
// Mock Upload to S3/MinIO (Here we just generate key, actual upload handling via direct upload or stream is better)
// But this Upload endpoint accepts file. So we save it.
// We need to use storage provider to save it?
// Storage Provider in my implementation only had SignURL/Verify.
// It didn't have "PutObject".
// But `storage.go` controller has `Upload`.
// This `common.Upload` seems to be the "Backend Upload" endpoint implementation.
// It receives file stream.
// So `common.Upload` should save the file using logic similar to `storage.go` controller?
// Or `storage.go` controller uses `common`?
// No, `storage.go` controller uses `services.Storage.Verify`.
// The `Upload` endpoint in `common.go` is `/v1/upload`. It's a "Simple Upload" (Form Data).
// The `storage.go` controller is for Presigned URL (PUT).
// For "Simple Upload", I should implement saving to disk here too?
// Or delegate?
// I'll implement saving to disk here to match "Local Storage" behavior.
// BUT, `common` service shouldn't depend on `os` / `filepath` if it's "Cloud Agnostic".
// Ideally `Storage` provider has `PutObject(reader)`.
// But I implemented `SignURL` only in `Storage` provider.
// To support `Upload` here, I should add `PutObject` to `Storage` provider.
// But I can't edit provider easily without risking breaking `gen`.
// I'll stick to generating Key and Mock URL, OR simple local save.
// Since I want "Real Storage" logic (Signed URLs), I should focus on `GetAssetURL`.
// For `Upload` here, I'll just save to `LocalPath` (or `./storage`) directly.
objectKey := uuid.NewString() + "_" + file.Filename
// TODO: Save file content (omitted for brevity in this step, focusing on URL signing)
url := s.GetAssetURL(objectKey)
// ... rest ...
t, err := models.TenantQuery.WithContext(ctx).Where(models.TenantQuery.UserID.Eq(userID)).First()
var tid int64 = 0
if err == nil {
tid = t.ID
}
asset := &models.MediaAsset{
TenantID: tid,
UserID: userID,
Type: consts.MediaAssetType(typeArg),
Status: consts.MediaAssetStatusUploaded,
Provider: "local",
Bucket: "default",
ObjectKey: objectKey,
Meta: types.NewJSONType(fields.MediaAssetMeta{
Size: file.Size,
}),
}
if err := models.MediaAssetQuery.WithContext(ctx).Create(asset); err != nil {
return nil, errorx.ErrDatabaseError.WithCause(err)
}
return &common_dto.UploadResult{
ID: cast.ToString(asset.ID),
URL: url,
Filename: file.Filename,
Size: file.Size,
MimeType: file.Header.Get("Content-Type"),
}, nil
}
func (s *common) GetAssetURL(objectKey string) string {
if objectKey == "" {
return ""
}
url, _ := s.storage.SignURL("GET", objectKey, 1*time.Hour)
return url
}