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:
@@ -247,11 +247,12 @@ async def router_user_register(
|
||||
)
|
||||
await identity.save(session)
|
||||
|
||||
# 8. 创建用户根目录
|
||||
default_policy = await sqlmodels.Policy.get(session, sqlmodels.Policy.name == "本地存储")
|
||||
if not default_policy:
|
||||
logger.error("默认存储策略不存在")
|
||||
# 8. 创建用户根目录(使用用户组关联的第一个存储策略)
|
||||
await session.refresh(default_group, ['policies'])
|
||||
if not default_group.policies:
|
||||
logger.error("默认用户组未关联任何存储策略")
|
||||
http_exceptions.raise_internal_error()
|
||||
default_policy = default_group.policies[0]
|
||||
|
||||
await sqlmodels.Object(
|
||||
name="/",
|
||||
|
||||
@@ -13,6 +13,7 @@ from sqlmodels import (
|
||||
AuthIdentity, AuthIdentityResponse, AuthProviderType, BindIdentityRequest,
|
||||
ChangePasswordRequest,
|
||||
AuthnDetailResponse, AuthnRenameRequest,
|
||||
PolicySummary,
|
||||
)
|
||||
from sqlmodels.color import ThemeColorsBase
|
||||
from sqlmodels.user_authn import UserAuthn
|
||||
@@ -31,16 +32,25 @@ user_settings_router.include_router(file_viewers_router)
|
||||
@user_settings_router.get(
|
||||
path='/policies',
|
||||
summary='获取用户可选存储策略',
|
||||
description='Get user selectable storage policies.',
|
||||
)
|
||||
def router_user_settings_policies() -> sqlmodels.ResponseBase:
|
||||
async def router_user_settings_policies(
|
||||
session: SessionDep,
|
||||
user: Annotated[sqlmodels.user.User, Depends(auth_required)],
|
||||
) -> list[PolicySummary]:
|
||||
"""
|
||||
Get user selectable storage policies.
|
||||
获取当前用户所在组可选的存储策略列表
|
||||
|
||||
Returns:
|
||||
dict: A dictionary containing available storage policies for the user.
|
||||
返回用户组关联的所有存储策略的摘要信息。
|
||||
"""
|
||||
http_exceptions.raise_not_implemented()
|
||||
group = await user.awaitable_attrs.group
|
||||
await session.refresh(group, ['policies'])
|
||||
return [
|
||||
PolicySummary(
|
||||
id=p.id, name=p.name, type=p.type,
|
||||
server=p.server, max_size=p.max_size, is_private=p.is_private,
|
||||
)
|
||||
for p in group.policies
|
||||
]
|
||||
|
||||
|
||||
@user_settings_router.get(
|
||||
|
||||
Reference in New Issue
Block a user