新增用户应用管理

This commit is contained in:
18610128193
2026-06-10 10:39:37 +08:00
parent bec4f6b419
commit d8bfebdcfb
6 changed files with 292 additions and 0 deletions
+4
View File
@@ -16,6 +16,8 @@ from app.api.v1.video_engines import router as video_engines_router
from app.api.v1.image_engines import router as image_engines_router
from app.api.v1.generation_ai import router as generation_ai_router
from app.api.v1.test import router as test_router
from app.api.v1.user_oauth import router as user_oauth_router
from app.api.v1.user_oauth_app import router as user_oauth_app_router
api_router = APIRouter()
api_router.include_router(auth_router)
@@ -34,3 +36,5 @@ api_router.include_router(video_engines_router)
api_router.include_router(image_engines_router)
api_router.include_router(generation_ai_router)
api_router.include_router(test_router)
api_router.include_router(user_oauth_router)
api_router.include_router(user_oauth_app_router)
@@ -0,0 +1,96 @@
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.dependencies import get_admin_user, get_db
from app.models.user import User
from app.schemas.user_oauth_app import UserOAuthAppCreate, UserOAuthAppOut, UserOAuthAppUpdate
from app.services.user_oauth_app_service import (
create_user_oauth_app,
delete_user_oauth_app,
get_user_oauth_app_by_id,
list_user_oauth_apps,
update_user_oauth_app,
)
router = APIRouter(prefix="/user-oauth-apps", tags=["oauth"])
@router.get("/list", summary="获取用户授权应用列表")
async def list_apps(
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=100),
open_type: int | None = Query(None, ge=1, le=10, description="开户方式"),
status: int | None = Query(None, ge=1, le=2, description="应用状态,1=正常,2=禁用"),
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
app_id: str | None = Query(None, max_length=255, description="应用id"),
):
result = await list_user_oauth_apps(db, page, page_size, open_type, status, admin.id, app_id)
return {
"total": result["total"],
"page": result["page"],
"page_size": result["page_size"],
"items": [UserOAuthAppOut.model_validate(item) for item in result["items"]],
}
@router.post("/create", summary="创建用户授权应用", response_model=UserOAuthAppOut, status_code=status.HTTP_201_CREATED)
async def create_app(
req: UserOAuthAppCreate,
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
try:
app = await create_user_oauth_app(db, req.app_id, req.secret, req.open_type, admin.id)
return app
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
)
@router.get("/read/{id}", summary="获取用户授权应用详情", response_model=UserOAuthAppOut)
async def get_app(
id: str,
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
app = await get_user_oauth_app_by_id(db, id)
if not app:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="应用不存在",
)
return app
@router.post("/update/{id}", summary="更新用户授权应用", response_model=UserOAuthAppOut)
async def update_app(
id: str,
req: UserOAuthAppUpdate,
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
app = await update_user_oauth_app(db, id, req.secret, req.open_type, req.status, admin.id)
if not app:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="应用不存在",
)
return app
@router.get("/delete/{id}", summary="删除用户授权应用")
async def delete_app(
id: str,
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
success = await delete_user_oauth_app(db, id, admin.id)
if not success:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="应用不存在",
)
return {"message": "删除成功"}
+4
View File
@@ -21,6 +21,9 @@ from app.models.chat_provider_call_log import ChatProviderCallLog
from app.models.generated_resource import GeneratedResource
from app.models.user_resource_month_stat import UserResourceMonthStat
from app.models.user_resource_total_stat import UserResourceTotalStat
from app.models.user_oauth import UserOAuth
from app.models.user_oauth_account import UserOAuthAccount
from app.models.user_oauth_app import UserOAuthApp
__all__ = [
"Base", "TimestampMixin", "SoftDeleteMixin", "engine", "async_session",
@@ -31,4 +34,5 @@ __all__ = [
"MenuConfig", "RechargePackage", "OperationLog",
"ChatGenerationTask", "ChatGenerationTaskEvent", "ChatProviderCallLog",
"GeneratedResource", "UserResourceMonthStat", "UserResourceTotalStat",
"UserOAuth", "UserOAuthAccount", "UserOAuthApp",
]
@@ -0,0 +1,27 @@
from sqlalchemy import BigInteger, ForeignKey, String
from sqlalchemy.orm import Mapped, mapped_column
from app.models.base import Base, TimestampMixin, SoftDeleteMixin
class UserOAuthApp(Base, TimestampMixin, SoftDeleteMixin):
__tablename__ = "user_oauth_app"
id: Mapped[str] = mapped_column(
String(32), primary_key=True, comment="主键"
)
app_id: Mapped[str] = mapped_column(
String(64), unique=True, nullable=False, index=True, comment="应用id"
)
secret: Mapped[str] = mapped_column(
String(256), nullable=False, comment="应用密钥"
)
status: Mapped[int] = mapped_column(
BigInteger, nullable=False, default=1, comment="状态,1=正常,2=禁用"
)
open_type: Mapped[int] = mapped_column(
BigInteger, nullable=False, index=True, comment="开户方式(1=千川,2=广告,3=本地推,4=星图,5=快手代理商,6=巨量星图,7=巨量服务单,8=腾讯服务单,9=腾讯营销K2,10=腾讯营销K3)"
)
create_by: Mapped[str | None] = mapped_column(
String(32), ForeignKey("users.id", ondelete="SET NULL"), nullable=True, comment="创建者"
)
@@ -0,0 +1,38 @@
from pydantic import BaseModel, Field
from app.schemas.common import NaiveDatetime
class UserOAuthAppCreate(BaseModel):
app_id: str = Field(..., max_length=64, description="应用id")
secret: str = Field(..., max_length=256, description="应用密钥")
open_type: int = Field(
...,
ge=1,
le=10,
description="开户方式(1=千川,2=广告,3=本地推,4=星图,5=快手代理商,6=巨量星图,7=巨量服务单,8=腾讯服务单,9=腾讯营销K2,10=腾讯营销K3)",
)
class UserOAuthAppUpdate(BaseModel):
secret: str | None = Field(None, max_length=256, description="应用密钥")
open_type: int | None = Field(
None,
ge=1,
le=10,
description="开户方式(1=千川,2=广告,3=本地推,4=星图,5=快手代理商,6=巨量星图,7=巨量服务单,8=腾讯服务单,9=腾讯营销K2,10=腾讯营销K3)",
)
status: int | None = Field(None, ge=1, le=2, description="应用状态(1=正常,2=禁用)")
class UserOAuthAppOut(BaseModel):
id: str = Field(..., description="主键")
app_id: str = Field(..., description="应用id")
secret: str = Field(..., description="应用密钥")
status: int = Field(..., description="状态,1=正常,2=禁用")
open_type: int = Field(..., description="开户方式")
create_by: str | None = Field(None, description="创建者")
created_at: NaiveDatetime = Field(..., description="创建时间")
updated_at: NaiveDatetime = Field(..., description="更新时间")
model_config = {"from_attributes": True}
@@ -0,0 +1,123 @@
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.user_oauth_app import UserOAuthApp
from app.utils.id_gen import generate_id
async def list_user_oauth_apps(
db: AsyncSession,
page: int = 1,
page_size: int = 20,
open_type: int | None = None,
status: int | None = None,
create_by: str | None = None,
app_id: str | None = None,
) -> dict:
query = select(UserOAuthApp).where(UserOAuthApp.deleted_at.is_(None)).order_by(UserOAuthApp.created_at.desc())
if open_type is not None:
query = query.where(UserOAuthApp.open_type == open_type)
if status is not None:
query = query.where(UserOAuthApp.status == status)
if create_by is not None:
query = query.where(UserOAuthApp.create_by == create_by)
if app_id is not None:
query = query.where(UserOAuthApp.app_id.like(f"%{app_id}%"))
total_result = await db.execute(select(func.count(UserOAuthApp.id)).where(UserOAuthApp.deleted_at.is_(None)))
total = total_result.scalar() or 0
result = await db.execute(query.offset((page - 1) * page_size).limit(page_size))
items = result.scalars().all()
return {
"total": total,
"page": page,
"page_size": page_size,
"items": items,
}
async def get_user_oauth_app_by_id(db: AsyncSession, id: str) -> UserOAuthApp | None:
result = await db.execute(
select(UserOAuthApp).where(UserOAuthApp.id == id, UserOAuthApp.deleted_at.is_(None)).limit(1)
)
return result.scalar_one_or_none()
async def get_user_oauth_app_by_app_id(db: AsyncSession, app_id: str) -> UserOAuthApp | None:
result = await db.execute(
select(UserOAuthApp).where(UserOAuthApp.app_id == app_id, UserOAuthApp.deleted_at.is_(None)).limit(1)
)
return result.scalar_one_or_none()
async def create_user_oauth_app(
db: AsyncSession,
app_id: str,
secret: str,
open_type: int,
create_by: str | None = None,
) -> UserOAuthApp:
existing = await get_user_oauth_app_by_app_id(db, app_id)
if existing:
raise ValueError("应用id已存在")
app = UserOAuthApp(
id=generate_id(),
app_id=app_id,
secret=secret,
open_type=open_type,
create_by=create_by,
)
db.add(app)
await db.flush()
return app
async def update_user_oauth_app(
db: AsyncSession,
id: str,
secret: str | None = None,
open_type: int | None = None,
status: int | None = None,
create_by: str | None = None,
) -> UserOAuthApp | None:
app = await get_user_oauth_app_by_id(db, id)
if not app:
return None
if secret is not None:
app.secret = secret
if open_type is not None:
app.open_type = open_type
if status is not None:
app.status = status
if create_by is not None:
app.create_by = create_by
await db.flush()
return app
async def delete_user_oauth_app(db: AsyncSession, id: str, create_by: str | None = None) -> bool:
app = await get_user_oauth_app_by_id(db, id)
if not app:
return False
app.deleted_at = func.now()
if create_by is not None:
app.create_by = create_by
await db.flush()
return True
async def get_apps_by_open_type(db: AsyncSession, open_type: int) -> list[UserOAuthApp]:
result = await db.execute(
select(UserOAuthApp).where(UserOAuthApp.open_type == open_type, UserOAuthApp.deleted_at.is_(None))
)
return result.scalars().all()