feat: 添加飞书用户模块和订阅功能支持 - 新增feishu_users模块用于处理飞书用户身份验证和权限管理 - 新增subscriptions模块用于处理订阅相关功能 - 新增personalization模块用于个性化服务 - 在alembic迁移配置中注册新的模型模块 - 在API路由器中添加feishu_users和subscriptions路由 - 实现事件调度服务的改进,包括错误处理和状态更新优化 - 添加飞书命令处理的权限检查机制 - 实现飞书应用票据事件处理 - 改进审计日志记录功能 ```
81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
from pathlib import Path
|
|
|
|
import pytest
|
|
from alembic import command
|
|
from alembic.config import Config
|
|
from sqlalchemy import create_engine, func, select
|
|
from sqlalchemy.orm import Session, sessionmaker
|
|
|
|
from app.core.config import get_settings
|
|
from app.core.config import Settings
|
|
from app.core.database import Base
|
|
from app.modules.audit.models import AuditLog
|
|
from app.modules.audit.schemas import AuditLogCreate
|
|
from app.modules.audit.service import AuditService
|
|
from app.modules.events.models import DomainEvent
|
|
from app.modules.events.services import EventService
|
|
from app.modules.risk.services import RiskService
|
|
|
|
|
|
def test_audit_and_outbox_rollback_with_business_transaction() -> None:
|
|
engine = create_engine("sqlite://")
|
|
Base.metadata.create_all(engine)
|
|
session_factory = sessionmaker(bind=engine, expire_on_commit=False)
|
|
|
|
with session_factory() as db:
|
|
AuditService(db).record(AuditLogCreate(action="transaction.rollback"))
|
|
EventService(db).enqueue(
|
|
event_type="test.rollback",
|
|
source="pytest",
|
|
aggregate_type="test",
|
|
aggregate_id="rollback",
|
|
idempotency_key="test-transaction-rollback",
|
|
)
|
|
db.rollback()
|
|
|
|
with session_factory() as db:
|
|
assert db.scalar(select(func.count()).select_from(AuditLog)) == 0
|
|
assert db.scalar(select(func.count()).select_from(DomainEvent)) == 0
|
|
|
|
|
|
def test_read_only_mode_allows_local_risk_state(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.setenv("READ_ONLY_MODE", "true")
|
|
get_settings.cache_clear()
|
|
engine = create_engine("sqlite://")
|
|
Base.metadata.create_all(engine)
|
|
try:
|
|
with Session(engine) as db:
|
|
result = RiskService(db).generate_events(actor="pytest")
|
|
|
|
assert result["created"] == 0
|
|
assert db.scalar(select(func.count()).select_from(AuditLog)) == 1
|
|
finally:
|
|
engine.dispose()
|
|
get_settings.cache_clear()
|
|
|
|
|
|
def test_production_settings_fail_closed() -> None:
|
|
with pytest.raises(ValueError, match="PostgreSQL"):
|
|
Settings(
|
|
app_env="production",
|
|
database_url="sqlite:///unsafe.db",
|
|
api_key="api",
|
|
audit_api_key="audit",
|
|
cors_origins=["https://internal.example.com"],
|
|
)
|
|
|
|
|
|
def test_migrations_match_sqlalchemy_metadata(
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
database_path = tmp_path / "migration-check.db"
|
|
monkeypatch.setenv("DATABASE_URL", f"sqlite:///{database_path}")
|
|
get_settings.cache_clear()
|
|
config = Config("alembic.ini")
|
|
try:
|
|
command.upgrade(config, "head")
|
|
command.check(config)
|
|
finally:
|
|
get_settings.cache_clear()
|