feat: add S3 storage support, policy migration, and quota enforcement
Some checks failed
Test / test (push) Failing after 2m21s
Some checks failed
Test / test (push) Failing after 2m21s
- Add S3StorageService with AWS Signature V4 signing (URI-encoded for non-ASCII keys)
- Add PATCH /object/{id}/policy endpoint for switching storage policies with background migration
- Implement cross-storage file migration service (local <-> S3)
- Replace deprecated StorageType enum with PolicyType (local/s3)
- Implement GET /user/settings/policies endpoint (was 501 stub)
- Add storage quota pre-allocation on upload session creation to prevent concurrent bypass
- Fix BigInteger for max_storage and user.storage to support >2GB values
- Add policy permission validation on upload and directory creation
- Use group's first policy as default on registration instead of hardcoded name
- Define TaskType.POLICY_MIGRATE and extend TaskProps with migration fields
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,8 @@ from sqlmodel import Field, Relationship, CheckConstraint, Index, text
|
||||
|
||||
from sqlmodel_ext import SQLModelBase, UUIDTableBaseMixin
|
||||
|
||||
from .policy import PolicyType
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .user import User
|
||||
from .policy import Policy
|
||||
@@ -23,18 +25,6 @@ class ObjectType(StrEnum):
|
||||
FILE = "file"
|
||||
FOLDER = "folder"
|
||||
|
||||
class StorageType(StrEnum):
|
||||
"""存储类型枚举"""
|
||||
LOCAL = "local"
|
||||
QINIU = "qiniu"
|
||||
TENCENT = "tencent"
|
||||
ALIYUN = "aliyun"
|
||||
ONEDRIVE = "onedrive"
|
||||
GOOGLE_DRIVE = "google_drive"
|
||||
DROPBOX = "dropbox"
|
||||
WEBDAV = "webdav"
|
||||
REMOTE = "remote"
|
||||
|
||||
|
||||
class FileMetadataBase(SQLModelBase):
|
||||
"""文件元数据基础模型"""
|
||||
@@ -156,7 +146,7 @@ class PolicyResponse(SQLModelBase):
|
||||
name: str
|
||||
"""策略名称"""
|
||||
|
||||
type: StorageType
|
||||
type: PolicyType
|
||||
"""存储类型"""
|
||||
|
||||
max_size: int = Field(ge=0, default=0, sa_type=BigInteger)
|
||||
@@ -624,6 +614,12 @@ class UploadSession(UploadSessionBase, UUIDTableBaseMixin):
|
||||
storage_path: str | None = Field(default=None, max_length=512)
|
||||
"""文件存储路径"""
|
||||
|
||||
s3_upload_id: str | None = Field(default=None, max_length=256)
|
||||
"""S3 Multipart Upload ID(仅 S3 策略使用)"""
|
||||
|
||||
s3_part_etags: str | None = None
|
||||
"""S3 已上传分片的 ETag 列表,JSON 格式 [[1,"etag1"],[2,"etag2"]](仅 S3 策略使用)"""
|
||||
|
||||
expires_at: datetime
|
||||
"""会话过期时间"""
|
||||
|
||||
@@ -732,6 +728,16 @@ class CreateFileRequest(SQLModelBase):
|
||||
"""存储策略UUID,不指定则使用父目录的策略"""
|
||||
|
||||
|
||||
class ObjectSwitchPolicyRequest(SQLModelBase):
|
||||
"""切换对象存储策略请求"""
|
||||
|
||||
policy_id: UUID
|
||||
"""目标存储策略UUID"""
|
||||
|
||||
is_migrate_existing: bool = False
|
||||
"""(仅目录)是否迁移已有文件,默认 false 只影响新文件"""
|
||||
|
||||
|
||||
# ==================== 对象操作相关 DTO ====================
|
||||
|
||||
class ObjectCopyRequest(SQLModelBase):
|
||||
|
||||
Reference in New Issue
Block a user