Replace old infrastructure layer with Kratos-style data layer: - data.go: GORM connection, transaction support, Wire ProviderSet, PO models - file_repo.go: All 12 S3 operations (upload, download, multipart, presign, buckets) - folder_repo.go: GORM queries including recursive CTE for descendant files - file_meta_repo.go: CRUD + move operations for file metadata - share_repo.go: CRUD + increment download count for share links Deleted old infrastructure/database, infrastructure/repository, infrastructure/s3. Kept infrastructure/grpc for later integration.
89 lines
2.7 KiB
Go
89 lines
2.7 KiB
Go
package data
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/go-kratos/kratos/v2/log"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// ShareRepo implements share link persistence operations using GORM.
|
|
type ShareRepo struct {
|
|
data *Data
|
|
log *log.Helper
|
|
}
|
|
|
|
// NewShareRepo creates a new ShareRepo.
|
|
func NewShareRepo(data *Data, logger log.Logger) *ShareRepo {
|
|
return &ShareRepo{
|
|
data: data,
|
|
log: log.NewHelper(logger),
|
|
}
|
|
}
|
|
|
|
// Create inserts a new share link record.
|
|
func (r *ShareRepo) Create(ctx context.Context, share *ShareLinkPO) error {
|
|
return r.data.DB(ctx).Create(share).Error
|
|
}
|
|
|
|
// GetByToken retrieves a share link by its token. Returns nil if not found.
|
|
func (r *ShareRepo) GetByToken(ctx context.Context, token string) (*ShareLinkPO, error) {
|
|
return r.queryOne(ctx, "token = ?", token)
|
|
}
|
|
|
|
// GetByID retrieves a share link by its ID. Returns nil if not found.
|
|
func (r *ShareRepo) GetByID(ctx context.Context, id string) (*ShareLinkPO, error) {
|
|
return r.queryOne(ctx, "id = ?", id)
|
|
}
|
|
|
|
// Delete removes a share link by ID and creator. Returns error if not found.
|
|
func (r *ShareRepo) Delete(ctx context.Context, id string, createdBy string) error {
|
|
result := r.data.DB(ctx).
|
|
Where("id = ? AND created_by = ?", id, createdBy).
|
|
Delete(&ShareLinkPO{})
|
|
if result.Error != nil {
|
|
return fmt.Errorf("failed to delete share link: %w", result.Error)
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return fmt.Errorf("share link not found or not owned by user")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// IncrementDownloadCount atomically increments the download count for the given token.
|
|
func (r *ShareRepo) IncrementDownloadCount(ctx context.Context, token string) error {
|
|
result := r.data.DB(ctx).Model(&ShareLinkPO{}).
|
|
Where("token = ?", token).
|
|
UpdateColumn("download_count", gorm.Expr("download_count + 1"))
|
|
if result.Error != nil {
|
|
return fmt.Errorf("failed to increment download count: %w", result.Error)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ListByResource retrieves all share links for a given resource, ordered by created_at descending.
|
|
func (r *ShareRepo) ListByResource(ctx context.Context, resourceType string, resourceID string) ([]ShareLinkPO, error) {
|
|
var links []ShareLinkPO
|
|
err := r.data.DB(ctx).
|
|
Where("resource_type = ? AND resource_id = ?", resourceType, resourceID).
|
|
Order("created_at DESC").
|
|
Find(&links).Error
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list share links: %w", err)
|
|
}
|
|
return links, nil
|
|
}
|
|
|
|
func (r *ShareRepo) queryOne(ctx context.Context, query string, args ...interface{}) (*ShareLinkPO, error) {
|
|
var share ShareLinkPO
|
|
err := r.data.DB(ctx).Where(query, args...).First(&share).Error
|
|
if err != nil {
|
|
if isRecordNotFound(err) {
|
|
return nil, nil
|
|
}
|
|
return nil, fmt.Errorf("failed to query share link: %w", err)
|
|
}
|
|
return &share, nil
|
|
}
|