Coverage for src/kwai/api/v1/news/endpoints/news.py: 85%
65 statements
« prev ^ index » next coverage.py v7.6.10, created at 2024-01-01 00:00 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2024-01-01 00:00 +0000
1"""Module that implements the endpoints for news."""
3from fastapi import APIRouter, Depends, HTTPException, Query, status
4from pydantic import BaseModel, Field
6from kwai.api.dependencies import create_database, get_current_user, get_optional_user
7from kwai.api.schemas.news_item import NewsItemDocument
8from kwai.core.domain.use_case import TextCommand
9from kwai.core.domain.value_objects.owner import Owner
10from kwai.core.json_api import Meta, PaginationModel
11from kwai.modules.identity.users.user import UserEntity
12from kwai.modules.portal.applications.application_db_repository import (
13 ApplicationDbRepository,
14)
15from kwai.modules.portal.create_news_item import CreateNewsItem, CreateNewsItemCommand
16from kwai.modules.portal.delete_news_item import DeleteNewsItem, DeleteNewsItemCommand
17from kwai.modules.portal.get_news_item import GetNewsItem, GetNewsItemCommand
18from kwai.modules.portal.get_news_items import GetNewsItems, GetNewsItemsCommand
19from kwai.modules.portal.news.news_item_db_repository import NewsItemDbRepository
20from kwai.modules.portal.news.news_item_repository import NewsItemNotFoundException
21from kwai.modules.portal.update_news_item import UpdateNewsItem, UpdateNewsItemCommand
24router = APIRouter()
27class NewsFilterModel(BaseModel):
28 """Define the JSON:API filter for news."""
30 enabled: bool = Field(Query(default=True, alias="filter[enabled]"))
31 publish_year: int = Field(Query(default=0, alias="filter[publish_year]"))
32 publish_month: int = Field(Query(default=0, alias="filter[publish_month]"))
33 application: str | None = Field(Query(default=None, alias="filter[application]"))
34 promoted: bool = Field(Query(default=False, alias="filter[promoted]"))
35 author: str | None = Field(Query(default=None, alias="filter[author]"))
38@router.get("/news_items")
39async def get_news_items(
40 pagination: PaginationModel = Depends(PaginationModel),
41 news_filter: NewsFilterModel = Depends(NewsFilterModel),
42 db=Depends(create_database),
43 user: UserEntity | None = Depends(get_optional_user),
44) -> NewsItemDocument:
45 """Get news items."""
46 # Only a know user is allowed to see disabled news.
47 if user is None and not news_filter.enabled:
48 raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
50 command = GetNewsItemsCommand(
51 offset=pagination.offset or 0,
52 limit=pagination.limit or 10,
53 enabled=news_filter.enabled,
54 publish_year=news_filter.publish_year,
55 publish_month=news_filter.publish_month,
56 application=news_filter.application,
57 promoted=news_filter.promoted,
58 author_uuid=news_filter.author,
59 )
60 count, news_item_iterator = await GetNewsItems(NewsItemDbRepository(db)).execute(
61 command
62 )
64 result = NewsItemDocument(
65 meta=Meta(count=count, offset=command.offset, limit=command.limit), data=[]
66 )
68 async for news_item in news_item_iterator:
69 news_document = NewsItemDocument.create(news_item)
70 result.merge(news_document)
72 return result
75@router.get("/news_items/{id}")
76async def get_news_item(
77 id: int,
78 db=Depends(create_database),
79 user: UserEntity | None = Depends(get_optional_user),
80) -> NewsItemDocument:
81 """Get a news item."""
82 command = GetNewsItemCommand(id=id)
84 try:
85 news_item = await GetNewsItem(NewsItemDbRepository(db)).execute(command)
86 except NewsItemNotFoundException as ex:
87 raise HTTPException(
88 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
89 ) from ex
91 # Only a know user is allowed to see disabled news.
92 if not user and not news_item.is_enabled:
93 raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
95 return NewsItemDocument.create(news_item)
98@router.post("/news_items", status_code=status.HTTP_201_CREATED)
99async def create_news_item(
100 resource: NewsItemDocument,
101 db=Depends(create_database),
102 user: UserEntity = Depends(get_current_user),
103) -> NewsItemDocument:
104 """Create a new news item."""
105 command = CreateNewsItemCommand(
106 enabled=resource.data.attributes.enabled,
107 texts=[
108 TextCommand(
109 locale=text.locale,
110 format=text.format,
111 title=text.title,
112 summary=text.original_summary,
113 content=text.original_content,
114 )
115 for text in resource.data.attributes.texts
116 ],
117 application=int(resource.data.relationships.application.data.id),
118 publish_datetime=resource.data.attributes.publish_date,
119 end_datetime=resource.data.attributes.end_date,
120 promotion=resource.data.attributes.priority,
121 promotion_end_datetime=resource.data.attributes.promotion_end_date,
122 remark=resource.data.attributes.remark,
123 )
124 news_item = await CreateNewsItem(
125 NewsItemDbRepository(db),
126 ApplicationDbRepository(db),
127 Owner(id=user.id, uuid=user.uuid, name=user.name),
128 ).execute(command)
130 return NewsItemDocument.create(news_item)
133@router.patch(
134 "/news_items/{id}",
135 status_code=status.HTTP_200_OK,
136 responses={status.HTTP_404_NOT_FOUND: {"description": "News item was not found."}},
137)
138async def update_news_item(
139 id: int,
140 resource: NewsItemDocument,
141 db=Depends(create_database),
142 user: UserEntity = Depends(get_current_user),
143) -> NewsItemDocument:
144 """Update a new news item."""
145 command = UpdateNewsItemCommand(
146 id=id,
147 enabled=resource.data.attributes.enabled,
148 texts=[
149 TextCommand(
150 locale=text.locale,
151 format=text.format,
152 title=text.title,
153 summary=text.original_summary,
154 content=text.original_content,
155 )
156 for text in resource.data.attributes.texts
157 ],
158 application=int(resource.data.relationships.application.data.id),
159 publish_datetime=resource.data.attributes.publish_date,
160 end_datetime=resource.data.attributes.end_date,
161 promotion=resource.data.attributes.priority,
162 promotion_end_datetime=resource.data.attributes.promotion_end_date,
163 remark=resource.data.attributes.remark,
164 )
165 try:
166 news_item = await UpdateNewsItem(
167 NewsItemDbRepository(db),
168 ApplicationDbRepository(db),
169 Owner(id=user.id, uuid=user.uuid, name=user.name),
170 ).execute(command)
171 except NewsItemNotFoundException as ex:
172 raise HTTPException(
173 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
174 ) from ex
176 return NewsItemDocument.create(news_item)
179@router.delete(
180 "/news_items/{id}",
181 status_code=status.HTTP_200_OK,
182 responses={status.HTTP_404_NOT_FOUND: {"description": "News Item was not found."}},
183)
184async def delete_news_item(
185 id: int,
186 db=Depends(create_database),
187 user: UserEntity = Depends(get_current_user),
188):
189 """Delete a new news item."""
190 command = DeleteNewsItemCommand(id=id)
192 try:
193 await DeleteNewsItem(NewsItemDbRepository(db)).execute(command)
194 except NewsItemNotFoundException as ex:
195 raise HTTPException(
196 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
197 ) from ex