diff --git a/kontor-api/src/apis/base.py b/kontor-api/src/apis/base.py index e401df5..10dd55e 100644 --- a/kontor-api/src/apis/base.py +++ b/kontor-api/src/apis/base.py @@ -2,31 +2,31 @@ add router for different parts (like comics, tysc, media) """ -from fastapi import APIRouter +from fastapi import APIRouter, Depends +from src.apis.version1.admin import token +from src.apis.version1.comics import artist, comic, issue +from src.apis.version1.media import mediaactor, mediaactorfile, mediafile +from src.apis.version1.tysc import card, cardset, fieldposition, player, rooster, sport, team, vendor +from src.core.security import get_current_user_from_token -from src.apis.version1 import ( - comic, - mediaactor, - mediafile, - mediaactorfile, - sport, - player, - team, - fieldposition, - vendor, - admin, - user, -) +from src.apis.version1.user import profile +from src.apis.version1.bookshelf import article api_router = APIRouter(prefix="/api") -api_router.include_router(comic.router, prefix="/comics", tags=["comics"]) -api_router.include_router(mediafile.router, prefix="/media", tags=["media"]) -api_router.include_router(mediaactor.router, prefix="/media", tags=["media"]) -api_router.include_router(mediaactorfile.router, prefix="/media", tags=["media"]) -api_router.include_router(sport.router, prefix="/tysc", tags=["tysc"]) -api_router.include_router(player.router, prefix="/tysc", tags=["tysc"]) -api_router.include_router(team.router, prefix="/tysc", tags=["tysc"]) -api_router.include_router(fieldposition.router, prefix="/tysc", tags=["tysc"]) -api_router.include_router(vendor.router, prefix="/tysc", tags=["tysc"]) -api_router.include_router(admin.router, prefix="/login", tags=["login"]) -api_router.include_router(user.router, prefix="/user", tags=["user"]) +api_router.include_router(comic.router, prefix="/comics", tags=["comics"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(artist.router, prefix="/comics", tags=["comics"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(issue.router, prefix="/comics", tags=["comics"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(mediafile.router, prefix="/media", tags=["media"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(mediaactor.router, prefix="/media", tags=["media"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(mediaactorfile.router, prefix="/media", tags=["media"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(sport.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(player.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(team.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(fieldposition.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(rooster.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(vendor.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(cardset.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(card.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(article.router, prefix="/bookshelf", tags=["bookshelf"], dependencies=[Depends(get_current_user_from_token)]) +api_router.include_router(token.router, prefix="/login", tags=["login"]) +api_router.include_router(profile.router, prefix="/user", tags=["user"], dependencies=[Depends(get_current_user_from_token)]) diff --git a/kontor-api/src/apis/version1/login.py b/kontor-api/src/apis/version1/admin/login.py similarity index 96% rename from kontor-api/src/apis/version1/login.py rename to kontor-api/src/apis/version1/admin/login.py index 9c35590..d06095e 100644 --- a/kontor-api/src/apis/version1/login.py +++ b/kontor-api/src/apis/version1/admin/login.py @@ -26,7 +26,7 @@ class LoginRequest(BaseModel): ) def login(request: LoginRequest) -> Token: logger.info(f"login with {request.email}") - user = authenticate_user_by_email(request.email, request.password) + user = authenticate_user_by_email(str(request.email), str(request.password)) scopes = ["admin", "read"] if not user: raise HTTPException( diff --git a/kontor-api/src/apis/version1/admin.py b/kontor-api/src/apis/version1/admin/token.py similarity index 100% rename from kontor-api/src/apis/version1/admin.py rename to kontor-api/src/apis/version1/admin/token.py diff --git a/kontor-api/src/apis/version1/bookshelf/article.py b/kontor-api/src/apis/version1/bookshelf/article.py new file mode 100644 index 0000000..b985b36 --- /dev/null +++ b/kontor-api/src/apis/version1/bookshelf/article.py @@ -0,0 +1,20 @@ +from typing import List + +from fastapi import APIRouter + +from src.db.models.bookshelf import Article +from src.db.session import SessionDep +from src.schema.bookshelf.article import ArticleResponse, to_response + + +router = APIRouter() + + +@router.get("/articles", response_model=List[ArticleResponse]) +def get_all_artists(db: SessionDep) -> List[ArticleResponse]: + results: List[ArticleResponse] = [] + articles = db.query(Article).all() + for article in articles: + response = to_response(article) + results.append(response) + return results diff --git a/kontor-api/src/apis/version1/comics/artist.py b/kontor-api/src/apis/version1/comics/artist.py new file mode 100644 index 0000000..168f3e9 --- /dev/null +++ b/kontor-api/src/apis/version1/comics/artist.py @@ -0,0 +1,43 @@ +from typing import List + +from fastapi import APIRouter, HTTPException, status + +from src.db.models.comic import Artist +from src.db.repository.comics.artist import get_artist_details +from src.db.session import SessionDep +from src.schema.comics.artist import ArtistCreation, ArtistResponse +from src.schema.comics.artist_details import ArtistDetailResponse + + +router = APIRouter() + + +@router.get("/artists", response_model=List[ArtistResponse]) +def get_all_artists(db: SessionDep) -> List[ArtistResponse]: + results: List[ArtistResponse] = [] + artists = db.query(Artist).all() + for artist in artists: + results.append(ArtistResponse(id=artist.id, name=str(artist.name))) + return results + + +@router.get("/artists/{artist_id}", response_model=ArtistDetailResponse) +def get_artist(artist_id: str, db: SessionDep) -> ArtistDetailResponse: + artist = db.get(Artist, artist_id) + if artist is None: + raise HTTPException(status_code=404, detail="Artist could not be found") + response: ArtistDetailResponse = get_artist_details(artist) + return response + + +@router.post("/artists", status_code=status.HTTP_201_CREATED) +def add_artist(db: SessionDep, artist_creation: ArtistCreation) -> ArtistResponse: + artist: Artist = Artist() + setattr(artist, "name", artist_creation.name) + try: + db.add(artist) + db.commit() + except: + raise HTTPException(status_code=409, detail="Artist already added") + response = ArtistResponse(id=artist.id, name=str(artist.name)) + return response diff --git a/kontor-api/src/apis/version1/comic.py b/kontor-api/src/apis/version1/comics/comic.py similarity index 51% rename from kontor-api/src/apis/version1/comic.py rename to kontor-api/src/apis/version1/comics/comic.py index a663434..1162bb9 100644 --- a/kontor-api/src/apis/version1/comic.py +++ b/kontor-api/src/apis/version1/comics/comic.py @@ -1,9 +1,9 @@ from typing import List -from fastapi import APIRouter, HTTPException, status +from fastapi import APIRouter, HTTPException from src.core.log_conf import logger -from src.db.models.comic import Artist, Comic, Issue, Publisher +from src.db.models.comic import Comic, Publisher from src.db.repository.comics.artist import get_artist_details from src.db.repository.comics.comic import ( get_comic_details, @@ -13,11 +13,8 @@ from src.db.repository.comics.comic import ( ) from src.db.repository.comics.publisher import get_publisher_details from src.db.session import SessionDep -from src.schema.comics.artist import ArtistCreation, ArtistResponse -from src.schema.comics.artist_details import ArtistDetailResponse from src.schema.comics.comic import ComicResponse from src.schema.comics.comic_details import ComicDetailsResponse -from src.schema.comics.issue_details import IssueDetailsResponse from src.schema.comics.publisher import PublisherResponse from src.schema.comics.publisher_details import PublisherDetailsResponse @@ -25,7 +22,7 @@ router = APIRouter() @router.get("/comics") -def get_all_comics(db: SessionDep) -> List[ComicResponse]: # type: ignore +def get_all_comics(db: SessionDep) -> List[ComicResponse]: results: List[ComicResponse] = [] comics = list_comics(db) for comic in comics: @@ -35,7 +32,7 @@ def get_all_comics(db: SessionDep) -> List[ComicResponse]: # type: ignore @router.get("/comics/{comic_id}", response_model=ComicDetailsResponse) -def get_comic(comic_id: str, db: SessionDep) -> ComicDetailsResponse: # type: ignore +def get_comic(comic_id: str, db: SessionDep) -> ComicDetailsResponse: comic = db.get(Comic, comic_id) if comic is None: raise HTTPException(status_code=404, detail="Comic could not be found") @@ -45,39 +42,10 @@ def get_comic(comic_id: str, db: SessionDep) -> ComicDetailsResponse: # type: ig return response -@router.get("/artists", response_model=List[ArtistResponse]) -def get_all_artists(db: SessionDep) -> List[ArtistResponse]: # type: ignore - results: List[ArtistResponse] = [] - artists = db.query(Artist).all() - for artist in artists: - results.append(ArtistResponse(id=artist.id, name=str(artist.name))) # type: ignore - return results - - -@router.get("/artists/{artist_id}", response_model=ArtistDetailResponse) -def get_artist(artist_id: str, db: SessionDep) -> ArtistDetailResponse: # type: ignore - artist = db.get(Artist, artist_id) - if artist is None: - raise HTTPException(status_code=404, detail="Artist could not be found") - response: ArtistDetailResponse = get_artist_details(artist) - return response - - -@router.post("/artists", status_code=status.HTTP_201_CREATED) -def add_artist(db: SessionDep, artist_creation: ArtistCreation) -> ArtistResponse: # type: ignore - artist: Artist = Artist() - setattr(artist, "name", artist_creation.name) - try: - db.add(artist) - db.commit() - except: - raise HTTPException(status_code=409, detail="Artist already added") - response = ArtistResponse(id=artist.id, name=str(artist.name)) - return response @router.get("/publishers", response_model=List[PublisherResponse]) -def get_all_publishers(db: SessionDep) -> List[PublisherResponse]: # type: ignore +def get_all_publishers(db: SessionDep) -> List[PublisherResponse]: results: List[PublisherResponse] = [] publishers = db.query(Publisher).all() for publisher in publishers: @@ -86,18 +54,10 @@ def get_all_publishers(db: SessionDep) -> List[PublisherResponse]: # type: ignor @router.get("/publishers/{publisher_id}", response_model=PublisherDetailsResponse) -def get_publisher(publisher_id: str, db: SessionDep) -> PublisherDetailsResponse: # type: ignore +def get_publisher(publisher_id: str, db: SessionDep) -> PublisherDetailsResponse: publisher = db.get(Publisher, publisher_id) if publisher is None: raise HTTPException(status_code=404, detail="Publisher could not be found") response: PublisherDetailsResponse = get_publisher_details(publisher) return response - -@router.get("/issues", response_model=List[IssueDetailsResponse]) -def get_issues(db: SessionDep) -> List[IssueDetailsResponse]: # type: ignore - results: List[IssueDetailsResponse] = [] - issues = db.query(Issue).all() - for issue in issues: - results.append(get_issue_details(issue)) - return results diff --git a/kontor-api/src/apis/version1/comics/issue.py b/kontor-api/src/apis/version1/comics/issue.py new file mode 100644 index 0000000..6b180f6 --- /dev/null +++ b/kontor-api/src/apis/version1/comics/issue.py @@ -0,0 +1,19 @@ +from typing import List + +from fastapi import APIRouter + +from src.db.models.comic import Issue +from src.db.repository.comics.comic import get_issue_details +from src.db.session import SessionDep +from src.schema.comics.issue_details import IssueDetailsResponse + + +router = APIRouter() + +@router.get("/issues", response_model=List[IssueDetailsResponse]) +def get_issues(db: SessionDep) -> List[IssueDetailsResponse]: + results: List[IssueDetailsResponse] = [] + issues = db.query(Issue).all() + for issue in issues: + results.append(get_issue_details(issue)) + return results diff --git a/kontor-api/src/apis/version1/mediaactor.py b/kontor-api/src/apis/version1/media/mediaactor.py similarity index 100% rename from kontor-api/src/apis/version1/mediaactor.py rename to kontor-api/src/apis/version1/media/mediaactor.py diff --git a/kontor-api/src/apis/version1/mediaactorfile.py b/kontor-api/src/apis/version1/media/mediaactorfile.py similarity index 100% rename from kontor-api/src/apis/version1/mediaactorfile.py rename to kontor-api/src/apis/version1/media/mediaactorfile.py diff --git a/kontor-api/src/apis/version1/mediafile.py b/kontor-api/src/apis/version1/media/mediafile.py similarity index 92% rename from kontor-api/src/apis/version1/mediafile.py rename to kontor-api/src/apis/version1/media/mediafile.py index a669d7b..9b3f313 100644 --- a/kontor-api/src/apis/version1/mediafile.py +++ b/kontor-api/src/apis/version1/media/mediafile.py @@ -1,9 +1,8 @@ from typing import List -from fastapi import APIRouter, status, HTTPException, Depends -from sqlalchemy import select, Sequence +from fastapi import APIRouter, status, HTTPException +from sqlalchemy import select from src.core.log_conf import logger -from src.core.security import UserDep, get_current_user_from_token from src.db.repository.media import ( create_new_mediaactorfile, create_new_mediafile, @@ -34,11 +33,7 @@ def update_titles(db: SessionDep) -> list[MediaFileResponse]: return results -@router.get( - "/files", - response_model=list[MediaFileResponse], - dependencies=[Depends(get_current_user_from_token)], -) +@router.get("/files", response_model=list[MediaFileResponse]) def get_all_files( db: SessionDep, review: bool = False, download: bool = False ) -> List[MediaFileResponse]: @@ -59,11 +54,7 @@ def get_all_files( return results -@router.get( - "/files/{file_id}", - response_model=MediaFileResponse, - dependencies=[Depends(get_current_user_from_token)], -) +@router.get("/files/{file_id}", response_model=MediaFileResponse) def get_file(file_id: str, db: SessionDep) -> MediaFileResponse: """ Get MediaFile with given id or return HTTPException. diff --git a/kontor-api/src/apis/version1/tysc/card.py b/kontor-api/src/apis/version1/tysc/card.py new file mode 100644 index 0000000..8c44b1c --- /dev/null +++ b/kontor-api/src/apis/version1/tysc/card.py @@ -0,0 +1,19 @@ +from typing import List + +from fastapi import APIRouter + +from src.db.models.tysc import Card +from src.db.session import SessionDep +from src.schema.tysc.card import CardResponse, to_response + + +router = APIRouter() + +@router.get("/cards") +def get_all_players(db: SessionDep) -> List[CardResponse]: + results: List[CardResponse] = [] + cards = db.query(Card).all() + for card in cards: + response = to_response(card) + results.append(response) + return results diff --git a/kontor-api/src/apis/version1/tysc/cardset.py b/kontor-api/src/apis/version1/tysc/cardset.py new file mode 100644 index 0000000..fe3d952 --- /dev/null +++ b/kontor-api/src/apis/version1/tysc/cardset.py @@ -0,0 +1,19 @@ +from typing import List + +from fastapi import APIRouter + +from src.db.models.tysc import CardSet +from src.db.session import SessionDep +from src.schema.tysc.cardset import CardSetResponse, to_response + + +router = APIRouter() + +@router.get("/cardsets") +def get_all_players(db: SessionDep) -> List[CardSetResponse]: + results: List[CardSetResponse] = [] + cardsets = db.query(CardSet).all() + for cardset in cardsets: + response = to_response(cardset) + results.append(response) + return results diff --git a/kontor-api/src/apis/version1/fieldposition.py b/kontor-api/src/apis/version1/tysc/fieldposition.py similarity index 100% rename from kontor-api/src/apis/version1/fieldposition.py rename to kontor-api/src/apis/version1/tysc/fieldposition.py diff --git a/kontor-api/src/apis/version1/player.py b/kontor-api/src/apis/version1/tysc/player.py similarity index 100% rename from kontor-api/src/apis/version1/player.py rename to kontor-api/src/apis/version1/tysc/player.py diff --git a/kontor-api/src/apis/version1/tysc/rooster.py b/kontor-api/src/apis/version1/tysc/rooster.py new file mode 100644 index 0000000..f817195 --- /dev/null +++ b/kontor-api/src/apis/version1/tysc/rooster.py @@ -0,0 +1,19 @@ +from typing import List + +from fastapi import APIRouter + +from src.db.models.tysc import Rooster +from src.db.session import SessionDep +from src.schema.tysc.rooster import RoosterResponse, to_response + + +router = APIRouter() + +@router.get("/roosters") +def get_all_sports(db: SessionDep) -> List[RoosterResponse]: + results: list[RoosterResponse] = [] + roosters = db.query(Rooster).all() + for rooster in roosters: + response = to_response(rooster) + results.append(response) + return results diff --git a/kontor-api/src/apis/version1/sport.py b/kontor-api/src/apis/version1/tysc/sport.py similarity index 100% rename from kontor-api/src/apis/version1/sport.py rename to kontor-api/src/apis/version1/tysc/sport.py diff --git a/kontor-api/src/apis/version1/team.py b/kontor-api/src/apis/version1/tysc/team.py similarity index 100% rename from kontor-api/src/apis/version1/team.py rename to kontor-api/src/apis/version1/tysc/team.py diff --git a/kontor-api/src/apis/version1/vendor.py b/kontor-api/src/apis/version1/tysc/vendor.py similarity index 100% rename from kontor-api/src/apis/version1/vendor.py rename to kontor-api/src/apis/version1/tysc/vendor.py diff --git a/kontor-api/src/apis/version1/user.py b/kontor-api/src/apis/version1/user/profile.py similarity index 100% rename from kontor-api/src/apis/version1/user.py rename to kontor-api/src/apis/version1/user/profile.py diff --git a/kontor-api/src/core/security.py b/kontor-api/src/core/security.py index 9a6ebfe..9fb190c 100644 --- a/kontor-api/src/core/security.py +++ b/kontor-api/src/core/security.py @@ -142,7 +142,7 @@ async def get_current_user( logger.info("Exception raised", exc_info=True) raise credentials_exception with SessionLocal() as db: - user = get_profile_by_username(username=token_data.username, db=db) + user = get_profile_by_username(username=str(token_data.username), db=db) if user is None: logger.info("user not found") raise credentials_exception diff --git a/kontor-api/src/db/models/bookshelf.py b/kontor-api/src/db/models/bookshelf.py index c2b4e4b..8f9f25d 100644 --- a/kontor-api/src/db/models/bookshelf.py +++ b/kontor-api/src/db/models/bookshelf.py @@ -1,50 +1,52 @@ +from typing import List + from sqlalchemy import Column, ForeignKey, Integer, String -from sqlalchemy.orm import relationship +from sqlalchemy.orm import Mapped, mapped_column, relationship from src.db.models.base import Base, BaseMixin class Article(Base, BaseMixin): __tablename__ = 'article' - title = Column(String, unique=True) + title: Mapped[str] = mapped_column(unique=True) article_authors = relationship("ArticleAuthor") class Author(Base, BaseMixin): __tablename__ = 'author' - first_name = Column(String) - last_name = Column(String) - article_authors = relationship("ArticleAuthor") - book_authors = relationship("BookAuthor") + first_name: Mapped[str] + last_name: Mapped[str] + article_authors: Mapped[List["ArticleAuthor"]] = relationship(back_populates="author") + book_authors: Mapped[List["BookAuthor"]] = relationship(back_populates="author") class BookshelfPublisher(Base, BaseMixin): __tablename__ = 'bookshelf_publisher' - name = Column(String, unique=True) - books = relationship("Book") + name: Mapped[str] = mapped_column(unique=True) + books: Mapped[List["Book"]] = relationship(back_populates="publisher") class Book(Base, BaseMixin): __tablename__ = 'book' - isbn = Column(String, unique=True) - title = Column(String) - year = Column(Integer, nullable=False) - publisher_id = Column(String, ForeignKey('bookshelf_publisher.id'), nullable=False) - publisher = relationship('BookshelfPublisher', back_populates="books") - book_authors = relationship("BookAuthor") + isbn: Mapped[str] = mapped_column(unique=True) + title: Mapped[str] + year: Mapped[int] = mapped_column(nullable=False) + publisher_id: Mapped[str] = mapped_column(ForeignKey("bookshelf_publisher.id"), nullable=False) + publisher: Mapped[BookshelfPublisher] = relationship(back_populates="books") + book_authors: Mapped[List["BookAuthor"]] = relationship(back_populates="book") class ArticleAuthor(Base, BaseMixin): __tablename__ = 'article_author' - article_id = Column(String, ForeignKey('article.id'), nullable=False) - article = relationship('Article', back_populates="article_authors") - author_id = Column(String, ForeignKey('author.id'), nullable=False) - author = relationship('Author', back_populates="article_authors") + article_id: Mapped[str] = mapped_column(ForeignKey("article.id"), nullable=False) + article: Mapped[Article] = relationship(back_populates="article_authors") + author_id: Mapped[str] = mapped_column(ForeignKey("author.id"), nullable=False) + author: Mapped[Author] = relationship(back_populates="article_authors") class BookAuthor(Base, BaseMixin): __tablename__ = 'book_author' - author_id = Column(String, ForeignKey('author.id'), nullable=False) - author = relationship('Author', back_populates="book_authors") - book_id = Column(String, ForeignKey('book.id'), nullable=False) - book = relationship('Book', back_populates="book_authors") + author_id: Mapped[str] = mapped_column(ForeignKey("author.id"), nullable=False) + author: Mapped[Author] = relationship(back_populates="book_authors") + book_id: Mapped[str] = mapped_column(ForeignKey("book.id"), nullable=False) + book: Mapped[Book] = relationship(back_populates="book_authors") diff --git a/kontor-api/src/db/repository/comics/comic.py b/kontor-api/src/db/repository/comics/comic.py index 3a752c4..14362d1 100644 --- a/kontor-api/src/db/repository/comics/comic.py +++ b/kontor-api/src/db/repository/comics/comic.py @@ -20,13 +20,16 @@ def list_comics(db: Session) -> List[Comic]: def get_issue_details(issue: Issue) -> IssueDetailsResponse: + volume = None + if issue.volume: + volume = VolumeResponse(id=issue.volume.id, name=issue.volume.name) response = IssueDetailsResponse( id=issue.id, issue_number=str(issue.issue_number), in_stock=bool(issue.in_stock), is_read=bool(issue.is_read), comic=ComicResponse(id=issue.comic.id, title=issue.comic.title, completed=issue.comic.completed), - volume=VolumeResponse(id=issue.volume.id, name=issue.volume.name) + volume=volume ) return response diff --git a/kontor-api/src/main.py b/kontor-api/src/main.py index b0301f2..3d48256 100644 --- a/kontor-api/src/main.py +++ b/kontor-api/src/main.py @@ -6,7 +6,7 @@ from fastapi.staticfiles import StaticFiles from src.apis.base import api_router from src.apis.version1.healthcheck import health_router -from src.apis.version1.login import login_router +from src.apis.version1.admin.login import login_router from src.core.config import settings from src.core.log_conf import logger from src.db.models.base import Base diff --git a/kontor-api/src/schema/bookshelf/article.py b/kontor-api/src/schema/bookshelf/article.py new file mode 100644 index 0000000..3cf3861 --- /dev/null +++ b/kontor-api/src/schema/bookshelf/article.py @@ -0,0 +1,23 @@ +from datetime import datetime + +from pydantic import BaseModel + +from src.db.models.bookshelf import Article + + +class ArticleResponse(BaseModel): + id: str + created_date: datetime + last_modified_date: datetime + version: int + title: str + +def to_response(article: Article) -> ArticleResponse: + response: ArticleResponse = ArticleResponse( + id=article.id, + created_date=article.created_date, + last_modified_date=article.last_modified_date, + version=article.version, + title=article.title + ) + return response diff --git a/kontor-api/src/schema/tysc/card.py b/kontor-api/src/schema/tysc/card.py new file mode 100644 index 0000000..7fe6cdf --- /dev/null +++ b/kontor-api/src/schema/tysc/card.py @@ -0,0 +1,31 @@ +from datetime import datetime + +from pydantic import BaseModel + +from src.db.models.tysc import Card + + +class CardResponse(BaseModel): + id: str + created_date: datetime + last_modified_date: datetime + version: int + card_number: int + year: int + card_set_id: str + rooster_id: str + vendor_id: str + +def to_response(card: Card) -> CardResponse: + response: CardResponse = CardResponse( + id=card.id, + created_date=card.created_date, + last_modified_date=card.last_modified_date, + version=card.version, + card_number=card.card_number, + year=card.year, + card_set_id=card.card_set_id, + rooster_id=card.rooster_id, + vendor_id=card.vendor_id + ) + return response diff --git a/kontor-api/src/schema/tysc/cardset.py b/kontor-api/src/schema/tysc/cardset.py new file mode 100644 index 0000000..0e2b77f --- /dev/null +++ b/kontor-api/src/schema/tysc/cardset.py @@ -0,0 +1,30 @@ +from datetime import datetime + +from pydantic import BaseModel + +from src.db.models.tysc import CardSet + + +class CardSetResponse(BaseModel): + id: str + created_date: datetime + last_modified_date: datetime + version: int + name: str + parallel_set: bool + insert_set: bool + vendor_id: str + + +def to_response(cardset: CardSet) -> CardSetResponse: + response: CardSetResponse = CardSetResponse( + id=cardset.id, + created_date=cardset.created_date, + last_modified_date=cardset.last_modified_date, + version=cardset.version, + name=cardset.name, + parallel_set=cardset.parallel_set, + insert_set=cardset.insert_set, + vendor_id=cardset.vendor_id + ) + return response diff --git a/kontor-api/src/schema/tysc/fieldposition.py b/kontor-api/src/schema/tysc/fieldposition.py index 4d57115..a206789 100644 --- a/kontor-api/src/schema/tysc/fieldposition.py +++ b/kontor-api/src/schema/tysc/fieldposition.py @@ -2,7 +2,7 @@ from datetime import datetime from pydantic import BaseModel -from src.db.models.tysc import FieldPosition, Team +from src.db.models.tysc import FieldPosition class FieldPositionResponse(BaseModel): diff --git a/kontor-api/src/schema/tysc/rooster.py b/kontor-api/src/schema/tysc/rooster.py index 645cce6..ccbcf55 100644 --- a/kontor-api/src/schema/tysc/rooster.py +++ b/kontor-api/src/schema/tysc/rooster.py @@ -19,7 +19,7 @@ class RoosterResponse(BaseModel): position_id: str -def to_reponse(rooster: Rooster) -> RoosterResponse: +def to_response(rooster: Rooster) -> RoosterResponse: """ convert database object to response object (Pydantic). """ diff --git a/kontor-api/src/webapps/auth/route_login.py b/kontor-api/src/webapps/auth/route_login.py index a3c54e9..4373afa 100644 --- a/kontor-api/src/webapps/auth/route_login.py +++ b/kontor-api/src/webapps/auth/route_login.py @@ -1,8 +1,4 @@ -# from src.apis.version1.admin import login_for_access_token -from fastapi.security import OAuth2PasswordRequestForm - -from src.apis.version1.admin import login_for_token_cookie -from src.db.session import SessionDep +from src.apis.version1.admin.token import login_for_token_cookie from fastapi import APIRouter, Depends from fastapi import HTTPException from fastapi import Request @@ -20,7 +16,7 @@ def login(request: Request): @router.post("/login/") -async def login(request: Request): +async def validate_login(request: Request): form = LoginForm(request) await form.load_data() if await form.is_valid(): @@ -31,6 +27,8 @@ async def login(request: Request): return response except HTTPException: form.__dict__.update(msg="") - form.__dict__.get("errors").append("Incorrect Email or Password") + errors = form.__dict__.get("errors") + if errors: + errors.append("Incorrect Email or Password") return templates.TemplateResponse("auth/login.html", form.__dict__) return templates.TemplateResponse("auth/login.html", form.__dict__) \ No newline at end of file diff --git a/kontor-scripts/api.py b/kontor-scripts/api.py index e37ba58..42c05c6 100644 --- a/kontor-scripts/api.py +++ b/kontor-scripts/api.py @@ -28,24 +28,30 @@ MAPPING: Dict[str, str] = { "story_arc": "api/comics/storyarcs", "issue": "api/comics/issues", "issue_work": "api/comics/issueworks", - "article": "", - "bookshelf_publisher": "", - "book": "", - "author": "", - "article_author": "", - "book_author": "", - "media_article": "", + "article": "api/bookshelf/articles", + "bookshelf_publisher": "api/bookshelf/publishers", + "book": "api/bookshelf/books", + "author": "api/bookshelf/authors", + "article_author": "api/bookshelf/articleauthors", + "book_author": "api/bookshelf/bookauthors", + "media_article": "api/media/articles", "media_video": "api/media/videos", "media_file": "api/media/files", "media_actor": "api/media/actors", "media_actor_file": "api/media/actorfiles", - "profile": "", - "permission": "", - "assignment": "", - "token": "", - "mail_account": "", + "profile": "api/user/profiles", + "permission": "api/user/permissions", + "assignment": "api/user/assignments", + "token": "api/user/tokens", + "mail_account": "api/admin/mailaccount", } +class EndPointNotAvailableException(Exception): + """ + Raised when calling an not existing endpoint. + """ + + pass @dataclass class Login: @@ -99,7 +105,9 @@ class Server: url: str = f"{self.url}/{MAPPING[table]}?{param}" headers: Dict[str, str] = {"Authorization": f"Bearer {self.token}"} response = requests.get(url, headers=headers, timeout=self.timeout) - log.info(f"Status: {response.status_code}") + log.debug(f"Status: {response.status_code}") + if response.status_code==404: + raise EndPointNotAvailableException data = response.json() return data @@ -121,6 +129,16 @@ class ApiConfig: login: Login server: List[Server] + + def get_server(self, server_name: str) -> Optional[Server]: + """ + """ + found_server = None + for server in self.server: + if server.name == server_name: + found_server = server + return found_server + def get_logger(level, config: str): diff --git a/kontor-scripts/db/models/bookshelf.py b/kontor-scripts/db/models/bookshelf.py index 83a00db..ee303c3 100644 --- a/kontor-scripts/db/models/bookshelf.py +++ b/kontor-scripts/db/models/bookshelf.py @@ -1,4 +1,4 @@ -from typing import Any, AnyStr, Dict +from typing import Any, Dict from sqlalchemy import Column, ForeignKey, Integer, String from sqlalchemy.orm import relationship diff --git a/kontor-scripts/sync.py b/kontor-scripts/sync.py index e84886a..0ddb0e9 100644 --- a/kontor-scripts/sync.py +++ b/kontor-scripts/sync.py @@ -1,12 +1,13 @@ from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser -from dataclasses import dataclass -from api import get_logger, get_api_config +from typing import List +from api import MAPPING, EndPointNotAvailableException, Server, get_logger, get_api_config parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) parser.add_argument("--verbose", "-v", action="count", default=0) parser.add_argument("--config", "-c", default="kontor-api") parser.add_argument("--dry-run", "-m", action="store_true") +parser.add_argument("--server", "-s") parser.add_argument("--cleanup", "-d", action="store_true") args = parser.parse_args() @@ -15,7 +16,20 @@ if __name__== "__main__": logger = get_logger(args.verbose, "kontor") logger.info("kontor.sync started") apiConfig = get_api_config(logger, args.config) - for server in apiConfig.server: - data = server.request(logger, "media_file") - logger.info(len(data)) + server_list: List[Server] = [] + if args.server: + server = apiConfig.get_server(args.server) + if server: + server_list.append(server) + else: + server_list.extend(apiConfig.server) + for server in server_list: + for table, path in MAPPING.items(): + try: + data = server.request(logger, table=table) + logger.info("%s: %s", table, len(data)) + if len(data) == 1: + logger.info("show data: %s", data) + except EndPointNotAvailableException: + logger.info("Endpoint not implemented") logger.info("kontor.sync finished")