from typing import List, Optional from fastapi import Depends, HTTPException, Path, Query from starlette import status from app.api.dependencies.authentication import get_current_user_authorizer from app.api.dependencies.database import get_repository from app.db.errors import EntityDoesNotExist from app.db.repositories.articles import ArticlesRepository from app.models.domain.articles import Article from app.models.domain.users import User from app.models.schemas.articles import ( DEFAULT_ARTICLES_LIMIT, DEFAULT_ARTICLES_OFFSET, ArticlesFilters, ) from app.resources import strings from app.services.articles import check_user_can_modify_article def get_articles_filters( tag: Optional[str] = None, tags: Optional[List[str]] = Query(default=None), author: Optional[str] = None, favorited: Optional[str] = None, search: Optional[str] = Query(default=None, description="搜索标题/描述/slug"), limit: int = Query(DEFAULT_ARTICLES_LIMIT, ge=1), offset: int = Query(DEFAULT_ARTICLES_OFFSET, ge=0), ) -> ArticlesFilters: final_tags: Optional[List[str]] = tags # 兼容旧的 tag 单值参数:若提供则与 tags 合并并去重 if tag: final_tags = list({*(final_tags or []), tag}) return ArticlesFilters( tag=tag, tags=final_tags, author=author, favorited=favorited, search=search, limit=limit, offset=offset, ) async def get_article_by_slug_from_path( slug: str = Path(..., min_length=1), user: Optional[User] = Depends(get_current_user_authorizer(required=False)), articles_repo: ArticlesRepository = Depends(get_repository(ArticlesRepository)), ) -> Article: try: return await articles_repo.get_article_by_slug(slug=slug, requested_user=user) except EntityDoesNotExist: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=strings.ARTICLE_DOES_NOT_EXIST_ERROR, ) def check_article_modification_permissions( current_article: Article = Depends(get_article_by_slug_from_path), user: User = Depends(get_current_user_authorizer()), ) -> None: if not check_user_can_modify_article(current_article, user): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=strings.USER_IS_NOT_AUTHOR_OF_ARTICLE, )