Skip to content

Commit 98fc2ce

Browse files
authored
Merge pull request #53 from PythonFloripa/feature/#44
Feature#44
2 parents 1b74e51 + 6289db2 commit 98fc2ce

File tree

8 files changed

+90
-53
lines changed

8 files changed

+90
-53
lines changed

app/routers/healthcheck/routes.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
from fastapi import APIRouter, status
1+
from fastapi import APIRouter, Request, status
22
from pydantic import BaseModel
33

4+
from app.services.limiter import limiter
5+
46

57
class HealthCheckResponse(BaseModel):
68
status: str = "healthy"
@@ -17,7 +19,8 @@ def setup():
1719
summary="Health check endpoint",
1820
description="Returns the health status of the API",
1921
)
20-
async def healthcheck():
22+
@limiter.limit("60/minute")
23+
async def healthcheck(request: Request):
2124
"""
2225
Health check endpoint that returns the current status of the API.
2326
"""

app/routers/libraries/routes.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
from typing import Annotated, List
22

33
from fastapi import APIRouter, Header, HTTPException, Request, status
4+
from fastapi.params import Depends
45
from pydantic import BaseModel
56

7+
from app.routers.authentication import get_current_active_community
68
from app.schemas import Library as LibrarySchema
79
from app.schemas import LibraryNews
810
from app.schemas import LibraryRequest as LibraryRequestSchema
911
from app.schemas import Subscription as SubscriptionSchema
1012
from app.services.database.models import Library, Subscription
13+
from app.services.database.models.communities import Community as DBCommunity
1114
from app.services.database.models.libraries_request import LibraryRequest
1215
from app.services.database.orm.library import (
1316
get_libraries_by_language,
@@ -16,6 +19,7 @@
1619
)
1720
from app.services.database.orm.library_request import insert_library_request
1821
from app.services.database.orm.subscription import upsert_multiple_subscription
22+
from app.services.limiter import limiter
1923

2024

2125
class LibraryResponse(BaseModel):
@@ -36,7 +40,14 @@ def setup():
3640
summary="Get libraries by language",
3741
description="Get libraries by language",
3842
)
39-
async def get_by_language(request: Request, language: str):
43+
@limiter.limit("60/minute")
44+
async def get_by_language(
45+
request: Request,
46+
language: str,
47+
current_community: Annotated[
48+
DBCommunity, Depends(get_current_active_community)
49+
],
50+
):
4051
try:
4152
libraryList = await get_libraries_by_language(
4253
language=language, session=request.app.db_session_factory
@@ -71,9 +82,13 @@ async def get_by_language(request: Request, language: str):
7182
summary="Create a library",
7283
description="Create a new library to follow",
7384
)
85+
@limiter.limit("60/minute")
7486
async def create_library(
7587
request: Request,
7688
body: LibrarySchema,
89+
current_community: Annotated[
90+
DBCommunity, Depends(get_current_active_community)
91+
],
7792
):
7893
library = Library(
7994
library_name=body.library_name,
@@ -84,6 +99,7 @@ async def create_library(
8499
releases_doc_url=body.releases_doc_url,
85100
fixed_release_url=body.fixed_release_url,
86101
language=body.language,
102+
community_id=current_community.id,
87103
)
88104
try:
89105
await insert_library(library, request.app.db_session_factory)
@@ -104,10 +120,14 @@ async def create_library(
104120
"Subscribe to multiple libs and tags to receive libs updates"
105121
),
106122
)
123+
@limiter.limit("60/minute")
107124
async def subscribe_libraries(
108125
request: Request,
109126
body: SubscriptionSchema,
110127
user_email: Annotated[str, Header(alias="user-email")],
128+
current_community: Annotated[
129+
DBCommunity, Depends(get_current_active_community)
130+
],
111131
):
112132
try:
113133
library_ids = await get_library_ids_by_multiple_names(
@@ -121,7 +141,10 @@ async def subscribe_libraries(
121141

122142
subscriptions = [
123143
Subscription(
124-
user_email=user_email, tags=body.tags, library_id=id
144+
user_email=user_email,
145+
tags=body.tags,
146+
library_id=id,
147+
community_id=current_community.id,
125148
)
126149
for id in library_ids
127150
]
@@ -145,16 +168,21 @@ async def subscribe_libraries(
145168
summary="Request a library",
146169
description="Request a library to follow",
147170
)
171+
@limiter.limit("60/minute")
148172
async def request_library(
149173
request: Request,
150174
body: LibraryRequestSchema,
151175
user_email: Annotated[str, Header(alias="user-email")],
176+
current_community: Annotated[
177+
DBCommunity, Depends(get_current_active_community)
178+
],
152179
):
153180
try:
154181
library_request = LibraryRequest(
155182
user_email=user_email,
156183
library_name=body.library_name,
157184
library_home_page=body.library_home_page,
185+
community_id=current_community.id,
158186
)
159187

160188
await insert_library_request(

app/routers/news.py

Whitespace-only changes.

app/routers/news/routes.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from app.routers.authentication import get_current_active_community
1111
from app.schemas import News
1212
from app.services.database.models import Community as DBCommunity
13+
from app.services.limiter import limiter
1314

1415
SECRET_KEY = os.getenv("SECRET_KEY", "default_fallback_key")
1516
ALGORITHM = os.getenv("ALGORITHM", "HS256")
@@ -43,6 +44,7 @@ def setup():
4344
summary="News endpoint",
4445
description="Creates news and returns a confirmation message",
4546
)
47+
@limiter.limit("60/minute")
4648
async def post_news(
4749
request: Request,
4850
current_community: Annotated[
@@ -68,6 +70,7 @@ async def post_news(
6870
summary="Get News",
6971
description="Retrieves news filtered by user and query params",
7072
)
73+
@limiter.limit("60/minute")
7174
async def get_news(
7275
request: Request,
7376
current_community: Annotated[
@@ -97,6 +100,7 @@ async def get_news(
97100
summary="News like endpoint",
98101
description="Allows user to like a news item",
99102
)
103+
@limiter.limit("60/minute")
100104
async def post_like(
101105
request: Request,
102106
current_community: Annotated[
@@ -123,6 +127,7 @@ async def post_like(
123127
summary="News undo like endpoint",
124128
description="Allows user to undo a like to a news item",
125129
)
130+
@limiter.limit("60/minute")
126131
async def delete_like(
127132
request: Request,
128133
current_community: Annotated[

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ async def community(session: AsyncSession):
9696

9797

9898
@pytest_asyncio.fixture()
99-
async def token(async_client: AsyncGenerator[AsyncClient, None]) -> str:
99+
async def token(async_client: AsyncClient) -> str:
100100
form_data = {
101101
"grant_type": "password",
102102
"username": CommunityCredentials.username,

tests/test_libraries.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from datetime import date
2+
from typing import Mapping
23

34
import pytest
4-
import pytest_asyncio
55
from httpx import AsyncClient
66
from sqlmodel import select
77
from sqlmodel.ext.asyncio.session import AsyncSession
@@ -11,15 +11,6 @@
1111
from app.services.database.models import Community, Library
1212

1313

14-
@pytest_asyncio.fixture
15-
async def community(session: AsyncSession):
16-
community = Community(username="admin", email="[email protected]", password="123")
17-
session.add(community)
18-
await session.commit()
19-
await session.refresh(community)
20-
return community
21-
22-
2314
@pytest.mark.asyncio
2415
async def test_insert_libraries(session: AsyncSession, community: Community):
2516
library = Library(
@@ -60,7 +51,9 @@ async def test_insert_libraries(session: AsyncSession, community: Community):
6051

6152
@pytest.mark.asyncio
6253
async def test_post_libraries_endpoint(
63-
async_client: AsyncClient, session: AsyncSession
54+
session: AsyncSession,
55+
async_client: AsyncClient,
56+
valid_auth_headers: Mapping[str, str],
6457
):
6558
body = {
6659
"library_name": "FastAPI",
@@ -79,7 +72,7 @@ async def test_post_libraries_endpoint(
7972
response = await async_client.post(
8073
"/api/libraries",
8174
json=body,
82-
headers={"Content-Type": "application/json"},
75+
headers=valid_auth_headers,
8376
)
8477

8578
assert response.status_code == 200
@@ -104,7 +97,10 @@ async def test_post_libraries_endpoint(
10497

10598

10699
@pytest.mark.asyncio
107-
async def test_get_libraries_by_language(async_client: AsyncClient):
100+
async def test_get_libraries_by_language(
101+
async_client: AsyncClient,
102+
valid_auth_headers: Mapping[str, str],
103+
):
108104
body = {
109105
"library_name": "FastAPI",
110106
"news": [
@@ -122,7 +118,7 @@ async def test_get_libraries_by_language(async_client: AsyncClient):
122118
responsePOST = await async_client.post(
123119
"/api/libraries",
124120
json=body,
125-
headers={"Content-Type": "application/json"},
121+
headers=valid_auth_headers,
126122
)
127123

128124
assert responsePOST.status_code == 200
@@ -131,6 +127,7 @@ async def test_get_libraries_by_language(async_client: AsyncClient):
131127
response = await async_client.get(
132128
"/api/libraries",
133129
params={"language": "Python"},
130+
headers=valid_auth_headers,
134131
)
135132

136133
assert response.status_code == 200
@@ -153,7 +150,10 @@ async def test_get_libraries_by_language(async_client: AsyncClient):
153150

154151

155152
@pytest.mark.asyncio
156-
async def test_get_libraries_by_inexistent_language(async_client: AsyncClient):
153+
async def test_get_libraries_by_inexistent_language(
154+
async_client: AsyncClient,
155+
valid_auth_headers: Mapping[str, str],
156+
):
157157
body = {
158158
"library_name": "FastAPI",
159159
"news": [
@@ -171,7 +171,7 @@ async def test_get_libraries_by_inexistent_language(async_client: AsyncClient):
171171
responsePOST = await async_client.post(
172172
"/api/libraries",
173173
json=body,
174-
headers={"Content-Type": "application/json"},
174+
headers=valid_auth_headers,
175175
)
176176

177177
assert responsePOST.status_code == 200
@@ -180,6 +180,7 @@ async def test_get_libraries_by_inexistent_language(async_client: AsyncClient):
180180
response = await async_client.get(
181181
"/api/libraries",
182182
params={"language": "NodeJS"},
183+
headers=valid_auth_headers,
183184
)
184185

185186
assert response.status_code == 200

tests/test_libraries_request.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
1+
from typing import Mapping
2+
13
import pytest
2-
import pytest_asyncio
34
from httpx import AsyncClient
45
from sqlmodel import select
56
from sqlmodel.ext.asyncio.session import AsyncSession
67

78
from app.services.database.models import Community, LibraryRequest
89

910

10-
@pytest_asyncio.fixture
11-
async def community(session: AsyncSession):
12-
community = Community(username="admin", email="[email protected]", password="123")
13-
session.add(community)
14-
await session.commit()
15-
await session.refresh(community)
16-
return community
17-
18-
1911
@pytest.mark.asyncio
2012
async def test_insert_libraries(session: AsyncSession, community: Community):
2113
library = LibraryRequest(
@@ -41,14 +33,17 @@ async def test_insert_libraries(session: AsyncSession, community: Community):
4133

4234
@pytest.mark.asyncio
4335
async def test_post_libraries_endpoint(
44-
async_client: AsyncClient, session: AsyncSession
36+
async_client: AsyncClient,
37+
session: AsyncSession,
38+
community: Community,
39+
valid_auth_headers: Mapping[str, str],
4540
):
4641
body = {"library_name": "FastAPI", "library_home_page": "http://teste.com/"}
4742

4843
response = await async_client.post(
4944
"/api/libraries/request",
5045
json=body,
51-
headers={"Content-Type": "application/json", "user-email": "[email protected]"},
46+
headers=valid_auth_headers,
5247
)
5348

5449
assert response.status_code == 200
@@ -61,5 +56,5 @@ async def test_post_libraries_endpoint(
6156
created_request = result.first()
6257

6358
assert created_request is not None
64-
assert created_request.user_email == "[email protected]"
59+
assert created_request.user_email == community.email
6560
assert created_request.library_home_page == "http://teste.com/"

0 commit comments

Comments
 (0)