Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d80aefe6b2 | |||
| 652378e7de | |||
| 57b942a9ca | |||
| bda453a92a | |||
| a113f08ddc | |||
| cc631a14ed | |||
| 9476d8853e | |||
| 8cc58aed5b | |||
| ec274a60d9 | |||
| 5b7c41c829 | |||
| f73ec33aeb | |||
| cdde57e033 | |||
| 9d07ed9bfb | |||
| 59e705d012 | |||
| 3b50a94928 | |||
| fd5bb14e77 | |||
| a786607608 | |||
| 031d71406c | |||
| 48149b67cf | |||
| 9f0a0c1d1e |
@@ -11,3 +11,4 @@ kontor-robyn.bak
|
|||||||
kontor-robyn.bak2
|
kontor-robyn.bak2
|
||||||
kontor-data/.gradle
|
kontor-data/.gradle
|
||||||
kontor-data/build/
|
kontor-data/build/
|
||||||
|
/kontor-api/kontor-api.code-workspace
|
||||||
|
|||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
# Posted by barth, modified by community. See post 'Timeline' for change history
|
||||||
|
# Retrieved 2026-08-19, License - CC BY-SA 4.0
|
||||||
|
NEXUS_URL=https://nexus.thpeetz.de
|
||||||
|
MAVEN_REPO=maven-snapshots
|
||||||
|
GROUP_ID=de.thpeetz
|
||||||
|
ARTIFACT_ID=kontor-spring
|
||||||
|
VERSION=0.4.0
|
||||||
|
FILE_EXTENSION=jar
|
||||||
|
|
||||||
|
download_url=$(curl -X GET "${NEXUS_URL}/service/rest/v1/search/assets?repository=${MAVEN_REPO}&maven.groupId=${GROUP_ID}&maven.artifactId=${ARTIFACT_ID}&maven.baseVersion=${VERSION}&maven.extension=${FILE_EXTENSION}" -H "accept: application/json" | jq -rc '.items | .[].downloadUrl' | sort | tail -n 1)
|
||||||
|
wget $download_url
|
||||||
|
|
||||||
@@ -14,7 +14,6 @@ ENV PATH="/root/.local/bin:${PATH}"
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY ./pyproject.toml .
|
COPY ./pyproject.toml .
|
||||||
|
|
||||||
RUN uv sync
|
RUN uv sync
|
||||||
|
|
||||||
# ------------------------------- Production Stage ------------------------------ ##
|
# ------------------------------- Production Stage ------------------------------ ##
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "kontor-api"
|
name = "kontor-api"
|
||||||
version = "0.1.0"
|
version = "0.4.0"
|
||||||
description = "Add your description here"
|
description = "Add your description here"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
@@ -24,10 +24,21 @@ dependencies = [
|
|||||||
"psycopg2-binary>=2.9.10",
|
"psycopg2-binary>=2.9.10",
|
||||||
"pytest-cov>=6.1.1",
|
"pytest-cov>=6.1.1",
|
||||||
"databases[sqlite]>=0.9.0",
|
"databases[sqlite]>=0.9.0",
|
||||||
"pydantic[email]>=2.11.3",
|
|
||||||
"jinja2>=3.1.6",
|
"jinja2>=3.1.6",
|
||||||
"asyncpg>=0.30.0",
|
"asyncpg>=0.30.0",
|
||||||
"bcrypt>=4.3.0",
|
"bcrypt>=4.3.0",
|
||||||
"fastapi-jwt-auth>=0.5.0",
|
"fastapi-jwt-auth>=0.5.0",
|
||||||
"msgspec[toml,yaml]>=0.21.1",
|
"msgspec[toml,yaml]>=0.21.1",
|
||||||
|
"kontor-model",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[tool.uv.index]]
|
||||||
|
name = "nexus"
|
||||||
|
url = "https://nexus.thpeetz.de/repository/pypi-group/simple"
|
||||||
|
publish-url = "https://nexus.thpeetz.de/repository/pypi-internal/"
|
||||||
|
default = true
|
||||||
|
|
||||||
|
|
||||||
|
[[tool.uv.index]]
|
||||||
|
name = "nexus-proxy"
|
||||||
|
url = "https://nexus.thpeetz.de/repository/pypi-proxy/simple"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from src.apis.version1.comics import (
|
|||||||
from src.apis.version1.media import (
|
from src.apis.version1.media import (
|
||||||
actor,
|
actor,
|
||||||
file,
|
file,
|
||||||
|
lofi,
|
||||||
mediaactorfile,
|
mediaactorfile,
|
||||||
mediavideo,
|
mediavideo,
|
||||||
mediaarticle,
|
mediaarticle,
|
||||||
@@ -104,6 +105,12 @@ api_router.include_router(
|
|||||||
tags=["media"],
|
tags=["media"],
|
||||||
dependencies=[Depends(get_current_user_from_token)],
|
dependencies=[Depends(get_current_user_from_token)],
|
||||||
)
|
)
|
||||||
|
api_router.include_router(
|
||||||
|
lofi.router,
|
||||||
|
prefix="/media",
|
||||||
|
tags=["media"],
|
||||||
|
dependencies=[Depends(get_current_user_from_token)],
|
||||||
|
)
|
||||||
api_router.include_router(
|
api_router.include_router(
|
||||||
mediaarticle.router,
|
mediaarticle.router,
|
||||||
prefix="/media",
|
prefix="/media",
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ from src.core.security import (
|
|||||||
authenticate_user_by_username,
|
authenticate_user_by_username,
|
||||||
create_access_token,
|
create_access_token,
|
||||||
)
|
)
|
||||||
from src.schema.admin.login import LoginRequest
|
from kontor_model.schema.admin.login import LoginRequest
|
||||||
from src.schema.admin.token import Token
|
from kontor_model.schema.admin.token import Token
|
||||||
from src.webapps.auth.forms import LoginForm
|
from src.webapps.auth.forms import LoginForm
|
||||||
|
|
||||||
login_router = APIRouter()
|
login_router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.admin import MailAccount
|
from kontor_model.db.models.admin import MailAccount
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.admin.mailaccount import MailAccountResponse, to_response
|
from kontor_model.schema.admin.mailaccount import MailAccountResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from src.db.models.bookshelf import Article
|
from kontor_model.db.models.bookshelf import Article
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.bookshelf.article import ArticleResponse, to_response
|
from kontor_model.schema.bookshelf.article import ArticleResponse, to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from src.db.models.bookshelf import ArticleAuthor
|
from kontor_model.db.models.bookshelf import ArticleAuthor
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.bookshelf.articleauthor import ArticleAuthorResponse, to_response
|
from kontor_model.schema.bookshelf.articleauthor import ArticleAuthorResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.bookshelf import Author
|
from kontor_model.db.models.bookshelf import Author
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.bookshelf.author import AuthorResponse, to_response
|
from kontor_model.schema.bookshelf.author import AuthorResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from src.db.models.bookshelf import Book
|
from kontor_model.db.models.bookshelf import Book
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.bookshelf.book import BookResponse, to_response
|
from kontor_model.schema.bookshelf.book import BookResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from src.db.models.bookshelf import BookAuthor
|
from kontor_model.db.models.bookshelf import BookAuthor
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.bookshelf.bookauthor import BookAuthorResponse, to_response
|
from kontor_model.schema.bookshelf.bookauthor import BookAuthorResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from src.db.models.bookshelf import BookshelfPublisher
|
from kontor_model.db.models.bookshelf import BookshelfPublisher
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.bookshelf.publisher import PublisherResponse, to_response
|
from kontor_model.schema.bookshelf.publisher import PublisherResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException, status
|
from fastapi import APIRouter, HTTPException, status
|
||||||
|
|
||||||
from src.db.models.comic import Artist
|
from kontor_model.db.models.comic import Artist
|
||||||
from src.db.repository.comics.artist import get_artist_details
|
from kontor_model.db.repository.comics.artist import get_artist_details
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.artist import ArtistCreation, ArtistResponse, artist_to_response
|
from kontor_model.schema.comics.artist import ArtistCreation, ArtistResponse, artist_to_response
|
||||||
from src.schema.comics.artist_details import ArtistDetailResponse
|
from kontor_model.schema.comics.artist_details import ArtistDetailResponse
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ from typing import List
|
|||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.db.models.comic import Comic
|
from kontor_model.db.models.comic import Comic
|
||||||
from src.db.repository.comics.comic import (
|
from kontor_model.db.repository.comics.comic import (
|
||||||
get_comic_details,
|
get_comic_details,
|
||||||
)
|
)
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.comic import ComicResponse, comic_to_response
|
from kontor_model.schema.comics.comic import ComicResponse, comic_to_response
|
||||||
from src.schema.comics.comic_details import ComicDetailsResponse
|
from kontor_model.schema.comics.comic_details import ComicDetailsResponse
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.comic import ComicWork
|
from kontor_model.db.models.comic import ComicWork
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.comicwork import ComicWorkResponse, comicwork_to_response
|
from kontor_model.schema.comics.comicwork import ComicWorkResponse, comicwork_to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.comic import Issue
|
from kontor_model.db.models.comic import Issue
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.issue import IssueResponse, issue_to_response
|
from kontor_model.schema.comics.issue import IssueResponse, issue_to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.comic import IssueWork
|
from kontor_model.db.models.comic import IssueWork
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.issuework import IssueWorkResponse, issuework_to_response
|
from kontor_model.schema.comics.issuework import IssueWorkResponse, issuework_to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.comic import Publisher
|
from kontor_model.db.models.comic import Publisher
|
||||||
from src.db.repository.comics.publisher import get_publisher_details
|
from kontor_model.db.repository.comics.publisher import get_publisher_details
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.publisher import PublisherResponse, publisher_to_response
|
from kontor_model.schema.comics.publisher import PublisherResponse, publisher_to_response
|
||||||
from src.schema.comics.publisher_details import PublisherDetailsResponse
|
from kontor_model.schema.comics.publisher_details import PublisherDetailsResponse
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.comic import StoryArc
|
from kontor_model.db.models.comic import StoryArc
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.storyarc import StoryArcResponse, storyarc_to_response
|
from kontor_model.schema.comics.storyarc import StoryArcResponse, storyarc_to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.comic import Volume
|
from kontor_model.db.models.comic import Volume
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.volume import VolumeResponse, volume_to_response
|
from kontor_model.schema.comics.volume import VolumeResponse, volume_to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.comic import WorkType
|
from kontor_model.db.models.comic import WorkType
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.worktype import WorktypeResponse, worktype_to_response
|
from kontor_model.schema.comics.worktype import WorktypeResponse, worktype_to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from fastapi import APIRouter, status
|
from fastapi import APIRouter, status
|
||||||
|
|
||||||
from src.schema.admin.healthcheck import HealthCheck
|
from kontor_model.schema.admin.healthcheck import HealthCheck
|
||||||
|
|
||||||
health_router = APIRouter()
|
health_router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, status, HTTPException
|
from fastapi import APIRouter, status, HTTPException
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.db.repository.media.actor import delete_mediaactor, import_mediaactor
|
from kontor_model.db.repository.media.actor import delete_mediaactor, import_mediaactor
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.media.actor import MediaActorModel, MediaActorResponse, actor_to_response
|
from kontor_model.schema.media.actor import MediaActorModel, MediaActorResponse, actor_to_response
|
||||||
from src.db.models.media import MediaActor
|
from kontor_model.db.models.media import MediaActor
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,21 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, status, HTTPException
|
from fastapi import APIRouter, status, HTTPException
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.db.repository.media.actorfile import (
|
from kontor_model.db.repository.media.actorfile import (
|
||||||
create_new_mediaactorfile,
|
create_new_mediaactorfile,
|
||||||
delete_mediaactorfile,
|
delete_mediaactorfile,
|
||||||
)
|
)
|
||||||
from src.db.repository.media.file import delete_mediafile, import_mediafile
|
from kontor_model.db.repository.media.file import delete_mediafile, import_mediafile
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.media.actor import MediaActorResponse, actor_to_response
|
from kontor_model.schema.media.actor import MediaActorResponse, actor_to_response
|
||||||
from src.schema.media.actorfile import MediaActorFileResponse, actorfile_to_response
|
from kontor_model.schema.media.actorfile import MediaActorFileResponse, actorfile_to_response
|
||||||
from src.schema.media.file import (
|
from kontor_model.schema.media.file import (
|
||||||
MediaFileModel,
|
MediaFileModel,
|
||||||
MediaFileResponse,
|
MediaFileResponse,
|
||||||
file_to_response,
|
file_to_response,
|
||||||
file_to_model,
|
file_to_model,
|
||||||
)
|
)
|
||||||
from src.db.models.media import MediaFile
|
from kontor_model.db.models.media import MediaFile
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from fastapi import APIRouter, status, HTTPException
|
||||||
|
|
||||||
|
from kontor_model.db.models.media import MediaLofi
|
||||||
|
from src.db.session import SessionDep
|
||||||
|
from src.core.log_conf import logger
|
||||||
|
from kontor_model.schema.media.lofi import (
|
||||||
|
MediaLofiModel,
|
||||||
|
MediaLofiResponse,
|
||||||
|
lofi_to_response,
|
||||||
|
lofi_to_model
|
||||||
|
)
|
||||||
|
from kontor_model.db.repository.media.lofi import (
|
||||||
|
import_medialofi,
|
||||||
|
delete_medialofi
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
@router.get("/lofi", response_model=List[MediaLofiResponse])
|
||||||
|
def get_all_lofis(
|
||||||
|
db: SessionDep, review: bool = False, download: bool = False
|
||||||
|
) -> List[MediaLofiResponse]:
|
||||||
|
"""
|
||||||
|
Get all MediaLofis.
|
||||||
|
"""
|
||||||
|
results: List[MediaLofiResponse] = []
|
||||||
|
lofis: List[MediaLofi]
|
||||||
|
if review:
|
||||||
|
lofis = db.query(MediaLofi).filter(MediaLofi.review.is_(True)).all()
|
||||||
|
elif download:
|
||||||
|
lofis = db.query(MediaLofi).filter(MediaLofi.should_download.is_(True)).all()
|
||||||
|
else:
|
||||||
|
lofis = db.query(MediaLofi).all()
|
||||||
|
for medialofi in lofis:
|
||||||
|
response = lofi_to_response(medialofi)
|
||||||
|
results.append(response)
|
||||||
|
return results
|
||||||
|
|
||||||
|
@router.get("/lofi/{lofi_id}", response_model=MediaLofiResponse)
|
||||||
|
def get_lofi(lofi_id: str, db: SessionDep) -> MediaLofiResponse:
|
||||||
|
"""
|
||||||
|
Get MediaLofi by id.
|
||||||
|
"""
|
||||||
|
lofi = db.get(MediaLofi, lofi_id)
|
||||||
|
if lofi is None:
|
||||||
|
raise HTTPException(status_code=404, detail="MediaLofi could not be found")
|
||||||
|
response = lofi_to_response(lofi)
|
||||||
|
return response
|
||||||
|
|
||||||
|
@router.delete("/lofi/{lofi_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||||
|
def delete_lofi(lofi_id: str, db: SessionDep):
|
||||||
|
"""
|
||||||
|
Delete MediaFile by given id.
|
||||||
|
"""
|
||||||
|
lofi = db.get(MediaLofi, lofi_id)
|
||||||
|
if not lofi:
|
||||||
|
raise HTTPException(status_code=404, detail="MediaLofi could not be found")
|
||||||
|
logger.info("delete MediaLofi: %s", lofi_id)
|
||||||
|
delete_medialofi(db=db, lofi_id=lofi.id)
|
||||||
|
|
||||||
|
@router.put("/lofi/{lofi_id}", response_model=MediaLofiResponse)
|
||||||
|
def update_lofi(lofi_id: str, db: SessionDep, info: MediaLofiResponse) -> MediaLofiResponse:
|
||||||
|
"""
|
||||||
|
Update MediaLofi with given id and data.
|
||||||
|
"""
|
||||||
|
media_lofi = db.get(MediaLofi, lofi_id)
|
||||||
|
if not media_lofi:
|
||||||
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="MediaLofi could not be found")
|
||||||
|
lofi_to_model(info, media_lofi)
|
||||||
|
db.add(media_lofi)
|
||||||
|
db.commit()
|
||||||
|
media_lofi = db.get(MediaLofi, lofi_id)
|
||||||
|
if not media_lofi:
|
||||||
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="MediaLofi could not be found")
|
||||||
|
response = lofi_to_response(media_lofi)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/lofi", status_code=status.HTTP_201_CREATED)
|
||||||
|
def add_lofi(new_lofi: MediaLofiModel, db: SessionDep) -> MediaLofiResponse:
|
||||||
|
logger.info("add medialofi %s", new_lofi)
|
||||||
|
try:
|
||||||
|
medialofi: MediaLofi = import_medialofi(db, new_lofi)
|
||||||
|
except:
|
||||||
|
raise HTTPException(status_code=409, detail="MediaLofi duplicate")
|
||||||
|
response = lofi_to_response(medialofi)
|
||||||
|
return response
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
from fastapi import APIRouter, status, HTTPException
|
from fastapi import APIRouter, status, HTTPException
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.db.models.media import MediaActorFile
|
from kontor_model.db.models.media import MediaActorFile
|
||||||
from src.db.repository.media.actorfile import delete_mediaactorfile, import_mediaactorfile
|
from kontor_model.db.repository.media.actorfile import delete_mediaactorfile, import_mediaactorfile
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.media.actorfile import MediaActorFileModel, MediaActorFileResponse, actorfile_to_response
|
from kontor_model.schema.media.actorfile import MediaActorFileModel, MediaActorFileResponse, actorfile_to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from src.db.models.media import MediaArticle
|
from kontor_model.db.models.media import MediaArticle
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.media.article import MediaArticleResponse, to_response
|
from kontor_model.schema.media.article import MediaArticleResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.media import MediaVideo
|
from kontor_model.db.models.media import MediaVideo
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.media.video import MediaVideoResponse, video_to_response
|
from kontor_model.schema.media.video import MediaVideoResponse, video_to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.tysc import Card
|
from kontor_model.db.models.tysc import Card
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.tysc.card import CardResponse, to_response
|
from kontor_model.schema.tysc.card import CardResponse, to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.tysc import CardSet
|
from kontor_model.db.models.tysc import CardSet
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.tysc.cardset import CardSetResponse, to_response
|
from kontor_model.schema.tysc.cardset import CardSetResponse, to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.tysc import FieldPosition
|
from kontor_model.db.models.tysc import FieldPosition
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.tysc.fieldposition import FieldPositionResponse, to_response
|
from kontor_model.schema.tysc.fieldposition import FieldPositionResponse, to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.tysc import Player
|
from kontor_model.db.models.tysc import Player
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.tysc.player import PlayerResponse, to_response
|
from kontor_model.schema.tysc.player import PlayerResponse, to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.tysc import Rooster
|
from kontor_model.db.models.tysc import Rooster
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.tysc.rooster import RoosterResponse, to_response
|
from kontor_model.schema.tysc.rooster import RoosterResponse, to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ from fastapi import APIRouter, HTTPException
|
|||||||
|
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.tysc.sport import SportResponse, to_response
|
from kontor_model.schema.tysc.sport import SportResponse, to_response
|
||||||
from src.db.models.tysc import Sport
|
from kontor_model.db.models.tysc import Sport
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.tysc import Team
|
from kontor_model.db.models.tysc import Team
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.tysc.team import TeamResponse, to_response
|
from kontor_model.schema.tysc.team import TeamResponse, to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.tysc import Vendor
|
from kontor_model.db.models.tysc import Vendor
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.tysc.vendor import VendorResponse, to_response
|
from kontor_model.schema.tysc.vendor import VendorResponse, to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.admin import Assignment
|
from kontor_model.db.models.admin import Assignment
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.user.assignment import AssignmentResponse, to_response
|
from kontor_model.schema.user.assignment import AssignmentResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
from src.db.models.admin import Permission
|
from kontor_model.db.models.admin import Permission
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.user.permission import PermissionResponse, to_response
|
from kontor_model.schema.user.permission import PermissionResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ from sqlalchemy import select
|
|||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
|
|
||||||
from src.core.security import CurrentUser
|
from src.core.security import CurrentUser
|
||||||
from src.db.models.admin import Profile
|
from kontor_model.db.models.admin import Profile
|
||||||
from src.db.repository.user import create_new_profile
|
from src.db.repository.user import create_new_profile
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.user.profile import ProfileResponse, ProfileModel, to_response
|
from kontor_model.schema.user.profile import ProfileResponse, ProfileModel, to_response
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from typing import List
|
|||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from src.db.models.admin import Token
|
from kontor_model.db.models.admin import Token
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.user.token import TokenResponse, to_response
|
from kontor_model.schema.user.token import TokenResponse, to_response
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -9,17 +9,21 @@ load_dotenv(dotenv_path=env_path)
|
|||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
PROJECT_NAME: str = "Kontor"
|
PROJECT_NAME: str = "Kontor"
|
||||||
PROJECT_VERSION: str = "0.3.0"
|
PROJECT_VERSION: str = "0.4.0"
|
||||||
|
|
||||||
DB_USER: str = os.getenv("DB_USER", "kontor")
|
DB_USER: str = os.getenv("DB_USER", "kontor")
|
||||||
DB_PASSWORD: str = os.getenv("DB_PASSWORD", "kontor")
|
DB_PASSWORD: str = os.getenv("DB_PASSWORD", "kontor")
|
||||||
DB_SERVER: str = os.getenv("DB_SERVER", "postgres")
|
DB_SERVER: str = os.getenv("DB_SERVER", "postgres")
|
||||||
DB_PORT: int = int(os.getenv("DB_PORT", 5432))
|
DB_PORT: int = int(os.getenv("DB_PORT", 5432))
|
||||||
DB_DBNAME: str = os.getenv("DB_DBNAME", "kontor")
|
DB_DBNAME: str = os.getenv("DB_DBNAME", "kontor")
|
||||||
DATABASE_URL: str = f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_SERVER}:{DB_PORT}/{DB_DBNAME}"
|
DATABASE_URL: str = (
|
||||||
SECRET_KEY: str = os.getenv("SECRET_KEY", "J6GOtcwC2NJI1l0VkHu20PacPFGTxpirBxWwynoHjsc=")
|
f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_SERVER}:{DB_PORT}/{DB_DBNAME}"
|
||||||
|
)
|
||||||
|
SECRET_KEY: str = os.getenv(
|
||||||
|
"SECRET_KEY", "J6GOtcwC2NJI1l0VkHu20PacPFGTxpirBxWwynoHjsc="
|
||||||
|
)
|
||||||
ALGORITHM = "HS256"
|
ALGORITHM = "HS256"
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES = 60*24*7 # one week in mins
|
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # one week in mins
|
||||||
|
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ from pydantic import ValidationError
|
|||||||
|
|
||||||
from src.core.config import settings
|
from src.core.config import settings
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.db.models.admin import Profile
|
from kontor_model.db.models.admin import Profile
|
||||||
from src.db.repository.admin import (
|
from kontor_model.db.repository.admin import (
|
||||||
get_profile_by_username,
|
get_profile_by_username,
|
||||||
get_profile_by_email,
|
get_profile_by_email,
|
||||||
is_database_empty,
|
is_database_empty,
|
||||||
)
|
)
|
||||||
from src.db.session import SessionLocal
|
from src.db.session import SessionLocal
|
||||||
from src.schema.admin.token import TokenData
|
from kontor_model.schema.admin.token import TokenData
|
||||||
from src.schema.user.profile import ProfileModel, to_model
|
from kontor_model.schema.user.profile import ProfileModel, to_model
|
||||||
|
|
||||||
oauth2_scheme = OAuth2PasswordBearer(
|
oauth2_scheme = OAuth2PasswordBearer(
|
||||||
tokenUrl="/token",
|
tokenUrl="/token",
|
||||||
@@ -163,7 +163,7 @@ async def get_current_user(
|
|||||||
async def get_current_active_user(
|
async def get_current_active_user(
|
||||||
current_user: Annotated[Profile, Security(get_current_user, scopes=["me"])],
|
current_user: Annotated[Profile, Security(get_current_user, scopes=["me"])],
|
||||||
) -> ProfileModel:
|
) -> ProfileModel:
|
||||||
if not current_user.enabled:
|
if not bool(current_user.enabled):
|
||||||
raise HTTPException(status_code=400, detail="Inactive user")
|
raise HTTPException(status_code=400, detail="Inactive user")
|
||||||
user_model = to_model(current_user)
|
user_model = to_model(current_user)
|
||||||
return user_model
|
return user_model
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from sqlalchemy import ForeignKey
|
|
||||||
from sqlalchemy.orm import relationship, mapped_column, Mapped
|
|
||||||
|
|
||||||
from src.db.models.base import Base, BaseMixin
|
|
||||||
|
|
||||||
|
|
||||||
class Profile(Base, BaseMixin):
|
|
||||||
__tablename__ = 'profile'
|
|
||||||
first_name: Mapped[str]
|
|
||||||
last_name: Mapped[str]
|
|
||||||
user_name: Mapped[str] = mapped_column(nullable=False)
|
|
||||||
email: Mapped[str]
|
|
||||||
password: Mapped[str]
|
|
||||||
enabled: Mapped[bool]
|
|
||||||
assignments: Mapped[List["Assignment"]] = relationship(back_populates="profile")
|
|
||||||
tokens: Mapped[List["Token"]] = relationship(back_populates="profile")
|
|
||||||
|
|
||||||
def get_full_name(self) -> str:
|
|
||||||
full_name: str = ""
|
|
||||||
if self.first_name is not None:
|
|
||||||
full_name += str(self.first_name)
|
|
||||||
if self.last_name is not None:
|
|
||||||
if len(full_name) > 0:
|
|
||||||
full_name += " "
|
|
||||||
full_name += str(self.last_name)
|
|
||||||
return full_name
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"Profile({self.id} {self.user_name}, {self.email})"
|
|
||||||
|
|
||||||
|
|
||||||
class Token(Base, BaseMixin):
|
|
||||||
__tablename__ = "token"
|
|
||||||
token: Mapped[str] = mapped_column(nullable=False, unique=True)
|
|
||||||
name: Mapped[str]
|
|
||||||
last_used_date: Mapped[datetime]
|
|
||||||
enabled: Mapped[bool]
|
|
||||||
profile_id = mapped_column(ForeignKey("profile.id"), nullable=False)
|
|
||||||
profile: Mapped[Profile] = relationship(back_populates="tokens")
|
|
||||||
|
|
||||||
|
|
||||||
class Permission(Base, BaseMixin):
|
|
||||||
__tablename__ = "permission"
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False)
|
|
||||||
assignments: Mapped[List["Assignment"]] = relationship(back_populates="permission")
|
|
||||||
|
|
||||||
|
|
||||||
class Assignment(Base, BaseMixin):
|
|
||||||
__tablename__ = "assignment"
|
|
||||||
profile_id = mapped_column(ForeignKey("profile.id"), nullable=False)
|
|
||||||
profile: Mapped[Profile] = relationship(back_populates="assignments")
|
|
||||||
permission_id = mapped_column(ForeignKey("permission.id"), nullable=False)
|
|
||||||
permission: Mapped[Permission] = relationship(back_populates="assignments")
|
|
||||||
|
|
||||||
|
|
||||||
class MailAccount(Base, BaseMixin):
|
|
||||||
__tablename__ = "mail_account"
|
|
||||||
host: Mapped[str]
|
|
||||||
port: Mapped[int]
|
|
||||||
protocol: Mapped[str]
|
|
||||||
user_name: Mapped[str]
|
|
||||||
password: Mapped[str]
|
|
||||||
start_tls: Mapped[bool]
|
|
||||||
|
|
||||||
|
|
||||||
class Mail(Base, BaseMixin):
|
|
||||||
__tablename__ = "mail"
|
|
||||||
folder: Mapped[str]
|
|
||||||
subject: Mapped[str]
|
|
||||||
body: Mapped[str]
|
|
||||||
sent_date: Mapped[datetime]
|
|
||||||
received_date: Mapped[datetime]
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
from typing import Optional
|
|
||||||
import uuid
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from sqlalchemy import func
|
|
||||||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
|
||||||
|
|
||||||
|
|
||||||
class Base(DeclarativeBase):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BaseMixin:
|
|
||||||
id: Mapped[str] = mapped_column(primary_key=True, default=str(uuid.uuid4()))
|
|
||||||
created_date: Mapped[datetime] = mapped_column(default=func.now())
|
|
||||||
last_modified_date: Mapped[datetime] = mapped_column(default=func.now())
|
|
||||||
version: Mapped[int] = mapped_column(default=0)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseVideoMixin:
|
|
||||||
cloud_link: Mapped[Optional[str]]
|
|
||||||
file_name: Mapped[Optional[str]]
|
|
||||||
path: Mapped[str]
|
|
||||||
review: Mapped[bool]
|
|
||||||
title: Mapped[str]
|
|
||||||
url: Mapped[str]
|
|
||||||
should_download: Mapped[bool]
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
from typing import List
|
|
||||||
|
|
||||||
from sqlalchemy import Column, ForeignKey, Integer, String
|
|
||||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
||||||
|
|
||||||
from src.db.models.base import Base, BaseMixin
|
|
||||||
|
|
||||||
|
|
||||||
class Article(Base, BaseMixin):
|
|
||||||
__tablename__ = 'article'
|
|
||||||
title: Mapped[str] = mapped_column(unique=True)
|
|
||||||
article_authors = relationship("ArticleAuthor")
|
|
||||||
|
|
||||||
|
|
||||||
class Author(Base, BaseMixin):
|
|
||||||
__tablename__ = 'author'
|
|
||||||
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: Mapped[str] = mapped_column(unique=True)
|
|
||||||
books: Mapped[List["Book"]] = relationship(back_populates="publisher")
|
|
||||||
|
|
||||||
|
|
||||||
class Book(Base, BaseMixin):
|
|
||||||
__tablename__ = 'book'
|
|
||||||
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: 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: 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")
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
import uuid
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import Dict, List, Optional, Any
|
|
||||||
from natsort import natsorted
|
|
||||||
from sqlalchemy import ForeignKey, func
|
|
||||||
from sqlalchemy.orm import relationship, Mapped, mapped_column
|
|
||||||
|
|
||||||
from src.db.models.base import Base, BaseMixin
|
|
||||||
|
|
||||||
|
|
||||||
class Publisher(Base):
|
|
||||||
__tablename__ = "publisher"
|
|
||||||
id: Mapped[str] = mapped_column(primary_key=True, default=uuid.uuid4)
|
|
||||||
created_date: Mapped[datetime] = mapped_column(default=func.now())
|
|
||||||
last_modified_date: Mapped[datetime] = mapped_column(default=func.now())
|
|
||||||
version: Mapped[int] = mapped_column(default=0)
|
|
||||||
name: Mapped[str] = mapped_column(unique=True)
|
|
||||||
weblink: Mapped[Optional[str]]
|
|
||||||
parent_publisher_id: Mapped[Optional[str]] = mapped_column(ForeignKey('publisher.id'))
|
|
||||||
parent_publisher: Mapped[Optional['Publisher']] = relationship(back_populates="imprints", remote_side=[id])
|
|
||||||
imprints: Mapped[List['Publisher']] = relationship(back_populates="parent_publisher")
|
|
||||||
comics: Mapped[List["Comic"]] = relationship(back_populates="publisher")
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f'Publisher({self.id} {self.name})'
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.__repr__()
|
|
||||||
|
|
||||||
|
|
||||||
class Comic(Base, BaseMixin):
|
|
||||||
__tablename__ = 'comic'
|
|
||||||
title: Mapped[str] = mapped_column(unique=True)
|
|
||||||
publisher_id: Mapped[str] = mapped_column(ForeignKey('publisher.id'), nullable=False)
|
|
||||||
publisher: Mapped[Publisher] = relationship(back_populates="comics")
|
|
||||||
current_order: Mapped[bool]
|
|
||||||
completed: Mapped[bool]
|
|
||||||
weblink: Mapped[Optional[str]]
|
|
||||||
issues: Mapped[List["Issue"]] = relationship(back_populates="comic", order_by="Issue.issue_number")
|
|
||||||
story_arcs: Mapped[List["StoryArc"]] = relationship(back_populates="comic")
|
|
||||||
trade_paperbacks: Mapped[List["TradePaperback"]] = relationship(back_populates="comic")
|
|
||||||
volumes: Mapped[List["Volume"]] = relationship(back_populates="comic")
|
|
||||||
comic_works: Mapped[List["ComicWork"]] = relationship(back_populates="comic")
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f'Comic({self.id} {self.version} {self.title} {self.publisher.name})'
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f'{self.title}({self.id})'
|
|
||||||
|
|
||||||
def get_artists(self) -> Dict[Any, List[Any]]:
|
|
||||||
works: Dict[Any, List[Any]] = {}
|
|
||||||
for work in self.comic_works:
|
|
||||||
work_type = work.work_type
|
|
||||||
artist = work.artist
|
|
||||||
if work_type in works:
|
|
||||||
works[work_type].append(artist)
|
|
||||||
else:
|
|
||||||
works[work_type] = [artist]
|
|
||||||
return works
|
|
||||||
|
|
||||||
def sorted_issues(self):
|
|
||||||
sorted_issues = natsorted(self.issues, key=lambda x: getattr(x, 'issue_number'))
|
|
||||||
return sorted_issues
|
|
||||||
|
|
||||||
|
|
||||||
class Volume(Base, BaseMixin):
|
|
||||||
__tablename__ = "volume"
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False)
|
|
||||||
comic_id: Mapped[str] = mapped_column(ForeignKey("comic.id"), nullable=False)
|
|
||||||
comic: Mapped[Comic] = relationship(back_populates="volumes")
|
|
||||||
story_arcs: Mapped[List["StoryArc"]] = relationship(back_populates="volume")
|
|
||||||
issues: Mapped[List["Issue"]] = relationship(back_populates="volume")
|
|
||||||
|
|
||||||
|
|
||||||
class TradePaperback(Base, BaseMixin):
|
|
||||||
__tablename__ = "trade_paperback"
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False)
|
|
||||||
issue_start: Mapped[int]
|
|
||||||
issue_end: Mapped[int]
|
|
||||||
comic_id: Mapped[str] = mapped_column(ForeignKey("comic.id"), nullable=False)
|
|
||||||
comic: Mapped[Comic] = relationship(back_populates="trade_paperbacks")
|
|
||||||
|
|
||||||
|
|
||||||
class StoryArc(Base, BaseMixin):
|
|
||||||
__tablename__ = "story_arc"
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False)
|
|
||||||
comic_id: Mapped[str] = mapped_column(ForeignKey("comic.id"), nullable=False)
|
|
||||||
comic: Mapped[Comic] = relationship(back_populates="story_arcs")
|
|
||||||
volume_id: Mapped[str] = mapped_column(ForeignKey("volume.id"), nullable=True)
|
|
||||||
volume: Mapped[Volume] = relationship(back_populates="story_arcs")
|
|
||||||
issues: Mapped[List["Issue"]] = relationship(back_populates="story_arc")
|
|
||||||
|
|
||||||
|
|
||||||
class Issue(Base, BaseMixin):
|
|
||||||
__tablename__ = "issue"
|
|
||||||
issue_number: Mapped[str]
|
|
||||||
title: Mapped[Optional[str]]
|
|
||||||
published_on: Mapped[Optional[datetime]]
|
|
||||||
in_stock: Mapped[bool]
|
|
||||||
is_read: Mapped[bool]
|
|
||||||
comic_id: Mapped[str] = mapped_column(ForeignKey("comic.id"), nullable=False)
|
|
||||||
comic: Mapped[Comic] = relationship(back_populates="issues")
|
|
||||||
volume_id: Mapped[str] = mapped_column(ForeignKey("volume.id"), nullable=True)
|
|
||||||
volume: Mapped[Volume] = relationship(back_populates="issues")
|
|
||||||
story_arc_id: Mapped[str] = mapped_column(ForeignKey("story_arc.id"), nullable=True)
|
|
||||||
story_arc: Mapped[StoryArc] = relationship(back_populates="issues")
|
|
||||||
issue_works: Mapped[List["IssueWork"]] = relationship(back_populates="issue")
|
|
||||||
|
|
||||||
def get_full_title(self) -> str:
|
|
||||||
full_title: str = str(self.issue_number)
|
|
||||||
if self.title:
|
|
||||||
full_title += str(": " + self.title)
|
|
||||||
return full_title
|
|
||||||
|
|
||||||
def get_artists(self) -> Dict[Any, List[Any]]:
|
|
||||||
works: Dict[Any, List[Any]] = {}
|
|
||||||
for work in self.issue_works:
|
|
||||||
work_type = work.work_type
|
|
||||||
artist = work.artist
|
|
||||||
if work_type in works:
|
|
||||||
works[work_type].append(artist)
|
|
||||||
else:
|
|
||||||
works[work_type] = [artist]
|
|
||||||
return works
|
|
||||||
|
|
||||||
|
|
||||||
class Artist(Base, BaseMixin):
|
|
||||||
__tablename__ = "artist"
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False)
|
|
||||||
weblink: Mapped[str] = mapped_column(nullable=True)
|
|
||||||
comic_works: Mapped[List["ComicWork"]] = relationship(back_populates="artist")
|
|
||||||
issue_works: Mapped[List["IssueWork"]] = relationship(back_populates="artist")
|
|
||||||
|
|
||||||
def get_comics(self) -> Dict[Any, List[Comic]]:
|
|
||||||
works: Dict[Any, List[Comic]] = {}
|
|
||||||
for work in self.comic_works:
|
|
||||||
work_type = work.work_type
|
|
||||||
comic = work.comic
|
|
||||||
if work_type in works:
|
|
||||||
works[work_type].append(comic)
|
|
||||||
else:
|
|
||||||
works[work_type] = [comic]
|
|
||||||
return works
|
|
||||||
|
|
||||||
|
|
||||||
class WorkType(Base, BaseMixin):
|
|
||||||
__tablename__ = "worktype"
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False, unique=True)
|
|
||||||
comic_works: Mapped[List["ComicWork"]] = relationship(back_populates="work_type")
|
|
||||||
issue_works: Mapped[List["IssueWork"]] = relationship(back_populates="work_type")
|
|
||||||
|
|
||||||
def get_artists(self) -> Dict[str, List[Artist]]:
|
|
||||||
works: Dict[str, List[Artist]] = {}
|
|
||||||
for work in self.comic_works:
|
|
||||||
comic = work.comic.title
|
|
||||||
artist = work.artist
|
|
||||||
if comic in works:
|
|
||||||
works[comic].append(artist)
|
|
||||||
else:
|
|
||||||
works[comic] = [artist]
|
|
||||||
return works
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f'Worktype({self.id} {self.version} {self.name} {len(self.comic_works)})'
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f'{self.name}({self.id})'
|
|
||||||
|
|
||||||
|
|
||||||
class ComicWork(Base, BaseMixin):
|
|
||||||
__tablename__ = "comic_work"
|
|
||||||
comic_id: Mapped[str] = mapped_column(ForeignKey("comic.id"), nullable=False)
|
|
||||||
comic: Mapped[Comic] = relationship(back_populates="comic_works")
|
|
||||||
artist_id: Mapped[str] = mapped_column(ForeignKey("artist.id"), nullable=False)
|
|
||||||
artist: Mapped[Artist] = relationship(back_populates="comic_works")
|
|
||||||
work_type_id: Mapped[str] = mapped_column(ForeignKey("worktype.id"), nullable=False)
|
|
||||||
work_type: Mapped[WorkType] = relationship(back_populates="comic_works")
|
|
||||||
|
|
||||||
|
|
||||||
class IssueWork(Base, BaseMixin):
|
|
||||||
__tablename__ = "issue_work"
|
|
||||||
issue_id: Mapped[str] = mapped_column(ForeignKey("issue.id"), nullable=False)
|
|
||||||
issue: Mapped[Issue] = relationship(back_populates="issue_works")
|
|
||||||
artist_id: Mapped[str] = mapped_column(ForeignKey("artist.id"), nullable=False)
|
|
||||||
artist: Mapped[Artist] = relationship(back_populates="issue_works")
|
|
||||||
work_type_id: Mapped[str] = mapped_column(ForeignKey("worktype.id"), nullable=False)
|
|
||||||
work_type: Mapped[WorkType] = relationship(back_populates="issue_works")
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
import logging
|
|
||||||
import re
|
|
||||||
import subprocess
|
|
||||||
from datetime import datetime
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
from sqlalchemy import ForeignKey
|
|
||||||
from sqlalchemy.orm import Mapped, relationship, mapped_column
|
|
||||||
|
|
||||||
from src.db.models.base import Base, BaseMixin, BaseVideoMixin
|
|
||||||
|
|
||||||
|
|
||||||
class MediaFile(Base, BaseMixin, BaseVideoMixin):
|
|
||||||
"""
|
|
||||||
MediaFile represents video link.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__tablename__ = "media_file"
|
|
||||||
media_actor_files: Mapped[List["MediaActorFile"]] = relationship(
|
|
||||||
back_populates="media_file"
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"MediaFile({self.id} {self.title} {self.title})"
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"{self.title}({self.id})"
|
|
||||||
|
|
||||||
def update_title(self):
|
|
||||||
"""
|
|
||||||
Update title from url.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class MediaActor(Base, BaseMixin):
|
|
||||||
__tablename__ = "media_actor"
|
|
||||||
name: Mapped[str]
|
|
||||||
url: Mapped[Optional[str]] = mapped_column(unique=True)
|
|
||||||
media_actor_files = relationship("MediaActorFile")
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
return f"MediaActor({self.id} {self.name} {self.url})"
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f"{self.url}({self.id})"
|
|
||||||
|
|
||||||
|
|
||||||
class MediaActorFile(Base, BaseMixin):
|
|
||||||
__tablename__ = "media_actor_file"
|
|
||||||
media_actor_id: Mapped[str] = mapped_column(
|
|
||||||
ForeignKey("media_actor.id"), nullable=False
|
|
||||||
)
|
|
||||||
media_actor: Mapped[MediaActor] = relationship(back_populates="media_actor_files")
|
|
||||||
media_file_id: Mapped[str] = mapped_column(
|
|
||||||
ForeignKey("media_file.id"), nullable=True
|
|
||||||
)
|
|
||||||
media_file: Mapped[MediaFile] = relationship(back_populates="media_actor_files")
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"MediaActorFile({self.id} {self.media_actor_id} {self.media_file_id})"
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f"{self.id} {self.media_actor_id} {self.media_file_id}"
|
|
||||||
|
|
||||||
|
|
||||||
class MediaArticle(Base, BaseMixin):
|
|
||||||
__tablename__ = "media_article"
|
|
||||||
review: Mapped[bool]
|
|
||||||
title: Mapped[str]
|
|
||||||
url: Mapped[str] = mapped_column(unique=True)
|
|
||||||
|
|
||||||
|
|
||||||
class MediaVideo(Base, BaseMixin):
|
|
||||||
"""
|
|
||||||
MediaFile represents video link.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__tablename__ = "media_video"
|
|
||||||
cloud_link: Mapped[str]
|
|
||||||
file_name: Mapped[str]
|
|
||||||
path: Mapped[str]
|
|
||||||
review: Mapped[bool]
|
|
||||||
title: Mapped[str]
|
|
||||||
url: Mapped[str] = mapped_column(unique=True)
|
|
||||||
should_download: Mapped[bool]
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"MediaFile({self.id} {self.title} {self.url})"
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.title is None:
|
|
||||||
return f"{self.url}({self.id})"
|
|
||||||
else:
|
|
||||||
return f"{self.title}({self.id})"
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
from typing import List
|
|
||||||
from sqlalchemy import ForeignKey, UniqueConstraint
|
|
||||||
from sqlalchemy.orm import relationship, mapped_column, Mapped
|
|
||||||
|
|
||||||
from src.db.models.base import Base, BaseMixin
|
|
||||||
|
|
||||||
|
|
||||||
class Sport(Base, BaseMixin):
|
|
||||||
__tablename__ = "sport"
|
|
||||||
__table_args__ = (
|
|
||||||
UniqueConstraint("name"),
|
|
||||||
)
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False, index=True, unique=True)
|
|
||||||
teams: Mapped[List["Team"]] = relationship(back_populates="sport")
|
|
||||||
positions: Mapped[List["FieldPosition"]] = relationship(back_populates="sport")
|
|
||||||
|
|
||||||
|
|
||||||
class Team(Base, BaseMixin):
|
|
||||||
__tablename__ = "team"
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False, index=True, unique=True)
|
|
||||||
short_name: Mapped[str] = mapped_column(nullable=False)
|
|
||||||
sport_id: Mapped[str] = mapped_column(ForeignKey("sport.id"), nullable=False)
|
|
||||||
sport: Mapped[Sport] = relationship(back_populates="teams")
|
|
||||||
roosters: Mapped[List["Rooster"]] = relationship(back_populates="team")
|
|
||||||
|
|
||||||
|
|
||||||
class FieldPosition(Base, BaseMixin):
|
|
||||||
__tablename__ = "field_position"
|
|
||||||
__table_args__ = (
|
|
||||||
UniqueConstraint("name", "sport_id"),
|
|
||||||
UniqueConstraint("short_name", "sport_id"),
|
|
||||||
)
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False, index=True)
|
|
||||||
short_name: Mapped[str] = mapped_column(nullable=False)
|
|
||||||
sport_id: Mapped[str] = mapped_column(ForeignKey("sport.id"), nullable=False, index=True)
|
|
||||||
sport: Mapped[Sport] = relationship(back_populates="positions")
|
|
||||||
roosters: Mapped[List["Rooster"]] = relationship(back_populates="position")
|
|
||||||
|
|
||||||
|
|
||||||
class Player(Base, BaseMixin):
|
|
||||||
__tablename__ = "player"
|
|
||||||
__table_args__ = (
|
|
||||||
UniqueConstraint("first_name", "last_name"),
|
|
||||||
)
|
|
||||||
first_name: Mapped[str] = mapped_column(nullable=False, index=True)
|
|
||||||
last_name: Mapped[str] = mapped_column(nullable=False, index=True)
|
|
||||||
roosters: Mapped[List["Rooster"]] = relationship(back_populates="player")
|
|
||||||
|
|
||||||
def get_full_name(self) -> str:
|
|
||||||
return f"{self.last_name}, {self.first_name}"
|
|
||||||
|
|
||||||
|
|
||||||
class Rooster(Base, BaseMixin):
|
|
||||||
__tablename__ = "rooster"
|
|
||||||
__table_args__ = (
|
|
||||||
UniqueConstraint("year", "team_id", "player_id", "position_id"),
|
|
||||||
)
|
|
||||||
year: Mapped[int]
|
|
||||||
team_id: Mapped[str] = mapped_column(ForeignKey("team.id"), nullable=False, index=True)
|
|
||||||
team: Mapped[Team] = relationship(back_populates="roosters")
|
|
||||||
player_id: Mapped[str] = mapped_column(ForeignKey("player.id"), nullable=False, index=True)
|
|
||||||
player: Mapped[Player] = relationship(back_populates="roosters")
|
|
||||||
position_id: Mapped[str] = mapped_column(ForeignKey("field_position.id"), nullable=False, index=True)
|
|
||||||
position: Mapped[FieldPosition] = relationship(back_populates="roosters")
|
|
||||||
cards: Mapped[List["Card"]] = relationship(back_populates="rooster")
|
|
||||||
|
|
||||||
|
|
||||||
class Vendor(Base, BaseMixin):
|
|
||||||
__tablename__ = "vendor"
|
|
||||||
name: Mapped[str] = mapped_column(nullable=False, unique=True, index=True)
|
|
||||||
card_sets: Mapped[List["CardSet"]] = relationship(back_populates="vendor")
|
|
||||||
cards: Mapped[List["Card"]] = relationship(back_populates="vendor")
|
|
||||||
|
|
||||||
|
|
||||||
class CardSet(Base, BaseMixin):
|
|
||||||
__tablename__ = "card_set"
|
|
||||||
__table_args__ = (
|
|
||||||
UniqueConstraint("name", "vendor_id"),
|
|
||||||
)
|
|
||||||
name: Mapped[str] = mapped_column(index=True)
|
|
||||||
parallel_set: Mapped[bool]
|
|
||||||
insert_set: Mapped[bool]
|
|
||||||
vendor_id: Mapped[str] = mapped_column(ForeignKey("vendor.id"), nullable=False, index=True)
|
|
||||||
vendor: Mapped[Vendor] = relationship(back_populates="card_sets")
|
|
||||||
cards: Mapped[List["Card"]] = relationship(back_populates="card_set")
|
|
||||||
|
|
||||||
|
|
||||||
class Card(Base, BaseMixin):
|
|
||||||
__tablename__ = "card"
|
|
||||||
__table_args__ = (
|
|
||||||
UniqueConstraint("card_number", "year", "vendor_id", "card_set_id"),
|
|
||||||
)
|
|
||||||
card_number: Mapped[int] = mapped_column(index=True)
|
|
||||||
year: Mapped[int] = mapped_column(index=True)
|
|
||||||
card_set_id: Mapped[str] = mapped_column(ForeignKey("card_set.id"), nullable=False)
|
|
||||||
card_set: Mapped[CardSet] = relationship(back_populates="cards")
|
|
||||||
rooster_id: Mapped[str] = mapped_column(ForeignKey("rooster.id"), nullable=False)
|
|
||||||
rooster: Mapped[Rooster] = relationship(back_populates="cards")
|
|
||||||
vendor_id: Mapped[str] = mapped_column(ForeignKey("vendor.id"), nullable=False)
|
|
||||||
vendor: Mapped[Vendor] = relationship(back_populates="cards")
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
from typing import List
|
|
||||||
|
|
||||||
from src.db.models.comic import Publisher
|
|
||||||
from src.schema.comics.comic import ComicResponse
|
|
||||||
from src.schema.comics.publisher import PublisherResponse
|
|
||||||
from src.schema.comics.publisher_details import PublisherDetailsResponse
|
|
||||||
|
|
||||||
|
|
||||||
def get_publisher_details(publisher: Publisher) -> PublisherDetailsResponse:
|
|
||||||
imprints: List[PublisherResponse] = []
|
|
||||||
for imprint in publisher.imprints:
|
|
||||||
imprints.append(PublisherResponse(id=imprint.id, name=str(imprint.name)))
|
|
||||||
comics: List[ComicResponse] = []
|
|
||||||
for comic in publisher.comics:
|
|
||||||
comics.append(
|
|
||||||
ComicResponse(id=comic.id, title=comic.title, completed=comic.completed)
|
|
||||||
)
|
|
||||||
parent_publisher: PublisherResponse | None = None
|
|
||||||
if publisher.parent_publisher:
|
|
||||||
parent_publisher = PublisherResponse(id=publisher.parent_publisher.id, name=str(publisher.parent_publisher.name))
|
|
||||||
response: PublisherDetailsResponse = PublisherDetailsResponse(
|
|
||||||
id=publisher.id, name=str(publisher.name), parent_publisher=parent_publisher, imprints=imprints, comics=comics
|
|
||||||
)
|
|
||||||
return response
|
|
||||||
@@ -2,10 +2,10 @@ from datetime import datetime
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
import uuid
|
import uuid
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.db.models.admin import Assignment, Profile
|
from kontor_model.db.models.admin import Assignment, Profile
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.schema.user.profile import ProfileModel
|
from kontor_model.schema.user.profile import ProfileModel
|
||||||
|
|
||||||
|
|
||||||
def create_new_profile(new_profile: ProfileModel, db: Session) -> Profile:
|
def create_new_profile(new_profile: ProfileModel, db: Session) -> Profile:
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from src.apis.version1.admin.login import login_router
|
|||||||
from src.core.config import settings
|
from src.core.config import settings
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.core.middleware import RequestLoggingMiddleware
|
from src.core.middleware import RequestLoggingMiddleware
|
||||||
from src.db.models.base import Base
|
from kontor_model.db.models.base import Base
|
||||||
from src.db.session import engine
|
from src.db.session import engine
|
||||||
from src.db.utils import check_db_connected, check_db_disconnected
|
from src.db.utils import check_db_connected, check_db_disconnected
|
||||||
from src.webapps.base import api_router as web_app_router
|
from src.webapps.base import api_router as web_app_router
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{% extends "shared/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
<title>Add a Lofi Link</title>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="text-danger font-weight-bold">
|
||||||
|
{% for error in errors %}
|
||||||
|
<li>{{error}}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row my-5">
|
||||||
|
<h3 class="text-center display-4">Add a Lofi Link</h3>
|
||||||
|
<form method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<input type="text" required class="form-control" name="url" value="{{url}}" placeholder="Lofi Link here">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
{% extends "shared/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
<title>MediaLofi Detail</title>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h1 class="display-5">MediaLofi Detail</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">MediaLofi Title</th>
|
||||||
|
<td colspan="2">{{medialofi.title}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">MediaLofi URL</th>
|
||||||
|
<td colspan="2">{{medialofi.url}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">MediaLofi Download?</th>
|
||||||
|
<td colspan="2">{{medialofi.should_download}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">MediaLofi Review?</th>
|
||||||
|
<td colspan="2">{{medialofi.review}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Data Created</th>
|
||||||
|
<td colspan="2">{{medialofi.created_date}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Data Modified</th>
|
||||||
|
<td colspan="2">{{medialofi.last_modified_date}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Data Version</th>
|
||||||
|
<td colspan="2">{{medialofi.version}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{% extends "shared/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
<title>Lofi Links</title>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% with msg=msg %}
|
||||||
|
{% include "components/alerts.html" %}
|
||||||
|
{% endwith %}
|
||||||
|
<div class="container">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead><tr>
|
||||||
|
<th scope="col">Titel</th>
|
||||||
|
<th scope="col">Review</th>
|
||||||
|
<th scope="col">Download</th>
|
||||||
|
</tr></thead>
|
||||||
|
<tbody>
|
||||||
|
{% for medialofi in medialofis %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><a href="/media/lofi/{{medialofi.id}}">{{medialofi.title}}</a></th>
|
||||||
|
<td>{% with check=medialofi.review %}{% include "components/check.html" %}{% endwith %}</td>
|
||||||
|
<td>{% with check=medialofi.should_download %}{% include "components/check.html" %}{% endwith %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -2,4 +2,5 @@
|
|||||||
<a href="/media/files/">MediaFiles</a>
|
<a href="/media/files/">MediaFiles</a>
|
||||||
<a href="/media/actors/">MediaActors</a>
|
<a href="/media/actors/">MediaActors</a>
|
||||||
<a href="/media/videos/">MediaVideos</a>
|
<a href="/media/videos/">MediaVideos</a>
|
||||||
|
<a href="/media/lofi/">MediaLofi</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from typing import Optional
|
|||||||
from fastapi import APIRouter, Request
|
from fastapi import APIRouter, Request
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
from src.db.models.admin import Permission, Profile
|
from kontor_model.db.models.admin import Permission, Profile
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
|
|
||||||
templates = Jinja2Templates(directory="src/templates")
|
templates = Jinja2Templates(directory="src/templates")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from fastapi.templating import Jinja2Templates
|
|||||||
from src.webapps.admin import route_admin
|
from src.webapps.admin import route_admin
|
||||||
from src.webapps.auth import route_login
|
from src.webapps.auth import route_login
|
||||||
from src.webapps.comic import route_comics, route_worktype, route_artists
|
from src.webapps.comic import route_comics, route_worktype, route_artists
|
||||||
from src.webapps.media import route_actors, route_media, route_videos
|
from src.webapps.media import route_actors, route_lofi, route_media, route_videos
|
||||||
|
|
||||||
templates = Jinja2Templates(directory="src/templates")
|
templates = Jinja2Templates(directory="src/templates")
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@ api_router.include_router(route_worktype.router, tags=["webapp"])
|
|||||||
api_router.include_router(route_media.router, tags=["webapp"])
|
api_router.include_router(route_media.router, tags=["webapp"])
|
||||||
api_router.include_router(route_actors.router, tags=["webapp"])
|
api_router.include_router(route_actors.router, tags=["webapp"])
|
||||||
api_router.include_router(route_videos.router, tags=["webapp"])
|
api_router.include_router(route_videos.router, tags=["webapp"])
|
||||||
|
api_router.include_router(route_lofi.router, tags=["webapp"])
|
||||||
api_router.include_router(route_login.router, tags=["webapp"])
|
api_router.include_router(route_login.router, tags=["webapp"])
|
||||||
api_router.include_router(route_admin.router, tags=["webapp"])
|
api_router.include_router(route_admin.router, tags=["webapp"])
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ from fastapi import APIRouter, Request, status, Form
|
|||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from fastapi.responses import RedirectResponse
|
from fastapi.responses import RedirectResponse
|
||||||
|
|
||||||
from src.db.models.comic import Artist
|
from kontor_model.db.models.comic import Artist
|
||||||
from typing import AnyStr
|
from typing import AnyStr
|
||||||
|
|
||||||
from src.db.repository.comics.artist import update_artist
|
from kontor_model.db.repository.comics.artist import update_artist
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
#from src.db.repository.comic import create_new_worktype, update_worktype
|
#from src.db.repository.comic import create_new_worktype, update_worktype
|
||||||
from src.main import logger
|
from kontor_model.schema.comics.artist import AddArtist
|
||||||
from src.schema.comics.artist import AddArtist
|
|
||||||
from src.webapps.comic.forms.artist import AddArtistForm
|
from src.webapps.comic.forms.artist import AddArtistForm
|
||||||
|
|
||||||
#from src.schema.comics.worktype import AddWorkType
|
#from src.schema.comics.worktype import AddWorkType
|
||||||
@@ -35,7 +34,7 @@ def edit_artist(db: SessionDep, request: Request, artist_id: str):
|
|||||||
return templates.TemplateResponse("comic/artist_edit.html", {"request": request, "artist_name": artist.name, "artist_link": artist.weblink})
|
return templates.TemplateResponse("comic/artist_edit.html", {"request": request, "artist_name": artist.name, "artist_link": artist.weblink})
|
||||||
|
|
||||||
@router.post("/artist/edit/{artist_id}")
|
@router.post("/artist/edit/{artist_id}")
|
||||||
async def edit_artist(request: Request, db: SessionDep, artist_id: str, action: str = Form(...), artist_name: str = Form(...), artist_link: str = Form(...)):
|
async def edit_artist_post(request: Request, db: SessionDep, artist_id: str, action: str = Form(...), artist_name: str = Form(...), artist_link: str = Form(...)):
|
||||||
if action == "cancel":
|
if action == "cancel":
|
||||||
return RedirectResponse(f"/comic/artists/{artist_id}", status_code=status.HTTP_303_SEE_OTHER)
|
return RedirectResponse(f"/comic/artists/{artist_id}", status_code=status.HTTP_303_SEE_OTHER)
|
||||||
form = AddArtistForm(request, artist_id, artist_name, artist_link)
|
form = AddArtistForm(request, artist_id, artist_name, artist_link)
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ from fastapi import APIRouter, Form, Request, status
|
|||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from fastapi.responses import RedirectResponse
|
from fastapi.responses import RedirectResponse
|
||||||
|
|
||||||
from src.db.models.comic import Comic, Publisher, Issue
|
from kontor_model.db.models.comic import Comic, Publisher, Issue
|
||||||
from typing import AnyStr
|
from typing import AnyStr
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.db.repository.comics.comic import update_comic
|
from kontor_model.db.repository.comics.comic import update_comic
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.schema.comics.comic import ComicSchema
|
from kontor_model.schema.comics.comic import ComicSchema
|
||||||
from src.webapps.comic.forms.comic import ValidateComicForm
|
from src.webapps.comic.forms.comic import ValidateComicForm
|
||||||
|
|
||||||
templates = Jinja2Templates(directory="src/templates")
|
templates = Jinja2Templates(directory="src/templates")
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ from fastapi import APIRouter, Request, status
|
|||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from fastapi.responses import RedirectResponse
|
from fastapi.responses import RedirectResponse
|
||||||
|
|
||||||
from src.db.models.comic import WorkType
|
from kontor_model.db.models.comic import WorkType
|
||||||
from typing import AnyStr
|
from typing import AnyStr
|
||||||
|
|
||||||
from src.db.repository.comics.worktype import create_new_worktype, update_worktype
|
from kontor_model.db.repository.comics.worktype import create_new_worktype, update_worktype
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.main import logger
|
from src.main import logger
|
||||||
from src.schema.comics.worktype import AddWorkType
|
from kontor_model.schema.comics.worktype import AddWorkType
|
||||||
from src.webapps.comic.forms.worktype import AddWorktypeForm
|
from src.webapps.comic.forms.worktype import AddWorktypeForm
|
||||||
|
|
||||||
templates = Jinja2Templates(directory="src/templates")
|
templates = Jinja2Templates(directory="src/templates")
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from typing import AnyStr
|
|||||||
|
|
||||||
from fastapi import APIRouter, Request
|
from fastapi import APIRouter, Request
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from src.db.models.media import MediaActor
|
from kontor_model.db.models.media import MediaActor
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
|
|
||||||
templates = Jinja2Templates(directory="src/templates")
|
templates = Jinja2Templates(directory="src/templates")
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Request, status, responses
|
||||||
|
from fastapi.security.utils import get_authorization_scheme_param
|
||||||
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
|
from src.core.security import get_current_user_from_token
|
||||||
|
from kontor_model.db.models.media import MediaLofi
|
||||||
|
from kontor_model.db.models.admin import Profile
|
||||||
|
from kontor_model.db.repository.media.lofi import create_new_lofi
|
||||||
|
from src.db.session import SessionDep
|
||||||
|
from src.webapps.media.forms import AddLinkForm
|
||||||
|
|
||||||
|
templates = Jinja2Templates(directory="src/templates")
|
||||||
|
router = APIRouter(include_in_schema=False, prefix="/media")
|
||||||
|
|
||||||
|
@router.get("/lofi")
|
||||||
|
def get_medialofis(db: SessionDep, request: Request, msg: Optional[str] = None):
|
||||||
|
medialofis = db.query(MediaLofi).all()
|
||||||
|
try:
|
||||||
|
token = request.cookies.get("access_token")
|
||||||
|
_, param = get_authorization_scheme_param(token) # scheme will hold "Bearer" and param will hold actual token value
|
||||||
|
current_user: Profile = get_current_user_from_token(token=param)
|
||||||
|
return templates.TemplateResponse("media/lofi_list.html", {"request": request, "msg": msg, "user": current_user, "medialofis": medialofis})
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return templates.TemplateResponse("media/lofi_list.html", {"request": request, "msg": msg, "user": None, "medialofis": medialofis})
|
||||||
|
|
||||||
|
@router.get("/lofi/{lofi_id}")
|
||||||
|
def lofi_details(lofi_id: str, request: Request, db: SessionDep):
|
||||||
|
medialofi = db.get(MediaLofi, lofi_id)
|
||||||
|
return templates.TemplateResponse("media/lofi_detail.html", {"request": request, "medialofi":medialofi})
|
||||||
|
|
||||||
|
@router.get("/add-lofi")
|
||||||
|
def add_lofi_link(request: Request, db: SessionDep):
|
||||||
|
return templates.TemplateResponse("media/add_lofi_link.html", {"request": request})
|
||||||
|
|
||||||
|
@router.post("/add-lofi")
|
||||||
|
async def post_lofi_link(request: Request, db: SessionDep):
|
||||||
|
form = AddLinkForm(request)
|
||||||
|
await form.load_data()
|
||||||
|
if form.is_valid():
|
||||||
|
try:
|
||||||
|
#video = AddLink(**form.__dict__)
|
||||||
|
medialofi = create_new_lofi(url=str(form.url), db=db)
|
||||||
|
return responses.RedirectResponse(f"media/lofi/{medialofi.id}", status_code=status.HTTP_302_FOUND)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
form.__dict__.get("errors").append("Link already added")
|
||||||
|
return templates.TemplateResponse("media/add_lofi_link.html", form.__dict__)
|
||||||
|
return templates.TemplateResponse("media/add_lofi_link.html", form.__dict__)
|
||||||
@@ -6,8 +6,8 @@ from fastapi.templating import Jinja2Templates
|
|||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
|
|
||||||
from src.core.security import get_current_user_from_token
|
from src.core.security import get_current_user_from_token
|
||||||
from src.db.models.admin import Profile
|
from kontor_model.db.models.admin import Profile
|
||||||
from src.db.models.media import MediaFile
|
from kontor_model.db.models.media import MediaFile
|
||||||
from src.core.log_conf import logger
|
from src.core.log_conf import logger
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ def get_mediafiles(db: SessionDep, request: Request, msg: str | None = None):
|
|||||||
try:
|
try:
|
||||||
token = request.cookies.get("access_token")
|
token = request.cookies.get("access_token")
|
||||||
scheme, param = get_authorization_scheme_param(token) # scheme will hold "Bearer" and param will hold actual token value
|
scheme, param = get_authorization_scheme_param(token) # scheme will hold "Bearer" and param will hold actual token value
|
||||||
current_user: Profile = get_current_user_from_token(token=param)
|
#current_user: Profile = get_current_user_from_token(token=param)
|
||||||
return templates.TemplateResponse("media/files.html", {"request": request, "msg": msg, "mediafiles": mediafiles})
|
return templates.TemplateResponse("media/files.html", {"request": request, "msg": msg, "mediafiles": mediafiles})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
from fastapi import APIRouter, Request, status, responses
|
from fastapi import APIRouter, Request, status, responses
|
||||||
from fastapi.security.utils import get_authorization_scheme_param
|
from fastapi.security.utils import get_authorization_scheme_param
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
from src.core.security import get_current_user_from_token
|
from src.core.security import get_current_user_from_token
|
||||||
from src.db.models.media import MediaVideo
|
from kontor_model.db.models.media import MediaVideo
|
||||||
from src.db.models.admin import Profile
|
from kontor_model.db.models.admin import Profile
|
||||||
from src.db.repository.media.video import create_new_video
|
from kontor_model.db.repository.media.video import create_new_video
|
||||||
from src.db.session import SessionDep
|
from src.db.session import SessionDep
|
||||||
from src.webapps.media.forms import AddLinkForm
|
from src.webapps.media.forms import AddLinkForm
|
||||||
|
|
||||||
@@ -13,12 +15,12 @@ templates = Jinja2Templates(directory="src/templates")
|
|||||||
router = APIRouter(include_in_schema=False, prefix="/media")
|
router = APIRouter(include_in_schema=False, prefix="/media")
|
||||||
|
|
||||||
@router.get("/videos")
|
@router.get("/videos")
|
||||||
def get_mediavideos(db: SessionDep, request: Request, msg: str = None):
|
def get_mediavideos(db: SessionDep, request: Request, msg: Optional[str] = None):
|
||||||
mediavideos = db.query(MediaVideo).all()
|
mediavideos = db.query(MediaVideo).all()
|
||||||
try:
|
try:
|
||||||
token = request.cookies.get("access_token")
|
token = request.cookies.get("access_token")
|
||||||
_, param = get_authorization_scheme_param(token) # scheme will hold "Bearer" and param will hold actual token value
|
_, param = get_authorization_scheme_param(token) # scheme will hold "Bearer" and param will hold actual token value
|
||||||
current_user: Profile = get_current_user_from_token(token=param, db=db)
|
current_user: Profile = get_current_user_from_token(token=param)
|
||||||
return templates.TemplateResponse("media/videos.html", {"request": request, "msg": msg, "user": current_user, "mediavideos": mediavideos})
|
return templates.TemplateResponse("media/videos.html", {"request": request, "msg": msg, "user": current_user, "mediavideos": mediavideos})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
@@ -40,7 +42,7 @@ async def post_video_link(request: Request, db: SessionDep):
|
|||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
try:
|
try:
|
||||||
#video = AddLink(**form.__dict__)
|
#video = AddLink(**form.__dict__)
|
||||||
mediavideo = create_new_video(video=form, db=db)
|
mediavideo = create_new_video(url=str(form.url), db=db)
|
||||||
return responses.RedirectResponse(f"media/videos/{mediavideo.id}", status_code=status.HTTP_302_FOUND)
|
return responses.RedirectResponse(f"media/videos/{mediavideo.id}", status_code=status.HTTP_302_FOUND)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from sqlalchemy import create_engine
|
|||||||
from sqlalchemy.orm import Session, sessionmaker
|
from sqlalchemy.orm import Session, sessionmaker
|
||||||
|
|
||||||
from src.apis.base import api_router
|
from src.apis.base import api_router
|
||||||
from src.db.models.base import Base
|
from kontor_model.db.models.base import Base
|
||||||
from src.db.session import get_db
|
from src.db.session import get_db
|
||||||
|
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|||||||
Generated
+1023
-560
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
# This file was generated by the Gradle 'init' task.
|
# This file was generated by the Gradle 'init' task.
|
||||||
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
|
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
|
||||||
description='Kontor Documentation'
|
description='Kontor Documentation'
|
||||||
version=0.3.0-SNAPSHOT
|
version=0.4.0-SNAPSHOT
|
||||||
group=de.thpeetz
|
group=de.thpeetz
|
||||||
org.gradle.configuration-cache=true
|
org.gradle.configuration-cache=true
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
3.13
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
[project]
|
||||||
|
name = "kontor_model"
|
||||||
|
version = "0.4.0"
|
||||||
|
description = "Kontor Model"
|
||||||
|
readme = "README.md"
|
||||||
|
authors = [
|
||||||
|
{ name = "Thomas Peetz", email = "thomas.peetz@cimt-ag.de" }
|
||||||
|
]
|
||||||
|
requires-python = ">=3.13"
|
||||||
|
dependencies = [
|
||||||
|
"sqlalchemy>=2.0.52",
|
||||||
|
"msgspec[toml,yaml]>=0.21.1",
|
||||||
|
"pydantic[email]>=2.13.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["uv_build>=0.9.27,<0.10.0"]
|
||||||
|
build-backend = "uv_build"
|
||||||
|
|
||||||
|
[[tool.uv.index]]
|
||||||
|
name = "nexus"
|
||||||
|
url = "https://nexus.thpeetz.de/repository/pypi-group/simple"
|
||||||
|
publish-url = "https://nexus.thpeetz.de/repository/pypi-internal/"
|
||||||
|
default = true
|
||||||
|
|
||||||
|
|
||||||
|
[[tool.uv.index]]
|
||||||
|
name = "nexus-proxy"
|
||||||
|
url = "https://nexus.thpeetz.de/repository/pypi-proxy/simple"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
def hello() -> str:
|
||||||
|
return "Hello from kontor-model!"
|
||||||
+7
-5
@@ -1,5 +1,5 @@
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
from db.models.admin import (
|
from kontor_model.db.models.admin import (
|
||||||
Assignment,
|
Assignment,
|
||||||
Token,
|
Token,
|
||||||
Profile,
|
Profile,
|
||||||
@@ -7,7 +7,7 @@ from db.models.admin import (
|
|||||||
MailAccount,
|
MailAccount,
|
||||||
Mail,
|
Mail,
|
||||||
)
|
)
|
||||||
from db.models.bookshelf import (
|
from kontor_model.db.models.bookshelf import (
|
||||||
ArticleAuthor,
|
ArticleAuthor,
|
||||||
BookAuthor,
|
BookAuthor,
|
||||||
BookshelfPublisher,
|
BookshelfPublisher,
|
||||||
@@ -15,7 +15,7 @@ from db.models.bookshelf import (
|
|||||||
Book,
|
Book,
|
||||||
Author,
|
Author,
|
||||||
)
|
)
|
||||||
from db.models.comic import (
|
from kontor_model.db.models.comic import (
|
||||||
Issue,
|
Issue,
|
||||||
StoryArc,
|
StoryArc,
|
||||||
TradePaperback,
|
TradePaperback,
|
||||||
@@ -27,14 +27,15 @@ from db.models.comic import (
|
|||||||
Publisher,
|
Publisher,
|
||||||
WorkType,
|
WorkType,
|
||||||
)
|
)
|
||||||
from db.models.media import (
|
from kontor_model.db.models.media import (
|
||||||
MediaFile,
|
MediaFile,
|
||||||
MediaActor,
|
MediaActor,
|
||||||
MediaActorFile,
|
MediaActorFile,
|
||||||
MediaArticle,
|
MediaArticle,
|
||||||
MediaVideo,
|
MediaVideo,
|
||||||
|
MediaLofi,
|
||||||
)
|
)
|
||||||
from db.models.tysc import (
|
from kontor_model.db.models.tysc import (
|
||||||
Card,
|
Card,
|
||||||
CardSet,
|
CardSet,
|
||||||
Rooster,
|
Rooster,
|
||||||
@@ -72,6 +73,7 @@ registry: Dict[str, Any] = {
|
|||||||
BookAuthor.__tablename__: BookAuthor,
|
BookAuthor.__tablename__: BookAuthor,
|
||||||
MediaArticle.__tablename__: MediaArticle,
|
MediaArticle.__tablename__: MediaArticle,
|
||||||
MediaVideo.__tablename__: MediaVideo,
|
MediaVideo.__tablename__: MediaVideo,
|
||||||
|
MediaLofi.__tablename__: MediaLofi,
|
||||||
MediaFile.__tablename__: MediaFile,
|
MediaFile.__tablename__: MediaFile,
|
||||||
MediaActor.__tablename__: MediaActor,
|
MediaActor.__tablename__: MediaActor,
|
||||||
MediaActorFile.__tablename__: MediaActorFile,
|
MediaActorFile.__tablename__: MediaActorFile,
|
||||||
+1
-1
@@ -4,7 +4,7 @@ from typing import Any, Dict
|
|||||||
from sqlalchemy import Column, ForeignKey, Integer, String, Boolean
|
from sqlalchemy import Column, ForeignKey, Integer, String, Boolean
|
||||||
from sqlalchemy.orm import relationship, mapped_column, Mapped
|
from sqlalchemy.orm import relationship, mapped_column, Mapped
|
||||||
|
|
||||||
from db.models.base import Base, BaseMixin
|
from kontor_model.db.models.base import Base, BaseMixin
|
||||||
|
|
||||||
|
|
||||||
class Profile(Base, BaseMixin):
|
class Profile(Base, BaseMixin):
|
||||||
+2
-2
@@ -2,7 +2,7 @@ from typing import Any, Dict
|
|||||||
from sqlalchemy import Column, ForeignKey, Integer, String
|
from sqlalchemy import Column, ForeignKey, Integer, String
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
from db.models.base import Base, BaseMixin
|
from kontor_model.db.models.base import Base, BaseMixin
|
||||||
|
|
||||||
|
|
||||||
class Article(Base, BaseMixin):
|
class Article(Base, BaseMixin):
|
||||||
@@ -56,7 +56,7 @@ class Author(Base, BaseMixin):
|
|||||||
class BookshelfPublisher(Base, BaseMixin):
|
class BookshelfPublisher(Base, BaseMixin):
|
||||||
__tablename__ = 'bookshelf_publisher'
|
__tablename__ = 'bookshelf_publisher'
|
||||||
name = Column(String, unique=True)
|
name = Column(String, unique=True)
|
||||||
books = relationship("Book")
|
books = relationship("Book", back_populates="publisher")
|
||||||
|
|
||||||
def import_dict(self, import_data: Dict[str, Any]):
|
def import_dict(self, import_data: Dict[str, Any]):
|
||||||
self.id = import_data['id']
|
self.id = import_data['id']
|
||||||
+1
-1
@@ -4,7 +4,7 @@ from typing import Dict, List, Optional, Any
|
|||||||
from sqlalchemy import Column, ForeignKey, Integer, String, Boolean, func
|
from sqlalchemy import Column, ForeignKey, Integer, String, Boolean, func
|
||||||
from sqlalchemy.orm import relationship, Mapped, mapped_column
|
from sqlalchemy.orm import relationship, Mapped, mapped_column
|
||||||
|
|
||||||
from db.models.base import Base, BaseMixin
|
from kontor_model.db.models.base import Base, BaseMixin
|
||||||
|
|
||||||
|
|
||||||
class Publisher(Base):
|
class Publisher(Base):
|
||||||
+36
-53
@@ -1,14 +1,8 @@
|
|||||||
import re
|
|
||||||
import subprocess
|
|
||||||
from datetime import datetime
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
import requests
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
from sqlalchemy import Boolean, Column, String, ForeignKey
|
from sqlalchemy import Boolean, Column, String, ForeignKey
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
from db.models.base import Base, BaseMixin, BaseVideoMixin
|
from kontor_model.db.models.base import Base, BaseMixin, BaseVideoMixin
|
||||||
|
|
||||||
|
|
||||||
class MediaFile(Base, BaseMixin, BaseVideoMixin):
|
class MediaFile(Base, BaseMixin, BaseVideoMixin):
|
||||||
@@ -21,6 +15,9 @@ class MediaFile(Base, BaseMixin, BaseVideoMixin):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'{self.title}({self.id})'
|
return f'{self.title}({self.id})'
|
||||||
|
|
||||||
|
def update_title(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def import_dict(self, import_data: Dict[str, Any]):
|
def import_dict(self, import_data: Dict[str, Any]):
|
||||||
self.id = import_data['id']
|
self.id = import_data['id']
|
||||||
self.created_date = import_data['created_date']
|
self.created_date = import_data['created_date']
|
||||||
@@ -49,52 +46,6 @@ class MediaFile(Base, BaseMixin, BaseVideoMixin):
|
|||||||
item['should_download'] = self.should_download
|
item['should_download'] = self.should_download
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def update_title(self) -> None:
|
|
||||||
print(f"update title for {self.url}")
|
|
||||||
try:
|
|
||||||
r = requests.get(self.url)
|
|
||||||
soup = BeautifulSoup(r.content, "html.parser")
|
|
||||||
title_tag = soup.find('title')
|
|
||||||
if title_tag:
|
|
||||||
self.title = title_tag.get_text()
|
|
||||||
self.review = False
|
|
||||||
except:
|
|
||||||
self.title = None
|
|
||||||
self.review = True
|
|
||||||
self.last_modified_date = datetime.now()
|
|
||||||
|
|
||||||
def download_file(self, download_dir: str, dl_tool: str):
|
|
||||||
print(f"download file for {self.url} to {download_dir}")
|
|
||||||
result = subprocess.run([dl_tool, self.url], cwd=download_dir, capture_output=True, text=True)
|
|
||||||
if result.returncode == 0:
|
|
||||||
output = result.stdout
|
|
||||||
output = re.sub(' +', ' ', output)
|
|
||||||
lines_list = output.splitlines()
|
|
||||||
file_name = self.__parse_output__(lines_list)
|
|
||||||
if file_name is None:
|
|
||||||
self.review = True
|
|
||||||
self.should_download = True
|
|
||||||
self.file_name = None
|
|
||||||
else:
|
|
||||||
download_file = Path(file_name)
|
|
||||||
self.should_download = False
|
|
||||||
self.file_name = download_file.name
|
|
||||||
self.cloud_link = str(download_file.absolute())
|
|
||||||
self.last_modified_date = datetime.now()
|
|
||||||
|
|
||||||
def __parse_output__(self, lines_list):
|
|
||||||
self.file_name = None
|
|
||||||
for line in lines_list:
|
|
||||||
if 'has already been downloaded' in line:
|
|
||||||
end_len = len(' has already been downloaded')
|
|
||||||
self.file_name = line[11:-end_len]
|
|
||||||
if 'Destination' in line:
|
|
||||||
line_len = len(line)
|
|
||||||
start_len = len('[download] Destination: ')
|
|
||||||
file_len = line_len - start_len
|
|
||||||
self.file_name = line[-file_len:]
|
|
||||||
return self.file_name
|
|
||||||
|
|
||||||
|
|
||||||
class MediaActor(Base, BaseMixin):
|
class MediaActor(Base, BaseMixin):
|
||||||
__tablename__ = 'media_actor'
|
__tablename__ = 'media_actor'
|
||||||
@@ -222,3 +173,35 @@ class MediaVideo(Base, BaseMixin):
|
|||||||
item['url'] = self.url
|
item['url'] = self.url
|
||||||
item['should_download'] = self.should_download
|
item['should_download'] = self.should_download
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
class MediaLofi(Base, BaseMixin):
|
||||||
|
__tablename__ = 'media_lofi'
|
||||||
|
file_name = Column(String)
|
||||||
|
review = Column(Boolean)
|
||||||
|
should_download = Column(Boolean)
|
||||||
|
title = Column(String)
|
||||||
|
url = Column(String, unique=True)
|
||||||
|
|
||||||
|
def import_dict(self, import_data: Dict[str, Any]):
|
||||||
|
self.id = import_data['id']
|
||||||
|
self.created_date = import_data['created_date']
|
||||||
|
self.last_modified_date = import_data['last_modified_date']
|
||||||
|
self.version = import_data['version']
|
||||||
|
self.file_name = import_data['file_name']
|
||||||
|
self.review = import_data['review']
|
||||||
|
self.should_download = import_data['should_download']
|
||||||
|
self.title = import_data['title']
|
||||||
|
self.url = import_data['url']
|
||||||
|
|
||||||
|
def export_dict(self) -> Dict[str, Any]:
|
||||||
|
item: Dict[str, Any] = {}
|
||||||
|
item['id'] = self.id
|
||||||
|
item['created_date'] = str(self.created_date)
|
||||||
|
item['last_modified_date'] = str(self.last_modified_date)
|
||||||
|
item['version'] = self.version
|
||||||
|
item['file_name'] = self.file_name
|
||||||
|
item['review'] = self.review
|
||||||
|
item['should_download'] = self.should_download
|
||||||
|
item['title'] = self.title
|
||||||
|
item['url'] = self.url
|
||||||
|
return item
|
||||||
@@ -2,7 +2,7 @@ from typing import Dict, Any
|
|||||||
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Boolean
|
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Boolean
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
from db.models.base import Base, BaseMixin
|
from kontor_model.db.models.base import Base, BaseMixin
|
||||||
|
|
||||||
|
|
||||||
class Sport(Base, BaseMixin):
|
class Sport(Base, BaseMixin):
|
||||||
+1
-1
@@ -2,7 +2,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.db.models.admin import Profile
|
from kontor_model.db.models.admin import Profile
|
||||||
|
|
||||||
|
|
||||||
def get_profile_by_username(username: str, db: Session) -> Optional[Profile]:
|
def get_profile_by_username(username: str, db: Session) -> Optional[Profile]:
|
||||||
+16
-9
@@ -1,14 +1,12 @@
|
|||||||
import uuid
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.core.log_conf import logger
|
from kontor_model.db.models.comic import Artist
|
||||||
from src.db.models.comic import Artist
|
from kontor_model.schema.comics.artist import AddArtist
|
||||||
from src.schema.comics.artist import AddArtist
|
from kontor_model.schema.comics.artist_details import ArtistDetailResponse, ArtistWorktypeComicResponse, ArtistWorktypeIssueResponse
|
||||||
from src.schema.comics.artist_details import ArtistDetailResponse, ArtistWorktypeComicResponse, ArtistWorktypeIssueResponse
|
from kontor_model.schema.comics.comic import ComicResponse
|
||||||
from src.schema.comics.comic import ComicResponse
|
from kontor_model.schema.comics.worktype import WorktypeResponse
|
||||||
from src.schema.comics.worktype import WorktypeResponse
|
|
||||||
|
|
||||||
|
|
||||||
def get_artist_details(artist: Artist) -> ArtistDetailResponse:
|
def get_artist_details(artist: Artist) -> ArtistDetailResponse:
|
||||||
@@ -17,7 +15,17 @@ def get_artist_details(artist: Artist) -> ArtistDetailResponse:
|
|||||||
for work in artist.comic_works:
|
for work in artist.comic_works:
|
||||||
worktype_id = work.work_type.id
|
worktype_id = work.work_type.id
|
||||||
if worktype_id in comic_works_map:
|
if worktype_id in comic_works_map:
|
||||||
comic = ComicResponse(id=work.comic.id, title=work.comic.title, completed=work.comic.completed)
|
comic = ComicResponse(
|
||||||
|
id=work.comic.id,
|
||||||
|
created_date=work.comic.created_date,
|
||||||
|
last_modified_date=work.comic.last_modified_date,
|
||||||
|
version=work.comic.version,
|
||||||
|
publisher_id=work.comic.publisher_id,
|
||||||
|
current_order=work.comic.current_order,
|
||||||
|
weblink=work.comic.weblink,
|
||||||
|
title=work.comic.title,
|
||||||
|
completed=work.comic.completed
|
||||||
|
)
|
||||||
comic_works_map[worktype_id].comics.append(comic)
|
comic_works_map[worktype_id].comics.append(comic)
|
||||||
else:
|
else:
|
||||||
comic_works_map[worktype_id] = ArtistWorktypeComicResponse(
|
comic_works_map[worktype_id] = ArtistWorktypeComicResponse(
|
||||||
@@ -37,7 +45,6 @@ def get_artist_details(artist: Artist) -> ArtistDetailResponse:
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
def update_artist(add_artist: AddArtist, artist_id: str, db: Session) -> Optional[Artist]:
|
def update_artist(add_artist: AddArtist, artist_id: str, db: Session) -> Optional[Artist]:
|
||||||
logger.info("update artist")
|
|
||||||
artist: Optional[Artist] = db.get(Artist, artist_id)
|
artist: Optional[Artist] = db.get(Artist, artist_id)
|
||||||
if artist is not None:
|
if artist is not None:
|
||||||
artist.name = add_artist.name
|
artist.name = add_artist.name
|
||||||
+9
-12
@@ -2,16 +2,15 @@ from typing import Dict, List, Optional
|
|||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.core.log_conf import logger
|
from kontor_model.db.models.comic import Comic, Issue
|
||||||
from src.db.models.comic import Comic, Issue
|
from kontor_model.schema.comics.artist import artist_to_response
|
||||||
from src.schema.comics.artist import artist_to_response
|
from kontor_model.schema.comics.comic import ComicSchema, comic_to_response
|
||||||
from src.schema.comics.comic import ComicSchema, comic_to_response
|
from kontor_model.schema.comics.comic_details import ComicDetailsResponse, ComicWorktypeArtistResponse
|
||||||
from src.schema.comics.comic_details import ComicDetailsResponse, ComicWorktypeArtistResponse
|
from kontor_model.schema.comics.issue import IssueResponse, issue_to_response
|
||||||
from src.schema.comics.issue import IssueResponse, issue_to_response
|
from kontor_model.schema.comics.issue_details import IssueDetailsResponse
|
||||||
from src.schema.comics.issue_details import IssueDetailsResponse
|
from kontor_model.schema.comics.publisher import publisher_to_response
|
||||||
from src.schema.comics.publisher import publisher_to_response
|
from kontor_model.schema.comics.volume import VolumeResponse, volume_to_response
|
||||||
from src.schema.comics.volume import VolumeResponse, volume_to_response
|
from kontor_model.schema.comics.worktype import worktype_to_response
|
||||||
from src.schema.comics.worktype import worktype_to_response
|
|
||||||
|
|
||||||
|
|
||||||
def get_issue_details(issue: Issue) -> IssueDetailsResponse:
|
def get_issue_details(issue: Issue) -> IssueDetailsResponse:
|
||||||
@@ -30,7 +29,6 @@ def get_issue_details(issue: Issue) -> IssueDetailsResponse:
|
|||||||
|
|
||||||
|
|
||||||
def update_comic(new_comic: ComicSchema, comic_id: str, db: Session) -> Optional[Comic]:
|
def update_comic(new_comic: ComicSchema, comic_id: str, db: Session) -> Optional[Comic]:
|
||||||
logger.info(f"update_comic: {new_comic} with {comic_id}")
|
|
||||||
comic: Optional[Comic] = db.get(Comic, comic_id)
|
comic: Optional[Comic] = db.get(Comic, comic_id)
|
||||||
return comic
|
return comic
|
||||||
|
|
||||||
@@ -48,7 +46,6 @@ def get_comic_details(comic: Comic) -> ComicDetailsResponse:
|
|||||||
if worktype_id in works_map:
|
if worktype_id in works_map:
|
||||||
artist = artist_to_response(work.artist)
|
artist = artist_to_response(work.artist)
|
||||||
works_map[worktype_id].artists.append(artist)
|
works_map[worktype_id].artists.append(artist)
|
||||||
logger.info(f"add artist to response map: {artist} -> {works_map}")
|
|
||||||
print(f"add artist to response map: {artist} -> {works_map}")
|
print(f"add artist to response map: {artist} -> {works_map}")
|
||||||
else:
|
else:
|
||||||
works_map[worktype_id] = ComicWorktypeArtistResponse(
|
works_map[worktype_id] = ComicWorktypeArtistResponse(
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from kontor_model.db.models.comic import Publisher
|
||||||
|
from kontor_model.schema.comics.comic import ComicResponse
|
||||||
|
from kontor_model.schema.comics.publisher import PublisherResponse
|
||||||
|
from kontor_model.schema.comics.publisher_details import PublisherDetailsResponse
|
||||||
|
|
||||||
|
|
||||||
|
def get_publisher_details(publisher: Publisher) -> PublisherDetailsResponse:
|
||||||
|
imprints: List[PublisherResponse] = []
|
||||||
|
for imprint in publisher.imprints:
|
||||||
|
imprints.append(
|
||||||
|
PublisherResponse(
|
||||||
|
id=imprint.id,
|
||||||
|
created_date=imprint.created_date,
|
||||||
|
last_modified_date=imprint.last_modified_date,
|
||||||
|
version=imprint.version,
|
||||||
|
weblink=str(imprint.weblink),
|
||||||
|
parent_publisher_id=imprint.parent_publisher_id,
|
||||||
|
name=str(imprint.name)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
comics: List[ComicResponse] = []
|
||||||
|
for comic in publisher.comics:
|
||||||
|
comics.append(
|
||||||
|
ComicResponse(
|
||||||
|
id=comic.id,
|
||||||
|
created_date=comic.created_date,
|
||||||
|
last_modified_date=comic.last_modified_date,
|
||||||
|
version=comic.version,
|
||||||
|
publisher_id=comic.publisher_id,
|
||||||
|
current_order=comic.current_order,
|
||||||
|
weblink=comic.weblink,
|
||||||
|
title=comic.title,
|
||||||
|
completed=comic.completed
|
||||||
|
)
|
||||||
|
)
|
||||||
|
parent_publisher: PublisherResponse | None = None
|
||||||
|
if publisher.parent_publisher:
|
||||||
|
parent_publisher = PublisherResponse(
|
||||||
|
id=publisher.parent_publisher.id,
|
||||||
|
created_date=publisher.parent_publisher.created_date,
|
||||||
|
last_modified_date=publisher.parent_publisher.last_modified_date,
|
||||||
|
version=publisher.parent_publisher.version,#
|
||||||
|
weblink=str(publisher.parent_publisher.weblink),
|
||||||
|
parent_publisher_id=publisher.parent_publisher.parent_publisher_id,
|
||||||
|
name=str(publisher.parent_publisher.name)
|
||||||
|
)
|
||||||
|
response: PublisherDetailsResponse = PublisherDetailsResponse(
|
||||||
|
id=publisher.id, name=str(publisher.name), parent_publisher=parent_publisher, imprints=imprints, comics=comics
|
||||||
|
)
|
||||||
|
return response
|
||||||
+2
-5
@@ -4,9 +4,8 @@ from typing import AnyStr, Optional
|
|||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.core.log_conf import logger
|
from kontor_model.db.models.comic import WorkType
|
||||||
from src.db.models.comic import WorkType
|
from kontor_model.schema.comics.worktype import AddWorkType
|
||||||
from src.schema.comics.worktype import AddWorkType
|
|
||||||
|
|
||||||
|
|
||||||
def create_new_worktype(work: AddWorkType, db: Session) -> WorkType:
|
def create_new_worktype(work: AddWorkType, db: Session) -> WorkType:
|
||||||
@@ -18,12 +17,10 @@ def create_new_worktype(work: AddWorkType, db: Session) -> WorkType:
|
|||||||
db.add(worktype)
|
db.add(worktype)
|
||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(worktype)
|
db.refresh(worktype)
|
||||||
logger.info(f"create_new_worktype: {worktype}")
|
|
||||||
return worktype
|
return worktype
|
||||||
|
|
||||||
|
|
||||||
def update_worktype(work: AddWorkType, worktype_id: AnyStr, db: Session) -> Optional[WorkType]:
|
def update_worktype(work: AddWorkType, worktype_id: AnyStr, db: Session) -> Optional[WorkType]:
|
||||||
logger.info("update worktype")
|
|
||||||
worktype: Optional[WorkType] = db.get(WorkType, worktype_id)
|
worktype: Optional[WorkType] = db.get(WorkType, worktype_id)
|
||||||
if worktype is not None:
|
if worktype is not None:
|
||||||
worktype.name = work.worktype
|
worktype.name = work.worktype
|
||||||
+7
-8
@@ -3,14 +3,13 @@ import uuid
|
|||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.core.log_conf import logger
|
from kontor_model.db.models.media import MediaActor
|
||||||
from src.db.models.media import MediaActor
|
from kontor_model.db.repository.media.actorfile import delete_mediaactorfile
|
||||||
from src.db.repository.media.actorfile import delete_mediaactorfile
|
from kontor_model.schema.media.actor import MediaActorModel
|
||||||
from src.schema.media.actor import MediaActorModel
|
|
||||||
|
|
||||||
|
|
||||||
def create_new_mediaactor(new_actor: MediaActorModel, db: Session) -> MediaActor:
|
def create_new_mediaactor(new_actor: MediaActorModel, db: Session) -> MediaActor:
|
||||||
logger.info(f"create MediaActor with url {new_actor.url}")
|
print(f"create MediaActor with url {new_actor.url}")
|
||||||
media_actor: MediaActor = MediaActor()
|
media_actor: MediaActor = MediaActor()
|
||||||
media_actor.id = str(uuid.uuid4())
|
media_actor.id = str(uuid.uuid4())
|
||||||
if new_actor.name is not None:
|
if new_actor.name is not None:
|
||||||
@@ -22,11 +21,11 @@ def create_new_mediaactor(new_actor: MediaActorModel, db: Session) -> MediaActor
|
|||||||
db.add(media_actor)
|
db.add(media_actor)
|
||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(media_actor)
|
db.refresh(media_actor)
|
||||||
logger.info(f"created {media_actor}")
|
print(f"created {media_actor}")
|
||||||
return media_actor
|
return media_actor
|
||||||
|
|
||||||
def delete_mediaactor(db: Session, actor_id: str):
|
def delete_mediaactor(db: Session, actor_id: str):
|
||||||
logger.info(f"delete MediaActor with id {actor_id}")
|
print(f"delete MediaActor with id {actor_id}")
|
||||||
media_actor = db.get(MediaActor, actor_id)
|
media_actor = db.get(MediaActor, actor_id)
|
||||||
if media_actor is not None:
|
if media_actor is not None:
|
||||||
actor_files = media_actor.media_actor_files
|
actor_files = media_actor.media_actor_files
|
||||||
@@ -40,7 +39,7 @@ def import_mediaactor(db: Session, new_actor: MediaActorModel) -> MediaActor:
|
|||||||
"""
|
"""
|
||||||
import MediaFile and set missing values with default ones.
|
import MediaFile and set missing values with default ones.
|
||||||
"""
|
"""
|
||||||
logger.info("import MediaActor with %s", new_actor)
|
print("import MediaActor with %s", new_actor)
|
||||||
media_actor: MediaActor = MediaActor()
|
media_actor: MediaActor = MediaActor()
|
||||||
media_actor.id = new_actor.id
|
media_actor.id = new_actor.id
|
||||||
if new_actor.created_date:
|
if new_actor.created_date:
|
||||||
+5
-6
@@ -3,9 +3,8 @@ import uuid
|
|||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.core.log_conf import logger
|
from kontor_model.db.models.media import MediaActorFile
|
||||||
from src.db.models.media import MediaActorFile
|
from kontor_model.schema.media.actorfile import MediaActorFileModel
|
||||||
from src.schema.media.actorfile import MediaActorFileModel
|
|
||||||
|
|
||||||
|
|
||||||
def create_new_mediaactorfile(
|
def create_new_mediaactorfile(
|
||||||
@@ -14,7 +13,7 @@ def create_new_mediaactorfile(
|
|||||||
"""
|
"""
|
||||||
Create relation for MediaFile and MediaActor
|
Create relation for MediaFile and MediaActor
|
||||||
"""
|
"""
|
||||||
logger.info("create MediaActorFile with actor %s and file %s", actor_id, file_id)
|
print("create MediaActorFile with actor %s and file %s", actor_id, file_id)
|
||||||
media_actor_file: MediaActorFile = MediaActorFile()
|
media_actor_file: MediaActorFile = MediaActorFile()
|
||||||
media_actor_file.id = str(uuid.uuid4())
|
media_actor_file.id = str(uuid.uuid4())
|
||||||
media_actor_file.created_date = datetime.now()
|
media_actor_file.created_date = datetime.now()
|
||||||
@@ -32,7 +31,7 @@ def delete_mediaactorfile(db: Session, actorfile_id: str):
|
|||||||
"""
|
"""
|
||||||
Delete relation between MediaFile and MediaActor.
|
Delete relation between MediaFile and MediaActor.
|
||||||
"""
|
"""
|
||||||
logger.info("delete MediaActorFile with id %s", actorfile_id)
|
print("delete MediaActorFile with id %s", actorfile_id)
|
||||||
media_actorfile = db.get(MediaActorFile, actorfile_id)
|
media_actorfile = db.get(MediaActorFile, actorfile_id)
|
||||||
db.delete(media_actorfile)
|
db.delete(media_actorfile)
|
||||||
db.commit()
|
db.commit()
|
||||||
@@ -44,7 +43,7 @@ def import_mediaactorfile(
|
|||||||
"""
|
"""
|
||||||
Import MediaFile and set missing values with default ones.
|
Import MediaFile and set missing values with default ones.
|
||||||
"""
|
"""
|
||||||
logger.info("import MediaActorFile with %s", new_actorfile)
|
print("import MediaActorFile with %s", new_actorfile)
|
||||||
media_actor_file: MediaActorFile = MediaActorFile()
|
media_actor_file: MediaActorFile = MediaActorFile()
|
||||||
media_actor_file.id = new_actorfile.id
|
media_actor_file.id = new_actorfile.id
|
||||||
if new_actorfile.created_date:
|
if new_actorfile.created_date:
|
||||||
+6
-7
@@ -3,16 +3,15 @@ import uuid
|
|||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.core.log_conf import logger
|
from kontor_model.db.models.media import MediaFile
|
||||||
from src.db.models.media import MediaFile
|
from kontor_model.schema.media.file import MediaFileModel
|
||||||
from src.schema.media.file import MediaFileModel
|
|
||||||
|
|
||||||
|
|
||||||
def create_new_mediafile(link: str, db: Session) -> MediaFile:
|
def create_new_mediafile(link: str, db: Session) -> MediaFile:
|
||||||
"""
|
"""
|
||||||
Create MediaFile with gievne URL.
|
Create MediaFile with gievne URL.
|
||||||
"""
|
"""
|
||||||
logger.info("create MediaFile with url {link}")
|
print("create MediaFile with url {link}")
|
||||||
media_file: MediaFile = MediaFile()
|
media_file: MediaFile = MediaFile()
|
||||||
media_file.id = str(uuid.uuid4())
|
media_file.id = str(uuid.uuid4())
|
||||||
media_file.url = link
|
media_file.url = link
|
||||||
@@ -24,7 +23,7 @@ def create_new_mediafile(link: str, db: Session) -> MediaFile:
|
|||||||
db.add(media_file)
|
db.add(media_file)
|
||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(media_file)
|
db.refresh(media_file)
|
||||||
logger.info("created %s", media_file)
|
print("created %s", media_file)
|
||||||
return media_file
|
return media_file
|
||||||
|
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ def delete_mediafile(db: Session, media_file_id: str):
|
|||||||
"""
|
"""
|
||||||
Delete MediaFile with given ID from db.
|
Delete MediaFile with given ID from db.
|
||||||
"""
|
"""
|
||||||
logger.info("delete MediaFile with id %s", media_file_id)
|
print("delete MediaFile with id %s", media_file_id)
|
||||||
media_file = db.get(MediaFile, media_file_id)
|
media_file = db.get(MediaFile, media_file_id)
|
||||||
db.delete(media_file)
|
db.delete(media_file)
|
||||||
db.commit()
|
db.commit()
|
||||||
@@ -42,7 +41,7 @@ def import_mediafile(db: Session, new_file: MediaFileModel) -> MediaFile:
|
|||||||
"""
|
"""
|
||||||
import MediaActor and set missing values with defautl ones.
|
import MediaActor and set missing values with defautl ones.
|
||||||
"""
|
"""
|
||||||
logger.info("import MediaFile with %s", new_file)
|
print("import MediaFile with %s", new_file)
|
||||||
media_file: MediaFile = MediaFile()
|
media_file: MediaFile = MediaFile()
|
||||||
media_file.id = new_file.id
|
media_file.id = new_file.id
|
||||||
if new_file.created_date:
|
if new_file.created_date:
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from kontor_model.db.models.media import MediaLofi
|
||||||
|
from kontor_model.schema.media.lofi import MediaLofiModel
|
||||||
|
|
||||||
|
|
||||||
|
def create_new_lofi(url: str, db: Session) -> MediaLofi:
|
||||||
|
"""
|
||||||
|
Create MediaLofi with given URL.
|
||||||
|
"""
|
||||||
|
print("create MediaLofi with url %s", url)
|
||||||
|
media_lofi = MediaLofi()
|
||||||
|
media_lofi.id = str(uuid.uuid4())
|
||||||
|
media_lofi.url = url
|
||||||
|
media_lofi.created_date = datetime.now()
|
||||||
|
media_lofi.last_modified_date = datetime.now()
|
||||||
|
media_lofi.review = True
|
||||||
|
media_lofi.should_download = False
|
||||||
|
db.add(media_lofi)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(media_lofi)
|
||||||
|
print(media_lofi)
|
||||||
|
return media_lofi
|
||||||
|
|
||||||
|
def import_medialofi(db: Session, new_lofi: MediaLofiModel) -> MediaLofi:
|
||||||
|
"""
|
||||||
|
import MediaLofi and set missing values with default ones.
|
||||||
|
"""
|
||||||
|
print("import MediaLofi with %s", new_lofi)
|
||||||
|
media_lofi: MediaLofi = MediaLofi()
|
||||||
|
media_lofi.id = new_lofi.id
|
||||||
|
if new_lofi.created_date:
|
||||||
|
media_lofi.created_date = new_lofi.created_date
|
||||||
|
else:
|
||||||
|
media_lofi.created_date = datetime.now()
|
||||||
|
if new_lofi.last_modified_date:
|
||||||
|
media_lofi.last_modified_date = new_lofi.last_modified_date
|
||||||
|
else:
|
||||||
|
media_lofi.last_modified_date = datetime.now()
|
||||||
|
media_lofi.version = new_lofi.version
|
||||||
|
if new_lofi.title:
|
||||||
|
media_lofi.title = new_lofi.title
|
||||||
|
else:
|
||||||
|
media_lofi.title = ""
|
||||||
|
if new_lofi.url:
|
||||||
|
media_lofi.url = new_lofi.url
|
||||||
|
else:
|
||||||
|
# TODO shoud exeception be raised when url is missing?
|
||||||
|
media_lofi.url = ""
|
||||||
|
media_lofi.review = new_lofi.review
|
||||||
|
media_lofi.should_download = new_lofi.should_download
|
||||||
|
db.add(media_lofi)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(media_lofi)
|
||||||
|
return media_lofi
|
||||||
|
|
||||||
|
|
||||||
|
def delete_medialofi(db: Session, lofi_id: str):
|
||||||
|
"""
|
||||||
|
Delete MediaLofi with given ID from db.
|
||||||
|
"""
|
||||||
|
print("delete MediaLofi with id %s", lofi_id)
|
||||||
|
lofi = db.get(MediaLofi, lofi_id)
|
||||||
|
db.delete(lofi)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
+4
-5
@@ -3,15 +3,14 @@ import uuid
|
|||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.db.models.media import MediaVideo
|
from kontor_model.db.models.media import MediaVideo
|
||||||
from src.webapps.media.forms import AddLinkForm
|
|
||||||
|
|
||||||
|
|
||||||
def create_new_video(video: AddLinkForm, db: Session) -> MediaVideo:
|
def create_new_video(url: str, db: Session) -> MediaVideo:
|
||||||
print(video.url)
|
print(url)
|
||||||
media_video = MediaVideo()
|
media_video = MediaVideo()
|
||||||
media_video.id = str(uuid.uuid4())
|
media_video.id = str(uuid.uuid4())
|
||||||
media_video.url = str(video.url)
|
media_video.url = url
|
||||||
media_video.created_date = datetime.now()
|
media_video.created_date = datetime.now()
|
||||||
media_video.last_modified_date = datetime.now()
|
media_video.last_modified_date = datetime.now()
|
||||||
media_video.review = True
|
media_video.review = True
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from typing import Optional
|
||||||
|
import uuid
|
||||||
|
from kontor_model.db.models.admin import Assignment, Profile
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from kontor_model.schema.user.profile import ProfileModel
|
||||||
|
|
||||||
|
|
||||||
|
def create_new_profile(new_profile: ProfileModel, db: Session) -> Profile:
|
||||||
|
print(f"create Profile with username {new_profile.username}")
|
||||||
|
profile: Profile = Profile()
|
||||||
|
profile.id = str(uuid.uuid4())
|
||||||
|
profile.user_name = new_profile.username
|
||||||
|
profile.first_name = new_profile.first_name
|
||||||
|
profile.last_name = new_profile.last_name
|
||||||
|
profile.created_date = datetime.now()
|
||||||
|
profile.last_modified_date = datetime.now()
|
||||||
|
profile.version = 0
|
||||||
|
db.add(profile)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(profile)
|
||||||
|
print(f"created {profile}")
|
||||||
|
return profile
|
||||||
|
|
||||||
|
def delete_profile(db: Session, profile_id: str):
|
||||||
|
print(f"delete Profile with id {profile_id}")
|
||||||
|
profile: Optional[Profile] = db.get(Profile, profile_id)
|
||||||
|
if profile is not None:
|
||||||
|
assignments = profile.assignments
|
||||||
|
for assignment in assignments:
|
||||||
|
delete_assignment(db, assignment.id)
|
||||||
|
db.delete(profile)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def delete_assignment(db: Session, assignment_id: str) -> None:
|
||||||
|
print(f"delete Assignment with id {assignment_id}")
|
||||||
|
assignment: Optional[Assignment] = db.get(Assignment, assignment_id)
|
||||||
|
if assignment is not None:
|
||||||
|
db.delete(assignment)
|
||||||
|
db.commit()
|
||||||
+6
-6
@@ -2,7 +2,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from src.db.models.admin import MailAccount
|
from kontor_model.db.models.admin import MailAccount
|
||||||
|
|
||||||
|
|
||||||
class MailAccountResponse(BaseModel):
|
class MailAccountResponse(BaseModel):
|
||||||
@@ -24,11 +24,11 @@ def to_response(account: MailAccount) -> MailAccountResponse:
|
|||||||
created_date=account.created_date,
|
created_date=account.created_date,
|
||||||
last_modified_date=account.last_modified_date,
|
last_modified_date=account.last_modified_date,
|
||||||
version=account.version,
|
version=account.version,
|
||||||
host=account.host,
|
host=str(account.host),
|
||||||
port=account.port,
|
port=account.port,
|
||||||
protocol=account.protocol,
|
protocol=str(account.protocol),
|
||||||
user_name=account.user_name,
|
user_name=str(account.user_name),
|
||||||
password=account.password,
|
password=str(account.password),
|
||||||
start_tls=account.start_tls,
|
start_tls=bool(account.start_tls),
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
+2
-2
@@ -2,7 +2,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from src.db.models.bookshelf import Article
|
from kontor_model.db.models.bookshelf import Article
|
||||||
|
|
||||||
|
|
||||||
class ArticleResponse(BaseModel):
|
class ArticleResponse(BaseModel):
|
||||||
@@ -18,6 +18,6 @@ def to_response(article: Article) -> ArticleResponse:
|
|||||||
created_date=article.created_date,
|
created_date=article.created_date,
|
||||||
last_modified_date=article.last_modified_date,
|
last_modified_date=article.last_modified_date,
|
||||||
version=article.version,
|
version=article.version,
|
||||||
title=article.title
|
title=str(article.title)
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user