Skip to content

Commit ee5a491

Browse files
Create PUT news endpoint
- Add PUT news to router - Add update news to orm - Add publish to news model
1 parent 4612f31 commit ee5a491

File tree

5 files changed

+101
-26
lines changed

5 files changed

+101
-26
lines changed

app/routers/news/routes.py

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88

99
import app.services.database.orm.news as orm_news
1010
from app.routers.authentication import get_current_active_community
11-
from app.schemas import News
11+
from app.schemas import News, NewsPublishStatus
1212
from app.services.database.models import Community as DBCommunity
1313
from app.services.limiter import limiter
1414

1515
SECRET_KEY = os.getenv("SECRET_KEY", "default_fallback_key")
1616
ALGORITHM = os.getenv("ALGORITHM", "HS256")
1717

1818

19-
class NewsPostResponse(BaseModel):
19+
class NewsCreateResponse(BaseModel):
2020
status: str = "News Criada"
2121

2222

@@ -25,6 +25,10 @@ class NewsGetResponse(BaseModel):
2525
news_list: list = []
2626

2727

28+
class NewsUpdateResponse(BaseModel):
29+
status: str = "News Atualizada"
30+
31+
2832
class NewsLikeResponse(BaseModel):
2933
total_likes: int | None
3034

@@ -39,7 +43,7 @@ def setup():
3943

4044
@router.post(
4145
"",
42-
response_model=NewsPostResponse,
46+
response_model=NewsCreateResponse,
4347
status_code=status.HTTP_200_OK,
4448
summary="News endpoint",
4549
description="Creates news and returns a confirmation message",
@@ -61,7 +65,7 @@ async def post_news(
6165
await orm_news.create_news(
6266
session=request.app.db_session_factory, news=news_dict
6367
)
64-
return NewsPostResponse()
68+
return NewsCreateResponse()
6569

6670
@router.get(
6771
"",
@@ -93,6 +97,48 @@ async def get_news(
9397
)
9498
return NewsGetResponse(news_list=news_list)
9599

100+
@router.put(
101+
"",
102+
response_model=NewsGetResponse,
103+
status_code=status.HTTP_200_OK,
104+
summary="PUT News",
105+
description="Updates news by query params and set publish value",
106+
)
107+
@limiter.limit("60/minute")
108+
async def put_news(
109+
request: Request,
110+
current_community: Annotated[
111+
DBCommunity, Depends(get_current_active_community)
112+
],
113+
publish_status: NewsPublishStatus,
114+
id: str | None = None,
115+
title: str | None = None,
116+
content: str | None = None,
117+
category: str | None = None,
118+
user_email: str = str(Header(..., alias="user-email")),
119+
source_url: str | None = None,
120+
tags: str | None = None,
121+
social_media_url: str | None = None,
122+
):
123+
"""
124+
Get News endpoint that retrieves news filtered by user and query params.
125+
"""
126+
news: dict = {
127+
"id": id,
128+
"title": title,
129+
"content": content,
130+
"category": category,
131+
"user_email": user_email,
132+
"source_url": source_url,
133+
"tags": tags,
134+
"social_media_url": social_media_url,
135+
"publish": publish_status.publish,
136+
}
137+
await orm_news.update_news(
138+
session=request.app.db_session_factory, news=news
139+
)
140+
return NewsUpdateResponse()
141+
96142
@router.post(
97143
path="/{news_id}/like",
98144
response_model=NewsLikeResponse,

app/schemas.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ class News(BaseModel):
5454
likes: int = 0
5555

5656

57+
class NewsPublishStatus(BaseModel):
58+
publish: bool = False
59+
60+
5761
class Token(BaseModel):
5862
access_token: str
5963
token_type: str

app/services/database/models/news.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class News(SQLModel, table=True):
4949
user_email_list: str = Field(default="[]")
5050
social_media_url: str
5151
likes: int = Field(default=0)
52+
publish: bool = Field(default=False)
5253

5354
# Chaves estrangeiras
5455
community_id: Optional[int] = Field(

app/services/database/orm/news.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,20 @@ async def get_news_by_query_params(
4242

4343
statement = select(News).where(*filters)
4444
results = await session.exec(statement)
45-
return results.all()
45+
return list(results.all())
46+
47+
48+
async def update_news(session: AsyncSession, news: dict) -> None:
49+
statement = select(News).where(News.id == news["id"])
50+
results = await session.exec(statement)
51+
news_item = results.first()
52+
if news_item:
53+
for key, value in news.items():
54+
if key != "id" and value is not None:
55+
setattr(news_item, key, value)
56+
session.add(news_item)
57+
await session.commit()
58+
await session.refresh(news_item)
4659

4760

4861
async def like_news(

tests/test_news.py

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,8 @@ async def test_news_integration(
294294
async def test_put_news_endpoint(
295295
session: AsyncSession,
296296
async_client: AsyncClient,
297-
community: Community,
298297
valid_auth_headers: Mapping[str, str],
298+
news_list: list,
299299
):
300300
session.add_all(news_list)
301301
await session.commit()
@@ -304,35 +304,46 @@ async def test_put_news_endpoint(
304304
result = await session.exec(statement)
305305
stored_news = result.first()
306306
assert stored_news is not None
307+
assert stored_news.publish is False
308+
309+
data: dict = {
310+
"title": "updated title",
311+
"content": "updated content",
312+
"category": "updated_category",
313+
"user_email": "updated_email@test.com",
314+
"source_url": "https://updated_url.com",
315+
"tags": "test_tag_updated",
316+
"social_media_url": "https://updated_social_media_url.com",
317+
}
307318

308319
response = await async_client.put(
309320
"/api/news",
310321
params={
311-
"title": "updated title",
312-
"content": "updated content",
313-
"category": "updated_category",
314-
"user_email": "updated_email@test.com",
315-
"source_url": "https://updated_url.com",
316-
"tags": "test_tag_updated",
317-
"user_email_list": "updated_email@test.com",
318-
"social_media_url": "https://updated_social_media_url.com",
319-
"likes": 42,
322+
"id": stored_news.id,
323+
"title": data["title"],
324+
"content": data["content"],
325+
"category": data["category"],
326+
"user_email": data["user_email"],
327+
"source_url": data["source_url"],
328+
"tags": data["tags"],
329+
"social_media_url": data["social_media_url"],
320330
},
321331
headers=valid_auth_headers,
322332
json={"publish": True},
323333
)
324-
data = response.json()
325334
assert response.status_code == status.HTTP_200_OK
326-
assert data["tittle"] == "updated title"
327-
assert data["content"] == "updated content"
328-
assert data["category"] == "updated_category"
329-
assert data["user_email"] == "updated_email@test.com"
330-
assert data["source_url"] == "https://updated_url.com"
331-
assert data["tags"] == "test_tag_updated"
332-
assert data["user_email_list"] == "updated_email@test.com"
333-
assert data["social_media_url"] == "https://updated_social_media_url.com"
334-
assert data["likes"] == 42
335-
assert data["publish"] is True
335+
336+
statement = select(News).where(News.title == data["title"])
337+
result = await session.exec(statement)
338+
stored_news = result.first()
339+
assert stored_news is not None
340+
assert stored_news.content == data["content"]
341+
assert stored_news.category == data["category"]
342+
assert stored_news.user_email == data["user_email"]
343+
assert stored_news.source_url == data["source_url"]
344+
assert stored_news.tags == data["tags"]
345+
assert stored_news.social_media_url == data["social_media_url"]
346+
assert stored_news.publish
336347

337348

338349
@pytest.mark.asyncio

0 commit comments

Comments
 (0)