feat: migrate ORM base to sqlmodel-ext, add file viewers and WOPI integration
All checks were successful
Test / test (push) Successful in 1m45s

- 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>
This commit is contained in:
2026-02-14 14:23:17 +08:00
parent 53b757de7a
commit ccadfe57cd
81 changed files with 5106 additions and 4837 deletions

View File

@@ -0,0 +1,77 @@
"""
WOPI Token 单元测试
测试 WOPI 访问令牌的生成和验证。
"""
from uuid import uuid4
import pytest
import utils.JWT as JWT
from utils.JWT.wopi_token import create_wopi_token, verify_wopi_token
# 确保测试 secret key
JWT.SECRET_KEY = "test_secret_key_for_jwt_token_generation"
class TestWopiToken:
"""WOPI Token 测试"""
def test_create_and_verify_token(self) -> None:
"""创建和验证令牌"""
file_id = uuid4()
user_id = uuid4()
token, ttl = create_wopi_token(file_id, user_id, can_write=True)
assert isinstance(token, str)
assert isinstance(ttl, int)
assert ttl > 0
payload = verify_wopi_token(token)
assert payload is not None
assert payload.file_id == file_id
assert payload.user_id == user_id
assert payload.can_write is True
def test_verify_read_only_token(self) -> None:
"""验证只读令牌"""
file_id = uuid4()
user_id = uuid4()
token, ttl = create_wopi_token(file_id, user_id, can_write=False)
payload = verify_wopi_token(token)
assert payload is not None
assert payload.can_write is False
def test_verify_invalid_token(self) -> None:
"""验证无效令牌返回 None"""
payload = verify_wopi_token("invalid_token_string")
assert payload is None
def test_verify_non_wopi_token(self) -> None:
"""验证非 WOPI 类型令牌返回 None"""
import jwt as pyjwt
# 创建一个不含 type=wopi 的令牌
token = pyjwt.encode(
{"file_id": str(uuid4()), "user_id": str(uuid4()), "type": "download"},
JWT.SECRET_KEY,
algorithm="HS256",
)
payload = verify_wopi_token(token)
assert payload is None
def test_ttl_is_future_milliseconds(self) -> None:
"""TTL 应为未来的毫秒时间戳"""
import time
file_id = uuid4()
user_id = uuid4()
token, ttl = create_wopi_token(file_id, user_id)
current_ms = int(time.time() * 1000)
# TTL 应大于当前时间
assert ttl > current_ms
# TTL 不应超过 11 小时后10h + 余量)
assert ttl < current_ms + 11 * 3600 * 1000