Files
disknext/routers/api/v1/file/viewers/__init__.py
于小丘 eac0766e79 feat: migrate ORM base to sqlmodel-ext, add file viewers and WOPI integration
- Migrate SQLModel base classes, mixins, and database management to
  external sqlmodel-ext package; remove sqlmodels/base/, sqlmodels/mixin/,
  and sqlmodels/database.py
- Add file viewer/editor system with WOPI protocol support for
  collaborative editing (OnlyOffice, Collabora)
- Add enterprise edition license verification module (ee/)
- Add Dockerfile multi-stage build with Cython compilation support
- Add new dependencies: sqlmodel-ext, cryptography, whatthepatch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 14:23:17 +08:00

107 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
文件查看器查询端点
提供按文件扩展名查询可用查看器的功能,包含用户组访问控制过滤。
"""
from typing import Annotated
from uuid import UUID
from fastapi import APIRouter, Depends, Query
from sqlalchemy import and_
from sqlalchemy import select
from middleware.auth import auth_required
from middleware.dependencies import SessionDep
from sqlmodels import (
FileApp,
FileAppExtension,
FileAppGroupLink,
FileAppSummary,
FileViewersResponse,
User,
UserFileAppDefault,
)
viewers_router = APIRouter(prefix="/viewers", tags=["file", "viewers"])
@viewers_router.get(
path='',
summary='查询可用文件查看器',
description='根据文件扩展名查询可用的查看器应用列表。',
)
async def get_viewers(
session: SessionDep,
user: Annotated[User, Depends(auth_required)],
ext: Annotated[str, Query(max_length=20, description="文件扩展名")],
) -> FileViewersResponse:
"""
查询可用文件查看器端点
流程:
1. 规范化扩展名(小写,去点号)
2. 查询匹配的已启用应用
3. 按用户组权限过滤
4. 按 priority 排序
5. 查询用户默认偏好
认证JWT token 必填
错误处理:
- 401: 未授权
"""
# 规范化扩展名
normalized_ext = ext.lower().strip().lstrip('.')
# 查询匹配扩展名的应用(已启用的)
ext_records: list[FileAppExtension] = await FileAppExtension.get(
session,
and_(
FileAppExtension.extension == normalized_ext,
),
fetch_mode="all",
load=FileAppExtension.app,
)
# 过滤和收集可用应用
user_group_id = user.group_id
viewers: list[tuple[FileAppSummary, int]] = []
for ext_record in ext_records:
app: FileApp = ext_record.app
if not app.is_enabled:
continue
if app.is_restricted:
# 检查用户组权限FileAppGroupLink 是纯关联表,使用 session 查询)
stmt = select(FileAppGroupLink).where(
and_(
FileAppGroupLink.app_id == app.id,
FileAppGroupLink.group_id == user_group_id,
)
)
result = await session.exec(stmt)
group_link = result.first()
if not group_link:
continue
viewers.append((app.to_summary(), ext_record.priority))
# 按 priority 排序
viewers.sort(key=lambda x: x[1])
# 查询用户默认偏好
user_default: UserFileAppDefault | None = await UserFileAppDefault.get(
session,
and_(
UserFileAppDefault.user_id == user.id,
UserFileAppDefault.extension == normalized_ext,
),
)
return FileViewersResponse(
viewers=[v[0] for v in viewers],
default_viewer_id=user_default.app_id if user_default else None,
)