Source code for cata_log_hub.api.v1.pages

# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Cata-Log - the central hub for digital flyers
# Copyright (C) 2026 David Aderbauer & The Cata-Log Contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.


from typing import Annotated

from fastapi import APIRouter, HTTPException, Path, Query, status
from fastapi.responses import FileResponse
from fastapi_pagination.ext.sqlalchemy import paginate
from sqlalchemy.orm import Session

from cata_log_hub import database
from cata_log_hub.api import common

from . import models
from .pagination import PaginationPage

router = APIRouter(prefix="/pages", tags=["pages"])


[docs] @router.get( "", response_model=PaginationPage[models.Page], operation_id="list-pages-v1", ) def list_pages( order: Annotated[ list[models.PageOrderChoices], Query(description="Fields to order by") ] = [ # noqa: B006 # no alternative in fastapi, not altered after declaration models.PageOrderChoices.DESC_CATALOG_ID, models.PageOrderChoices.NUMBER, ], db_session: Session = database.depends_db_session, ) -> PaginationPage[database.Page]: """List all pages.""" return paginate( db_session.query(database.Page).order_by( *[order_param.sql(database.Page) for order_param in order] ) )
[docs] @router.get( "/{page_id}", response_model=models.Page, responses={ status.HTTP_404_NOT_FOUND: { "model": common.HTTPStatusError, "description": "Object doesn't exist", }, }, operation_id="get-page-v1", ) def get_page( page_id: Annotated[int, Path(description="ID of the page")], db_session: Session = database.depends_db_session, ) -> database.Page: """Get a single page.""" page = db_session.get(database.Page, page_id) if not page: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Page not found" ) return page
[docs] @router.get( "/{page_id}/download", responses={ status.HTTP_404_NOT_FOUND: { "model": common.HTTPStatusError, "description": "Object doesn't exist", }, }, operation_id="download-page-v1", ) def download_page( page_id: Annotated[int, Path(title="test", description="ID of the page")], filename: Annotated[str | None, Query(description="Name for the file")] = None, db_session: Session = database.depends_db_session, ) -> FileResponse: """Download a single page.""" page_path = ( db_session.query(database.PageFile.path) .join(database.Page.file) .filter(database.Page.id == page_id) .scalar() ) if not page_path: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Page not found" ) filename = filename or page_path.name return FileResponse( path=page_path, filename=filename, content_disposition_type="attachment", )
[docs] @router.get( "/{page_id}/embed", responses={ status.HTTP_404_NOT_FOUND: { "model": common.HTTPStatusError, "description": "Object doesn't exist", }, }, operation_id="embed-page-v1", ) def embed_page( page_id: Annotated[int, Path(description="ID of the page")], filename: Annotated[str | None, Query(description="Name for the file")] = None, db_session: Session = database.depends_db_session, ) -> FileResponse: """Embed a single page.""" page_path = ( db_session.query(database.PageFile.path) .join(database.Page.file) .filter(database.Page.id == page_id) .scalar() ) if not page_path: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Page not found" ) filename = filename or page_path.name return FileResponse( path=page_path, filename=filename, content_disposition_type="inline", )