mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-07-15 15:05:48 +00:00
feat: add pagination to packages list
This commit is contained in:
@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from aiohttp_cors import CorsViewMixin # type: ignore[import]
|
||||
from aiohttp.web import Request, StreamResponse, View
|
||||
from aiohttp.web import HTTPBadRequest, Request, StreamResponse, View
|
||||
from collections.abc import Awaitable, Callable
|
||||
from typing import Any, TypeVar
|
||||
|
||||
@ -184,6 +184,30 @@ class BaseView(View, CorsViewMixin):
|
||||
|
||||
self._raise_allowed_methods()
|
||||
|
||||
def page(self) -> tuple[int, int]:
|
||||
"""
|
||||
parse limit and offset and return values
|
||||
|
||||
Returns:
|
||||
tuple[int, int]: limit and offset from request
|
||||
|
||||
Raises:
|
||||
HTTPBadRequest: if supplied parameters are invalid
|
||||
"""
|
||||
try:
|
||||
limit = int(self.request.query.getone("limit", default=-1))
|
||||
offset = int(self.request.query.getone("offset", default=0))
|
||||
except Exception as ex:
|
||||
raise HTTPBadRequest(reason=str(ex))
|
||||
|
||||
# some checks
|
||||
if limit < -1:
|
||||
raise HTTPBadRequest(reason=f"Limit must be -1 or non-negative, got {limit}")
|
||||
if offset < 0:
|
||||
raise HTTPBadRequest(reason=f"Offset must be non-negative, got {offset}")
|
||||
|
||||
return limit, offset
|
||||
|
||||
async def username(self) -> str | None:
|
||||
"""
|
||||
extract username from request if any
|
||||
|
@ -18,11 +18,15 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import aiohttp_apispec # type: ignore[import]
|
||||
import itertools
|
||||
|
||||
from collections.abc import Callable
|
||||
from aiohttp.web import HTTPNoContent, Response, json_response
|
||||
|
||||
from ahriman.models.build_status import BuildStatus
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.user_access import UserAccess
|
||||
from ahriman.web.schemas import AuthSchema, ErrorSchema, PackageStatusSchema
|
||||
from ahriman.web.schemas import AuthSchema, ErrorSchema, PackageStatusSchema, PaginationSchema
|
||||
from ahriman.web.views.base import BaseView
|
||||
|
||||
|
||||
@ -41,9 +45,10 @@ class PackagesView(BaseView):
|
||||
@aiohttp_apispec.docs(
|
||||
tags=["Packages"],
|
||||
summary="Get packages list",
|
||||
description="Retrieve all packages and their descriptors",
|
||||
description="Retrieve packages and their descriptors",
|
||||
responses={
|
||||
200: {"description": "Success response", "schema": PackageStatusSchema(many=True)},
|
||||
400: {"description": "Bad data is supplied", "schema": ErrorSchema},
|
||||
401: {"description": "Authorization required", "schema": ErrorSchema},
|
||||
403: {"description": "Access is forbidden", "schema": ErrorSchema},
|
||||
500: {"description": "Internal server error", "schema": ErrorSchema},
|
||||
@ -51,6 +56,7 @@ class PackagesView(BaseView):
|
||||
security=[{"token": [GET_PERMISSION]}],
|
||||
)
|
||||
@aiohttp_apispec.cookies_schema(AuthSchema)
|
||||
@aiohttp_apispec.querystring_schema(PaginationSchema)
|
||||
async def get(self) -> Response:
|
||||
"""
|
||||
get current packages status
|
||||
@ -58,12 +64,17 @@ class PackagesView(BaseView):
|
||||
Returns:
|
||||
Response: 200 with package description on success
|
||||
"""
|
||||
limit, offset = self.page()
|
||||
stop = offset + limit if limit >= 0 else None
|
||||
|
||||
comparator: Callable[[tuple[Package, BuildStatus]], str] = lambda pair: pair[0].base
|
||||
response = [
|
||||
{
|
||||
"package": package.view(),
|
||||
"status": status.view()
|
||||
} for package, status in self.service.packages
|
||||
} for package, status in itertools.islice(sorted(self.service.packages, key=comparator), offset, stop)
|
||||
]
|
||||
|
||||
return json_response(response)
|
||||
|
||||
@aiohttp_apispec.docs(
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import aiohttp_apispec # type: ignore[import]
|
||||
|
||||
from aiohttp.web import HTTPBadRequest, HTTPNotFound, Response, json_response
|
||||
from aiohttp.web import HTTPNotFound, Response, json_response
|
||||
|
||||
from ahriman.core.exceptions import UnknownPackageError
|
||||
from ahriman.models.user_access import UserAccess
|
||||
@ -63,15 +63,10 @@ class LogsView(BaseView):
|
||||
Response: 200 with package logs on success
|
||||
|
||||
Raises:
|
||||
HTTPBadRequest: if supplied parameters are invalid
|
||||
HTTPNotFound: if package base is unknown
|
||||
"""
|
||||
package_base = self.request.match_info["package"]
|
||||
try:
|
||||
limit = int(self.request.query.getone("limit", default=-1))
|
||||
offset = int(self.request.query.getone("offset", default=0))
|
||||
except Exception as ex:
|
||||
raise HTTPBadRequest(reason=str(ex))
|
||||
limit, offset = self.page()
|
||||
|
||||
try:
|
||||
_, status = self.service.package_get(package_base)
|
||||
|
Reference in New Issue
Block a user