Files
server-core/app/main.py
T
Pine e831fdd34e feat: 内容审核体系(0070)— 违规内容库/举报表/IP采集/统一审核服务/审核API
- 迁移0070:content_moderation_records(违规库,快照+发布者+IP+原因+处置人)、
  content_reports(举报队列);各内容表加 ip 列,dm_messages 加 hidden,
  community_comments/ratings 加 status,users 加 profile_hidden/original_nickname
- moderation_service:hide/restore/delete(物理删除留档)/list/archive/report/
  handle_report/scan + 申诉通知;用户资料隐藏自动脱敏昵称
- rbac_moderation:/admin/moderation/{type} 列表、hide/restore/delete、
  violations 违规库、reports 举报处理、scan 巡查;/content/report 用户举报入口
- IP 采集:任务/岗位/服务/社区帖子/评论/私信/评价/主页提交创建端点写入发布者 IP
- 前台可见性:社区评论/私信查询过滤 hidden
2026-09-07 15:07:43 +08:00

150 lines
5.7 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.
# -*- coding: utf-8 -*-
"""FastAPI 应用入口(接口层组装)。
启动方式(项目根目录):
uv run uvicorn app.main:app --host 127.0.0.1 --port 8090
或使用脚本:``uv run python -m app``
"""
from __future__ import annotations
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app import config
from app.infrastructure.repositories import Database
from app.api.routers import agents as agents_router
from app.api.routers import auth as auth_router
from app.api.routers import bootstrap as bootstrap_router
from app.api.routers import rbac_admin as rbac_admin_router
from app.api.routers import rbac_hall as rbac_hall_router
from app.api.routers import rbac_service_market as rbac_service_market_router
from app.api.routers import rbac_pages as rbac_pages_router
from app.api.routers import rbac_opc as rbac_opc_router
from app.api.routers import rbac_operator as rbac_operator_router
from app.api.routers import rbac_agents as rbac_agents_router
from app.api.routers import rbac_public as rbac_public_router
from app.api.routers import rbac_org as rbac_org_router
from app.api.routers import rbac_portals as rbac_portals_router
from app.api.routers import rbac_certifications as rbac_certifications_router
from app.api.routers import rbac_training as rbac_training_router
from app.api.routers import rbac_credit as rbac_credit_router
from app.api.routers import rbac_ecosystem as rbac_ecosystem_router
from app.api.routers import rbac_enterprise as rbac_enterprise_router
from app.api.routers import rbac_desktop_updates as rbac_desktop_updates_router
from app.api.routers import rbac_moderation as rbac_moderation_router
from app.api.routers import templates as templates_router
from app.api.routers import relay as relay_router
from app.pay import routers as pay_router
from app.market import routers as market_router
from app.incubator import routers as incubator_router
from app.api.routers import invite as invite_router
from app.api.routers import rbac_compute_pricing as compute_pricing_router
from app.im import router as im_router
APP_NAME = "云超服Agents 演示后端"
@asynccontextmanager
async def lifespan(app: FastAPI):
"""启动时初始化数据库(建表 + 幂等种子)+ Redis 缓存连接。
若 ``app.state.db`` 已由外部注入(如测试夹具),则直接复用,
不重新创建,避免覆盖调用方准备的数据库实例。
"""
from .infrastructure.cache import cache as redis_cache
db = getattr(app.state, "db", None)
if db is None:
db = Database()
await db.initialize()
app.state.db = db
# 连接 Redis(失败自动降级为无缓存)
await redis_cache.connect()
app.state.cache = redis_cache
yield
# 关闭 Redis
await redis_cache.close()
if db is not None and db._owns_session:
await db.close()
# 释放引擎连接池,避免连接残留导致下次启动 initialize() 被锁挂起/连接泄漏
engine = getattr(db, "_engine", None)
if engine is not None:
try:
await engine.dispose()
except Exception: # noqa: BLE001
pass
app = FastAPI(
title=APP_NAME,
description=(
"云超服核心服务端:身份/平台 API + 培训子应用(/api/*),统一对外 opc.pinesound.cn。"
"异步四层架构(接口/业务/领域/基础设施)。"
),
version="0.1.0",
lifespan=lifespan,
)
# 演示服务允许任意来源(实际生产由主后端网关收敛)。
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(auth_router.router)
app.include_router(agents_router.router)
app.include_router(templates_router.router)
app.include_router(bootstrap_router.router)
app.include_router(rbac_admin_router.router)
app.include_router(rbac_opc_router.router)
app.include_router(rbac_operator_router.router)
app.include_router(rbac_agents_router.router)
app.include_router(rbac_public_router.router)
app.include_router(rbac_org_router.router)
app.include_router(rbac_portals_router.router)
app.include_router(rbac_hall_router.router)
app.include_router(rbac_service_market_router.router)
app.include_router(rbac_pages_router.router)
app.include_router(rbac_certifications_router.router)
app.include_router(rbac_training_router.router)
app.include_router(rbac_credit_router.router)
app.include_router(rbac_ecosystem_router.router)
app.include_router(rbac_enterprise_router.router)
app.include_router(rbac_desktop_updates_router.router)
app.include_router(rbac_desktop_updates_router.public_router)
app.include_router(rbac_hall_router.community_router)
app.include_router(rbac_moderation_router.router)
app.include_router(rbac_moderation_router.report_router)
app.include_router(rbac_hall_router.dm_router)
# compute_pricing 必须在 relay_router 之前注册:relay 有 /{path:path} catch-all
# 会吞掉 /api/compute/* 导致全部 404。
app.include_router(compute_pricing_router.router)
app.include_router(relay_router.router)
app.include_router(pay_router.router)
app.include_router(market_router.router)
app.include_router(market_router.admin_router)
app.include_router(incubator_router.router)
app.include_router(invite_router.router)
app.include_router(im_router.router)
@app.get("/health", tags=["meta"], summary="健康检查")
async def health():
return {
"status": "ok",
"service": "pineagents-demo-server",
"auth_enabled": config.AUTH_ENABLED,
}
@app.get("/", tags=["meta"], include_in_schema=False)
async def root():
return {
"service": APP_NAME,
"docs": "/docs",
"health": "/health",
}