Coverage for apps/kwai-api/src/kwai_api/v1/news/endpoints.py: 81%
79 statements
« prev ^ index » next coverage.py v7.11.0, created at 2024-01-01 00:00 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2024-01-01 00:00 +0000
1"""Module that implements the endpoints for /api/v1/news."""
3from fastapi import APIRouter, Depends, HTTPException, Query, status
4from kwai_bc_identity.users.user import UserEntity
5from kwai_bc_portal.applications.application_db_repository import (
6 ApplicationDbRepository,
7)
8from kwai_bc_portal.create_news_item import CreateNewsItem, CreateNewsItemCommand
9from kwai_bc_portal.delete_news_item import DeleteNewsItem, DeleteNewsItemCommand
10from kwai_bc_portal.get_news_item import GetNewsItem, GetNewsItemCommand
11from kwai_bc_portal.get_news_items import GetNewsItems, GetNewsItemsCommand
12from kwai_bc_portal.news.news_item_db_repository import NewsItemDbRepository
13from kwai_bc_portal.news.news_item_repository import NewsItemNotFoundException
14from kwai_bc_portal.update_news_item import UpdateNewsItem, UpdateNewsItemCommand
15from kwai_core.domain.exceptions import NotAllowedException
16from kwai_core.domain.use_case import TextCommand
17from kwai_core.domain.value_objects.owner import Owner
18from kwai_core.json_api import PaginationModel
19from pydantic import BaseModel, Field
21from kwai_api.dependencies import create_database, get_current_user, get_optional_user
22from kwai_api.v1.news.presenters import (
23 JsonApiNewsItemPresenter,
24 JsonApiNewsItemsPresenter,
25)
26from kwai_api.v1.news.schemas import NewsItemDocument, NewsItemsDocument
29router = APIRouter()
32class NewsFilterModel(BaseModel):
33 """Define the JSON:API filter for news."""
35 enabled: bool = Field(Query(default=True, alias="filter[enabled]"))
36 publish_year: int = Field(Query(default=0, alias="filter[publish_year]"))
37 publish_month: int = Field(Query(default=0, alias="filter[publish_month]"))
38 application: str | None = Field(Query(default=None, alias="filter[application]"))
39 promoted: bool = Field(Query(default=False, alias="filter[promoted]"))
40 author: str | None = Field(Query(default=None, alias="filter[author]"))
43@router.get("/news_items")
44async def get_news_items(
45 pagination: PaginationModel = Depends(PaginationModel),
46 news_filter: NewsFilterModel = Depends(NewsFilterModel),
47 db=Depends(create_database),
48 user: UserEntity | None = Depends(get_optional_user),
49) -> NewsItemsDocument:
50 """Get news items."""
51 # Only a know user is allowed to see disabled news.
52 if user is None and not news_filter.enabled:
53 raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
55 command = GetNewsItemsCommand(
56 offset=pagination.offset or 0,
57 limit=pagination.limit or 10,
58 enabled=news_filter.enabled,
59 publish_year=news_filter.publish_year,
60 publish_month=news_filter.publish_month,
61 application=news_filter.application,
62 promoted=news_filter.promoted,
63 author_uuid=news_filter.author,
64 )
65 presenter = JsonApiNewsItemsPresenter(user)
66 await GetNewsItems(NewsItemDbRepository(db), presenter).execute(command)
67 return presenter.get_document()
70@router.get("/news_items/{id}")
71async def get_news_item(
72 id: int,
73 db=Depends(create_database),
74 user: UserEntity | None = Depends(get_optional_user),
75) -> NewsItemDocument:
76 """Get a news item."""
77 command = GetNewsItemCommand(id=id)
78 presenter = JsonApiNewsItemPresenter(user)
79 try:
80 await GetNewsItem(NewsItemDbRepository(db), presenter).execute(command)
81 except NewsItemNotFoundException as ex:
82 raise HTTPException(
83 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
84 ) from ex
85 except NotAllowedException as ex:
86 raise HTTPException(
87 status_code=status.HTTP_403_FORBIDDEN, detail=str(ex)
88 ) from ex
90 return presenter.get_document()
93@router.post("/news_items", status_code=status.HTTP_201_CREATED)
94async def create_news_item(
95 resource: NewsItemDocument,
96 db=Depends(create_database),
97 user: UserEntity = Depends(get_current_user),
98) -> NewsItemDocument:
99 """Create a new news item."""
100 if resource.data.relationships is None:
101 raise HTTPException(
102 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
103 detail="Relationships data is missing.",
104 )
105 if resource.data.relationships.application.data is None:
106 raise HTTPException(
107 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
108 detail="Relationship application data should not be None.",
109 )
110 if resource.data.relationships.application.data.id is None:
111 raise HTTPException(
112 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
113 detail="Id of the application relationship should be set.",
114 )
116 command = CreateNewsItemCommand(
117 enabled=resource.data.attributes.enabled,
118 texts=[
119 TextCommand(
120 locale=text.locale,
121 format=text.format,
122 title=text.title,
123 summary=text.original_summary,
124 content=text.original_content or "",
125 )
126 for text in resource.data.attributes.texts
127 ],
128 application=int(resource.data.relationships.application.data.id),
129 publish_datetime=resource.data.attributes.publish_date,
130 end_datetime=resource.data.attributes.end_date,
131 promotion=resource.data.attributes.priority,
132 promotion_end_datetime=resource.data.attributes.promotion_end_date,
133 remark=resource.data.attributes.remark,
134 )
135 presenter = JsonApiNewsItemPresenter(user)
136 await CreateNewsItem(
137 NewsItemDbRepository(db),
138 ApplicationDbRepository(db),
139 Owner(id=user.id, uuid=user.uuid, name=user.name),
140 presenter,
141 ).execute(command)
143 return presenter.get_document()
146@router.patch(
147 "/news_items/{id}",
148 status_code=status.HTTP_200_OK,
149 responses={
150 status.HTTP_404_NOT_FOUND: {"description": "News item was not found."},
151 status.HTTP_422_UNPROCESSABLE_ENTITY: {"description": "Invalid data passed."},
152 },
153)
154async def update_news_item(
155 id: int,
156 resource: NewsItemDocument,
157 db=Depends(create_database),
158 user: UserEntity = Depends(get_current_user),
159) -> NewsItemDocument:
160 """Update a new news item."""
161 if resource.data.relationships is None:
162 raise HTTPException(
163 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
164 detail="Relationships data is missing.",
165 )
166 if resource.data.relationships.application.data is None:
167 raise HTTPException(
168 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
169 detail="Relationship application data should not be None.",
170 )
171 if resource.data.relationships.application.data.id is None:
172 raise HTTPException(
173 status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
174 detail="Id of the application relationship should be set.",
175 )
177 command = UpdateNewsItemCommand(
178 id=id,
179 enabled=resource.data.attributes.enabled,
180 texts=[
181 TextCommand(
182 locale=text.locale,
183 format=text.format,
184 title=text.title,
185 summary=text.original_summary,
186 content=text.original_content or "",
187 )
188 for text in resource.data.attributes.texts
189 ],
190 application=int(resource.data.relationships.application.data.id),
191 publish_datetime=resource.data.attributes.publish_date,
192 end_datetime=resource.data.attributes.end_date,
193 promotion=resource.data.attributes.priority,
194 promotion_end_datetime=resource.data.attributes.promotion_end_date,
195 remark=resource.data.attributes.remark,
196 )
197 presenter = JsonApiNewsItemPresenter(user)
198 try:
199 await UpdateNewsItem(
200 NewsItemDbRepository(db),
201 ApplicationDbRepository(db),
202 Owner(id=user.id, uuid=user.uuid, name=user.name),
203 presenter,
204 ).execute(command)
205 except NewsItemNotFoundException as ex:
206 raise HTTPException(
207 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
208 ) from ex
210 return presenter.get_document()
213@router.delete(
214 "/news_items/{id}",
215 status_code=status.HTTP_200_OK,
216 responses={status.HTTP_404_NOT_FOUND: {"description": "News Item was not found."}},
217)
218async def delete_news_item(
219 id: int,
220 db=Depends(create_database),
221 user: UserEntity = Depends(get_current_user),
222):
223 """Delete a new news item."""
224 command = DeleteNewsItemCommand(id=id)
226 try:
227 await DeleteNewsItem(NewsItemDbRepository(db)).execute(command)
228 except NewsItemNotFoundException as ex:
229 raise HTTPException(
230 status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
231 ) from ex