file-system/internal/api/handlers/share_commands.go
向宁 3a18ca0579 feat: add directory structure and file sharing support
- PostgreSQL metadata overlay layer on top of existing S3 storage
- 3 new tables: folders, files, share_links
- Folder CRUD: create, get with children, tree, rename, delete (cascade)
- File operations: upload to folder, move between folders
- Share links: create with optional password/expiry/download limit, public access
- S3 compensation on PG write failure
- Existing 14 endpoints untouched
2026-05-20 20:26:19 +08:00

85 lines
1.9 KiB
Go

package handlers
import (
"context"
"crypto/rand"
"encoding/hex"
"fmt"
"time"
"rag/file-system/internal/domain/model"
"rag/file-system/internal/domain/repository"
"github.com/google/uuid"
)
type CreateShareCommand struct {
ResourceType string
ResourceID string
Password *string
ExpiresAt *time.Time
MaxDownloads *int
CreatedBy string
}
type DeleteShareCommand struct {
ShareID string
CreatedBy string
}
type CreateShareHandler struct {
ShareRepo repository.ShareRepository
}
func NewCreateShareHandler(shareRepo repository.ShareRepository) *CreateShareHandler {
return &CreateShareHandler{ShareRepo: shareRepo}
}
func (h *CreateShareHandler) Handle(ctx context.Context, cmd CreateShareCommand) (*model.ShareLink, error) {
token, err := generateShareToken()
if err != nil {
return nil, fmt.Errorf("failed to generate token: %w", err)
}
share := &model.ShareLink{
ID: uuid.New().String(),
ResourceType: cmd.ResourceType,
ResourceID: cmd.ResourceID,
Token: token,
Password: cmd.Password,
ExpiresAt: cmd.ExpiresAt,
DownloadCount: 0,
MaxDownloads: cmd.MaxDownloads,
CreatedBy: cmd.CreatedBy,
CreatedAt: time.Now(),
}
if err := h.ShareRepo.Create(ctx, share); err != nil {
return nil, err
}
return share, nil
}
type DeleteShareHandler struct {
ShareRepo repository.ShareRepository
}
func NewDeleteShareHandler(shareRepo repository.ShareRepository) *DeleteShareHandler {
return &DeleteShareHandler{ShareRepo: shareRepo}
}
func (h *DeleteShareHandler) Handle(ctx context.Context, cmd DeleteShareCommand) (string, error) {
if err := h.ShareRepo.Delete(ctx, cmd.ShareID, cmd.CreatedBy); err != nil {
return "", err
}
return "分享已取消", nil
}
func generateShareToken() (string, error) {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
return "", err
}
return hex.EncodeToString(b), nil
}