diff --git a/src/aleph/schemas/addresses_query_params.py b/src/aleph/schemas/addresses_query_params.py index c3f23fd0a..5a5701a50 100644 --- a/src/aleph/schemas/addresses_query_params.py +++ b/src/aleph/schemas/addresses_query_params.py @@ -45,8 +45,9 @@ class AddressesQueryParams(BaseModel): # Pagination pagination: int = Field( default=DEFAULT_MESSAGES_PER_PAGE, - ge=0, - description="Maximum number of address to return. Specifying 0 removes this limit.", + ge=1, + le=1000, + description="Maximum number of addresses to return.", ) page: int = Field( default=DEFAULT_PAGE, ge=1, description="Offset in pages. Starts at 1." diff --git a/src/aleph/schemas/api/accounts.py b/src/aleph/schemas/api/accounts.py index 6340b9d26..e8a1afca9 100644 --- a/src/aleph/schemas/api/accounts.py +++ b/src/aleph/schemas/api/accounts.py @@ -32,8 +32,9 @@ class GetAccountBalanceResponse(BaseModel): class GetAccountFilesQueryParams(BaseModel): pagination: int = Field( default=100, - ge=0, - description="Maximum number of files to return. Specifying 0 removes this limit.", + ge=1, + le=1000, + description="Maximum number of files to return.", ) page: int = Field( default=DEFAULT_PAGE, ge=1, description="Offset in pages. Starts at 1." @@ -51,8 +52,9 @@ class GetBalancesChainsQueryParams(BaseModel): ) pagination: int = Field( default=100, - ge=0, - description="Maximum number of files to return. Specifying 0 removes this limit.", + ge=1, + le=1000, + description="Maximum number of balances to return.", ) page: int = Field( default=DEFAULT_PAGE, ge=1, description="Offset in pages. Starts at 1." @@ -77,8 +79,9 @@ class AddressBalanceResponse(BaseModel): class GetCreditBalancesQueryParams(BaseModel): pagination: int = Field( default=100, - ge=0, - description="Maximum number of credit balances to return. Specifying 0 removes this limit.", + ge=1, + le=1000, + description="Maximum number of credit balances to return.", ) page: int = Field( default=DEFAULT_PAGE, ge=1, description="Offset in pages. Starts at 1." @@ -116,9 +119,10 @@ class GetAccountFilesResponse(BaseModel): class GetAccountCreditHistoryQueryParams(BaseModel): pagination: int = Field( - default=0, - ge=0, - description="Maximum number of credit history entries to return. Specifying 0 returns all entries.", + default=100, + ge=1, + le=1000, + description="Maximum number of credit history entries to return.", ) page: int = Field( default=DEFAULT_PAGE, ge=1, description="Offset in pages. Starts at 1." diff --git a/src/aleph/schemas/messages_query_params.py b/src/aleph/schemas/messages_query_params.py index 19b7698e7..b8f046624 100644 --- a/src/aleph/schemas/messages_query_params.py +++ b/src/aleph/schemas/messages_query_params.py @@ -157,8 +157,9 @@ def split_str(cls, v): class MessageQueryParams(BaseMessageQueryParams): pagination: int = Field( default=DEFAULT_MESSAGES_PER_PAGE, - ge=0, - description="Maximum number of messages to return. Specifying 0 removes this limit.", + ge=1, + le=1000, + description="Maximum number of messages to return.", ) page: int = Field( default=DEFAULT_PAGE, ge=1, description="Offset in pages. Starts at 1." @@ -198,8 +199,9 @@ class MessageHashesQueryParams(BaseModel): ) pagination: int = Field( default=DEFAULT_MESSAGES_PER_PAGE, - ge=0, - description="Maximum number of messages to return. Specifying 0 removes this limit.", + ge=1, + le=1000, + description="Maximum number of messages to return.", ) start_date: float = Field( default=0, diff --git a/tests/api/test_address_stats.py b/tests/api/test_address_stats.py index 7a4bdda6f..4e45309a8 100644 --- a/tests/api/test_address_stats.py +++ b/tests/api/test_address_stats.py @@ -253,7 +253,6 @@ async def test_address_stats_endpoint_basic( [ (2, 1, 2), (1, 1, 2), - (0, 1, 2), # all items in one page ], ) async def test_address_stats_pagination( @@ -280,20 +279,14 @@ async def test_address_stats_pagination( # Basic pagination assertions assert data_page1["pagination_page"] == page1 - if per_page > 0: - assert data_page1["pagination_per_page"] == per_page - assert data_page2["pagination_page"] == page2 + assert data_page1["pagination_per_page"] == per_page + assert data_page2["pagination_page"] == page2 - # Should not return the same addresses across pages - page1_addresses = set(data_page1["data"].keys()) - page2_addresses = set(data_page2["data"].keys()) + # Should not return the same addresses across pages + page1_addresses = set(data_page1["data"].keys()) + page2_addresses = set(data_page2["data"].keys()) - assert len(page1_addresses.intersection(page2_addresses)) == 0 - - else: - # per_page == 0 then everything in one page - assert data_page1["pagination_per_page"] == 0 - assert len(data_page2["data"]) == 5 + assert len(page1_addresses.intersection(page2_addresses)) == 0 @pytest.mark.asyncio @@ -423,25 +416,12 @@ async def test_address_stats_all_message_types( @pytest.mark.asyncio -async def test_address_stats_request_all_items( +async def test_address_stats_pagination_zero_rejected( ccn_api_client, fixture_address_stats_messages ): - """Test requesting all items without pagination.""" - # Get count of all addresses - response_normal = await ccn_api_client.get(ADDRESSES_STATS_URI_V1) - assert response_normal.status == 200 - data_normal = await response_normal.json() - total_count = data_normal["pagination_total"] - - # Request all items with pagination=0 - response_all = await ccn_api_client.get(ADDRESSES_STATS_URI_V1 + "?pagination=0") - assert response_all.status == 200 - data_all = await response_all.json() - - # Should return all items - assert len(data_all["data"]) == total_count - assert data_all["pagination_per_page"] == 0 - assert data_all["pagination_total"] == total_count + """Test that pagination=0 is rejected.""" + response = await ccn_api_client.get(ADDRESSES_STATS_URI_V1 + "?pagination=0") + assert response.status == 422 @pytest.mark.asyncio diff --git a/tests/api/test_list_messages.py b/tests/api/test_list_messages.py index 916888d54..18dcf13b6 100644 --- a/tests/api/test_list_messages.py +++ b/tests/api/test_list_messages.py @@ -426,9 +426,9 @@ async def test_pagination(fixture_messages, ccn_api_client): ) assert_messages_equal(messages=messages, expected_messages=fixture_messages) - # All the messages + # All the messages (use a large pagination value) messages = await fetch_messages_with_pagination_expect_success( - ccn_api_client, page=1, pagination=0 + ccn_api_client, page=1, pagination=1000 ) assert_messages_equal(messages=messages, expected_messages=fixture_messages) diff --git a/tests/db/test_address_stats.py b/tests/db/test_address_stats.py index 14dce4762..ca709c36d 100644 --- a/tests/db/test_address_stats.py +++ b/tests/db/test_address_stats.py @@ -214,8 +214,8 @@ async def test_fetch_stats_address_query(session_factory: DbSessionFactory): @pytest.mark.asyncio -async def test_zero_per_page_returns_all(session_factory: DbSessionFactory): - """Test that setting pagination=0 returns all results without pagination.""" +async def test_large_pagination_returns_all(session_factory: DbSessionFactory): + """Test that a large pagination value returns all results.""" with session_factory() as session: test_messages = create_test_messages() session.add_all(test_messages) @@ -226,13 +226,13 @@ async def test_zero_per_page_returns_all(session_factory: DbSessionFactory): # Count total addresses total_count = count_address_stats(session) - # Get all results with pagination=0 + # Get all results with a large pagination value all_stats = get_message_stats_by_address( session=session, sort_by=SortByMessageType.TOTAL, sort_order=SortOrder.DESCENDING, page=1, - pagination=0, # This should return all results + pagination=1000, ) # Should have all addresses