Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -519,9 +519,9 @@ def build_jobs_search_request(*, page: int = 1, per_page: int = 100, **kwargs: A

# Construct parameters
if page is not None:
_params["page"] = _SERIALIZER.query("page", page, "int")
_params["page"] = _SERIALIZER.query("page", page, "int", minimum=1)
if per_page is not None:
_params["per_page"] = _SERIALIZER.query("per_page", per_page, "int")
_params["per_page"] = _SERIALIZER.query("per_page", per_page, "int", maximum=10000, minimum=1)

# Construct headers
if content_type is not None:
Expand Down
11 changes: 4 additions & 7 deletions diracx-routers/src/diracx/routers/jobs/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
from http import HTTPStatus
from typing import Annotated, Any

from fastapi import Body, Depends, Response
from fastapi import Body, Depends, Query, Response

from diracx.core.models.search import (
SearchParams,
SummaryParams,
)
from diracx.core.properties import JOB_ADMINISTRATOR
from diracx.logic.jobs.query import MAX_PER_PAGE
from diracx.logic.jobs.query import search as search_bl
from diracx.logic.jobs.query import summary as summary_bl

Expand All @@ -25,10 +26,6 @@

router = DiracxRouter()


MAX_PER_PAGE = 10000


EXAMPLE_SEARCHES = {
"Show all": {
"summary": "Show all",
Expand Down Expand Up @@ -132,8 +129,8 @@ async def search(
user_info: Annotated[AuthorizedUserInfo, Depends(verify_dirac_access_token)],
check_permissions: CheckWMSPolicyCallable,
response: Response,
page: int = 1,
per_page: int = 100,
page: Annotated[int, Query(ge=1)] = 1,
per_page: Annotated[int, Query(ge=1, le=MAX_PER_PAGE)] = 100,
body: Annotated[
SearchParams | None, Body(openapi_examples=EXAMPLE_SEARCHES)
] = None,
Expand Down
14 changes: 10 additions & 4 deletions diracx-routers/tests/jobs/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,19 +525,25 @@ def test_search_pagination(normal_user_client):

# Set the per_page parameter to 0
r = normal_user_client.post("/api/jobs/search", params={"page": 1, "per_page": 0})
assert r.status_code == 400, r.json()
assert r.status_code == 422, r.json()

# Set the per_page parameter to a negative number
r = normal_user_client.post("/api/jobs/search", params={"page": 1, "per_page": -1})
assert r.status_code == 400, r.json()
assert r.status_code == 422, r.json()

# Set the page parameter to 0
r = normal_user_client.post("/api/jobs/search", params={"page": 0, "per_page": 10})
assert r.status_code == 400, r.json()
assert r.status_code == 422, r.json()

# Set the page parameter to a negative number
r = normal_user_client.post("/api/jobs/search", params={"page": -1, "per_page": 10})
assert r.status_code == 400, r.json()
assert r.status_code == 422, r.json()

# Too many jobs per page (max = 10000)
r = normal_user_client.post(
"/api/jobs/search", params={"page": 1, "per_page": 20000}
)
assert r.status_code == 422, r.json()


def test_user_cannot_submit_parametric_jdl_greater_than_max_parametric_jobs(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,9 +519,9 @@ def build_jobs_search_request(*, page: int = 1, per_page: int = 100, **kwargs: A

# Construct parameters
if page is not None:
_params["page"] = _SERIALIZER.query("page", page, "int")
_params["page"] = _SERIALIZER.query("page", page, "int", minimum=1)
if per_page is not None:
_params["per_page"] = _SERIALIZER.query("per_page", per_page, "int")
_params["per_page"] = _SERIALIZER.query("per_page", per_page, "int", maximum=10000, minimum=1)

# Construct headers
if content_type is not None:
Expand Down
Loading