243 lines
9.2 KiB
Go
243 lines
9.2 KiB
Go
package filemanager
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
SystemRootFolderName = "__system_root_files__"
|
|
)
|
|
|
|
var (
|
|
ErrDuplicateName = errors.New("duplicate name in target folder")
|
|
ErrInvalidMove = errors.New("invalid folder move")
|
|
ErrFolderNotFound = errors.New("folder not found")
|
|
ErrFileNotFound = errors.New("file not found")
|
|
ErrFileAlreadyFinalized = errors.New("file already finalized")
|
|
ErrFileNotEligibleForFinalize = errors.New("file is not eligible for finalize")
|
|
ErrInvalidFileStatusTransition = errors.New("invalid file status transition")
|
|
ErrFileStatusConflict = errors.New("file status conflict")
|
|
ErrStorageUnavailable = errors.New("storage unavailable")
|
|
ErrFolderNotEmpty = errors.New("folder is not empty")
|
|
ErrFolderNotInTrash = errors.New("folder is not in trash")
|
|
ErrFileNotInTrash = errors.New("file is not in trash")
|
|
ErrInvalidName = errors.New("invalid name")
|
|
ErrReservedName = errors.New("reserved name")
|
|
ErrFileTooLarge = errors.New("file too large")
|
|
ErrFileMimeTypeNotAllowed = errors.New("file mime type is not allowed")
|
|
ErrFileExtensionNotAllowed = errors.New("file extension is not allowed")
|
|
ErrEmptyFileNotAllowed = errors.New("empty file is not allowed")
|
|
ErrFileNameTooLong = errors.New("file name exceeds maximum length")
|
|
ErrFileProcessingQueueDisabled = errors.New("file processing queue is not configured")
|
|
ErrUploadIntentRepositoryDisabled = errors.New("file upload intent repository is not configured")
|
|
ErrUploadIntentNotFound = errors.New("upload intent not found")
|
|
ErrUploadIntentExpired = errors.New("upload intent is expired")
|
|
ErrUploadIntentAlreadyComplete = errors.New("upload intent already completed")
|
|
ErrUploadIntentStatusConflict = errors.New("upload intent status conflict")
|
|
ErrUploadObjectNotFound = errors.New("uploaded object not found in storage")
|
|
ErrUploadObjectMismatch = errors.New("uploaded object does not match upload intent")
|
|
ErrAttachmentRepositoryDisabled = errors.New("attachment repository is not configured")
|
|
ErrAttachmentNotFound = errors.New("attachment not found")
|
|
ErrAttachmentAlreadyExists = errors.New("attachment already exists for this reference")
|
|
ErrAttachmentRefRequired = errors.New("attachment ref_type and ref_id are required")
|
|
ErrFileNotReadyForAttachment = errors.New("file is not ready for attachment")
|
|
)
|
|
|
|
type FileUploadPolicy struct {
|
|
MaxFileSizeBytes int64
|
|
AllowedMimeTypes []string
|
|
AllowedExtensions []string
|
|
AllowEmptyFile bool
|
|
MaxFilenameLength int
|
|
}
|
|
|
|
type FileProcessingJob struct {
|
|
JobID string
|
|
FileUUID string
|
|
Bucket string
|
|
ObjectKey string
|
|
UploadedBy string
|
|
MimeType string
|
|
SizeBytes int64
|
|
TraceID string
|
|
RequestID string
|
|
}
|
|
|
|
type FileProcessingQueue interface {
|
|
Enqueue(ctx context.Context, job FileProcessingJob) error
|
|
}
|
|
|
|
type CreateFolderParams struct {
|
|
Name string
|
|
ParentID []byte
|
|
ActorID []byte
|
|
}
|
|
|
|
type MoveFolderParams struct {
|
|
Name *string
|
|
ParentID []byte
|
|
ParentProvided bool
|
|
ActorID []byte
|
|
}
|
|
|
|
type UploadFileParams struct {
|
|
Name string
|
|
ContentType string
|
|
SizeBytes int64
|
|
Body io.Reader
|
|
ActorID []byte
|
|
IsTemplate bool
|
|
}
|
|
|
|
type RequestFileUploadIntentParams struct {
|
|
Name string
|
|
ContentType string
|
|
SizeBytes int64
|
|
ActorID []byte
|
|
}
|
|
|
|
type FileUploadIntentGrant struct {
|
|
UploadIntentID []byte
|
|
Bucket string
|
|
ObjectKey string
|
|
Name string
|
|
MimeType string
|
|
SizeBytes int64
|
|
Method string
|
|
UploadURL string
|
|
Headers map[string]string
|
|
ExpiresAt time.Time
|
|
}
|
|
|
|
type CompleteFileUploadIntentParams struct {
|
|
UploadIntentID []byte
|
|
ActorID []byte
|
|
}
|
|
|
|
type CancelFileUploadIntentParams struct {
|
|
UploadIntentID []byte
|
|
ActorID []byte
|
|
}
|
|
|
|
type CreateFileFromUploadParams struct {
|
|
UploadFileID []byte
|
|
FolderID []byte
|
|
FolderProvided bool
|
|
Name *string
|
|
ActorID []byte
|
|
IsTemplate bool
|
|
}
|
|
|
|
type CreateFileFromUploadIntentParams struct {
|
|
UploadIntentID []byte
|
|
FolderID []byte
|
|
FolderProvided bool
|
|
Name string
|
|
ActorID []byte
|
|
IsTemplate bool
|
|
}
|
|
|
|
type BulkFileNodeResult struct {
|
|
Index int
|
|
File *File
|
|
Err error
|
|
}
|
|
|
|
type MoveFileParams struct {
|
|
Name *string
|
|
FolderID []byte
|
|
FolderProvided bool
|
|
ActorID []byte
|
|
}
|
|
|
|
type CreateAttachmentParams struct {
|
|
FileID []byte
|
|
RefType string
|
|
RefID string
|
|
Category *string
|
|
SortOrder int
|
|
IsPrimary bool
|
|
ActorID []byte
|
|
}
|
|
|
|
type ListAttachmentsParams struct {
|
|
RefType string
|
|
RefID string
|
|
Category *string
|
|
Sort string
|
|
Limit int
|
|
Offset int
|
|
}
|
|
|
|
type FileCleanupStats struct {
|
|
Scanned int
|
|
Deleted int
|
|
Skipped int
|
|
Failed int
|
|
DryRun bool
|
|
}
|
|
|
|
// LifecycleManager is an optional extension implemented by concrete services
|
|
// to expose file lifecycle transitions without widening the base Service
|
|
// interface used by existing handlers/tests.
|
|
type LifecycleManager interface {
|
|
MarkFileActive(ctx context.Context, fileID []byte, actorID []byte) error
|
|
ReconcileFileLifecycle(ctx context.Context, fileID []byte, actorID []byte) error
|
|
CleanupOrphanPendingFiles(ctx context.Context, now time.Time, gracePeriod time.Duration, limit int, dryRun bool) (FileCleanupStats, error)
|
|
}
|
|
|
|
type Service interface {
|
|
SetObjectStorage(storage ObjectStorage)
|
|
SetUploadPolicy(policy FileUploadPolicy)
|
|
SetFileProcessingQueue(fileQueue FileProcessingQueue)
|
|
SetFileUploadIntentRepository(repo FileUploadIntentRepository)
|
|
RequestFileUploadIntent(ctx context.Context, params RequestFileUploadIntentParams) (*FileUploadIntentGrant, error)
|
|
CompleteFileUploadIntent(ctx context.Context, params CompleteFileUploadIntentParams) (*File, error)
|
|
CancelFileUploadIntent(ctx context.Context, params CancelFileUploadIntentParams) error
|
|
CreateFileNodeFromUploadIntent(ctx context.Context, params CreateFileFromUploadIntentParams) (*File, error)
|
|
GetOrCreateSystemRootFolder(ctx context.Context) (*Folder, error)
|
|
CreateFolderNode(ctx context.Context, params CreateFolderParams) (*Folder, error)
|
|
MoveFolderNode(ctx context.Context, id []byte, params MoveFolderParams) (*Folder, error)
|
|
UploadFileNode(ctx context.Context, params UploadFileParams) (*File, error)
|
|
CreateFileNodeFromUpload(ctx context.Context, params CreateFileFromUploadParams) (*File, error)
|
|
UploadFileNodesBulk(ctx context.Context, params []UploadFileParams) []BulkFileNodeResult
|
|
CreateFileNodesFromUploadBulk(ctx context.Context, params []CreateFileFromUploadParams) []BulkFileNodeResult
|
|
MoveFileNode(ctx context.Context, id []byte, params MoveFileParams) (*File, error)
|
|
PurgeFolderNode(ctx context.Context, id []byte) error
|
|
PurgeFileNode(ctx context.Context, id []byte) error
|
|
ListNodesByParent(ctx context.Context, parentID []byte) ([]Folder, []File, error)
|
|
SearchNodes(ctx context.Context, query string) ([]Folder, []File, error)
|
|
ListTrashNodes(ctx context.Context) ([]Folder, []File, error)
|
|
|
|
CreateFolder(ctx context.Context, row *Folder) error
|
|
UpdateFolder(ctx context.Context, row *Folder) error
|
|
DeleteFolder(ctx context.Context, id []byte, deletedBy []byte, purgeAt *time.Time) error
|
|
RestoreFolder(ctx context.Context, id []byte, targetParentID []byte, targetProvided bool, restoredBy []byte) error
|
|
PurgeFolder(ctx context.Context, id []byte) error
|
|
GetFolderByID(ctx context.Context, id []byte) (*Folder, error)
|
|
GetFolderByIDAny(ctx context.Context, id []byte) (*Folder, error)
|
|
GetFolderByParentAndName(ctx context.Context, parentID []byte, nameNormalized string) (*Folder, error)
|
|
ListFoldersByParent(ctx context.Context, parentID []byte, sort string, limit, offset int) ([]Folder, int64, error)
|
|
ListTrashFoldersByParent(ctx context.Context, parentID []byte, sort string, limit, offset int) ([]Folder, int64, error)
|
|
|
|
CreateFile(ctx context.Context, row *File) error
|
|
UpdateFile(ctx context.Context, row *File) error
|
|
DeleteFile(ctx context.Context, id []byte, deletedBy []byte, purgeAt *time.Time) error
|
|
RestoreFile(ctx context.Context, id []byte, targetFolderID []byte, targetProvided bool, restoredBy []byte) error
|
|
PurgeFile(ctx context.Context, id []byte) error
|
|
GetFileByID(ctx context.Context, id []byte) (*File, error)
|
|
GetFileByIDAny(ctx context.Context, id []byte) (*File, error)
|
|
GetFileByObjectKey(ctx context.Context, objectKey string) (*File, error)
|
|
GetFileByFolderAndName(ctx context.Context, folderID []byte, nameNormalized string) (*File, error)
|
|
ListFilesByFolder(ctx context.Context, folderID []byte, sort string, limit, offset int) ([]File, int64, error)
|
|
ListTrashFilesByFolder(ctx context.Context, folderID []byte, sort string, limit, offset int) ([]File, int64, error)
|
|
CreateAttachment(ctx context.Context, params CreateAttachmentParams) (*Attachment, error)
|
|
GetAttachmentByID(ctx context.Context, id []byte) (*Attachment, error)
|
|
ListAttachmentsByReference(ctx context.Context, params ListAttachmentsParams) ([]Attachment, int64, error)
|
|
DeleteAttachment(ctx context.Context, id []byte) error
|
|
ListEditedWBFilesByTakeoverID(ctx context.Context, takeoverID []byte) ([]File, error)
|
|
}
|