Remove obsolete endpoints (#89)

Remove endpoints api/login/token and api/login/profile

---------

Co-authored-by: Thomas Peetz <thomas.peetz@cimt-ag.de>
Reviewed-on: #89
This commit is contained in:
2026-05-19 17:52:30 +00:00
parent 7b374b1eeb
commit 6310377d84
38 changed files with 527 additions and 113 deletions
+12 -4
View File
@@ -3,9 +3,9 @@ add router for different parts (like comics, tysc, media)
"""
from fastapi import APIRouter, Depends
from src.apis.version1.admin import token
from src.apis.version1.comics import artist, comic, issue
from src.apis.version1.media import mediaactor, mediaactorfile, mediafile
from src.apis.version1.admin import mailaccount
from src.apis.version1.comics import artist, comic, issue, worktype, volume, storyarc
from src.apis.version1.media import mediaactor, mediaactorfile, mediafile, mediavideo, mediaarticle
from src.apis.version1.tysc import card, cardset, fieldposition, player, rooster, sport, team, vendor
from src.core.security import get_current_user_from_token
@@ -15,7 +15,12 @@ api_router = APIRouter(prefix="/api")
api_router.include_router(comic.router, prefix="/comics", tags=["comics"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(artist.router, prefix="/comics", tags=["comics"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(issue.router, prefix="/comics", tags=["comics"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(worktype.router, prefix="/comics", tags=["comics"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(volume.router, prefix="/comics", tags=["comics"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(storyarc.router, prefix="/comics", tags=["comics"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(mediafile.router, prefix="/media", tags=["media"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(mediavideo.router, prefix="/media", tags=["media"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(mediaarticle.router, prefix="/media", tags=["media"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(mediaactor.router, prefix="/media", tags=["media"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(mediaactorfile.router, prefix="/media", tags=["media"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(sport.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)])
@@ -27,5 +32,8 @@ api_router.include_router(vendor.router, prefix="/tysc", tags=["tysc"], dependen
api_router.include_router(cardset.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(card.router, prefix="/tysc", tags=["tysc"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(article.router, prefix="/bookshelf", tags=["bookshelf"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(token.router, prefix="/login", tags=["login"])
api_router.include_router(profile.router, prefix="/user", tags=["user"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(token.router, prefix="/user", tags=["user"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(permission.router, prefix="/user", tags=["user"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(assignment.router, prefix="/user", tags=["user"], dependencies=[Depends(get_current_user_from_token)])
api_router.include_router(mailaccount.router, prefix="/admin", tags=["admin"], dependencies=[Depends(get_current_user_from_token)])
+22 -12
View File
@@ -1,8 +1,7 @@
from datetime import timedelta
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi import APIRouter, Depends, HTTPException, Response, status
from fastapi.security import OAuth2PasswordRequestForm
from pydantic import BaseModel
from typing import Annotated
from src.core.config import settings
from src.core.log_conf import logger
@@ -11,16 +10,12 @@ from src.core.security import (
authenticate_user_by_username,
create_access_token,
)
from src.schema.admin import Token
from src.schema.admin.login import LoginRequest
from src.schema.admin.token import Token
from src.webapps.auth.forms import LoginForm
login_router = APIRouter()
class LoginRequest(BaseModel):
email: str | None = None
password: str | None = None
@login_router.post(
"/login",
tags=["login"],
@@ -47,9 +42,8 @@ def login(request: LoginRequest) -> Token:
@login_router.post("/token", tags=["login"], summary="Login for access token")
async def login_for_access_token(
form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> Token:
#async def login_for_access_token(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]) -> Token:
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()) -> Token:
user = authenticate_user_by_username(form_data.username, form_data.password)
if not user:
raise HTTPException(status_code=400, detail="Incorrect username or password")
@@ -59,3 +53,19 @@ async def login_for_access_token(
expires_delta=access_token_expires,
)
return Token(access_token=access_token, token_type="bearer")
def login_for_token_cookie(response: Response, form_data: LoginForm = Depends()):
user = authenticate_user_by_email(str(form_data.username), str(form_data.password))
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
)
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.email}, expires_delta=access_token_expires
)
response.set_cookie(
key="access_token", value=f"Bearer {access_token}", httponly=True
)
return {"access_token": access_token, "token_type": "bearer"}
@@ -4,7 +4,7 @@ from fastapi import APIRouter
from src.db.models.admin import MailAccount
from src.db.session import SessionDep
from src.schema.admin import MailAccountResponse, to_response
from src.schema.admin.mailaccount import MailAccountResponse, to_response
router = APIRouter()
@@ -1,69 +0,0 @@
import logging
from datetime import timedelta
import bcrypt
from fastapi import APIRouter, HTTPException, status, Response, Depends
from fastapi.security import OAuth2PasswordRequestForm
from jose import jwt, JWTError
from src.apis.utils import SessionDep, OAuth2PasswordBearerWithCookie
from src.core.config import settings
from src.core.security import create_access_token
from src.db.models.admin import Profile
from src.db.repository.admin import get_profile
from src.schema.admin import Token
router = APIRouter()
def authenticate_user(username: str, password: str, db: SessionDep) -> Profile | None:
user = get_profile(username=username, db=db)
print(user)
if not user:
return None
if bcrypt.checkpw(password.encode(), user.password.encode()):
print("User successful authenticated")
else:
logging.info("Authentication failed!")
return user
@router.post("/token", response_model=Token)
def login_for_access_token(response: Response, db: SessionDep, form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password, db)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
)
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.email}, expires_delta=access_token_expires
)
response.set_cookie(
key="access_token", value=f"Bearer {access_token}", httponly=True
)
return {"access_token": access_token, "token_type": "bearer"}
oauth2_scheme = OAuth2PasswordBearerWithCookie(tokenUrl="/api/login/token")
def get_current_user_from_token(db: SessionDep, token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
)
try:
payload = jwt.decode(
token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM]
)
username: str = payload.get("sub")
print("username/email extracted is ", username)
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = get_profile(username=username, db=db)
if user is None:
raise credentials_exception
return user
+6 -6
View File
@@ -3,17 +3,17 @@ from typing import List
from fastapi import APIRouter
from src.db.models.comic import Issue
from src.db.repository.comics.comic import get_issue_details
from src.db.session import SessionDep
from src.schema.comics.issue_details import IssueDetailsResponse
from src.schema.comics.issue import IssueResponse, to_response
router = APIRouter()
@router.get("/issues", response_model=List[IssueDetailsResponse])
def get_issues(db: SessionDep) -> List[IssueDetailsResponse]:
results: List[IssueDetailsResponse] = []
@router.get("/issues", response_model=List[IssueResponse])
def get_issues(db: SessionDep) -> List[IssueResponse]:
results: List[IssueResponse] = []
issues = db.query(Issue).all()
for issue in issues:
results.append(get_issue_details(issue))
response = to_response(issue)
results.append(response)
return results
@@ -0,0 +1,18 @@
from typing import List
from fastapi import APIRouter
from src.db.models.comic import StoryArc
from src.db.session import SessionDep
from src.schema.comics.storyarc import StoryArcResponse, to_response
router = APIRouter()
@router.get("/storyarcs", response_model=List[StoryArcResponse])
def get_issues(db: SessionDep) -> List[StoryArcResponse]:
results: List[StoryArcResponse] = []
storyarcs = db.query(StoryArc).all()
for storyarc in storyarcs:
response = to_response(storyarc)
results.append(response)
return results
@@ -0,0 +1,18 @@
from typing import List
from fastapi import APIRouter
from src.db.models.comic import Volume
from src.db.session import SessionDep
from src.schema.comics.volume import VolumeResponse, to_response
router = APIRouter()
@router.get("/volumes", response_model=List[VolumeResponse])
def get_issues(db: SessionDep) -> List[VolumeResponse]:
results: List[VolumeResponse] = []
worktypes = db.query(Volume).all()
for worktype in worktypes:
response = to_response(worktype)
results.append(response)
return results
@@ -0,0 +1,19 @@
from typing import List
from fastapi import APIRouter
from src.db.models.comic import WorkType
from src.db.session import SessionDep
from src.schema.comics.worktype import WorktypeResponse, to_response
router = APIRouter()
@router.get("/worktypes", response_model=List[WorktypeResponse])
def get_issues(db: SessionDep) -> List[WorktypeResponse]:
results: List[WorktypeResponse] = []
worktypes = db.query(WorkType).all()
for worktype in worktypes:
response = to_response(worktype)
results.append(response)
return results
+1 -1
View File
@@ -1,6 +1,6 @@
from fastapi import APIRouter, status
from src.schema.admin import HealthCheck
from src.schema.admin.healthcheck import HealthCheck
health_router = APIRouter()
@@ -0,0 +1,25 @@
from typing import List
from fastapi import APIRouter
from src.db.models.media import MediaArticle
from src.db.session import SessionDep
from src.schema.media.article import MediaArticleResponse, to_response
router = APIRouter()
@router.get("/articles", response_model=List[MediaArticleResponse])
def get_all_files(
db: SessionDep, review: bool = False, download: bool = False
) -> List[MediaArticleResponse]:
"""
Get all MediaVideos.
"""
results: List[MediaArticleResponse] = []
articles: List[MediaArticle]
articles = db.query(MediaArticle).all()
for article in articles:
response = to_response(article)
results.append(response)
return results
@@ -0,0 +1,31 @@
from typing import List
from fastapi import APIRouter
from src.db.models.media import MediaVideo
from src.db.session import SessionDep
from src.schema.media.video import MediaVideoResponse, to_response
router = APIRouter()
@router.get("/videos", response_model=List[MediaVideoResponse])
def get_all_files(
db: SessionDep, review: bool = False, download: bool = False
) -> List[MediaVideoResponse]:
"""
Get all MediaVideos.
"""
results: List[MediaVideoResponse] = []
files: List[MediaVideo]
if review:
files = db.query(MediaVideo).filter(MediaVideo.review.is_(True)).all()
elif download:
files = db.query(MediaVideo).filter(MediaVideo.should_download.is_(True)).all()
else:
files = db.query(MediaVideo).all()
for mediafile in files:
response = to_response(mediafile)
results.append(response)
return results
@@ -0,0 +1,20 @@
from typing import List
from fastapi import APIRouter
from src.db.models.admin import Assignment
from src.db.session import SessionDep
from src.schema.user.assignment import AssignmentResponse, to_response
router = APIRouter()
@router.get("/assignments", response_model=List[AssignmentResponse])
def get_all_profiles(db: SessionDep) -> List[AssignmentResponse]:
results: List[AssignmentResponse] = []
profiles = db.query(Assignment).all()
for profile in profiles:
response = to_response(profile)
results.append(response)
return results
@@ -0,0 +1,19 @@
from typing import List
from fastapi import APIRouter
from src.db.models.admin import Permission
from src.db.session import SessionDep
from src.schema.user.permission import PermissionResponse, to_response
router = APIRouter()
@router.get("/permissions", response_model=List[PermissionResponse])
def get_all_profiles(db: SessionDep) -> List[PermissionResponse]:
results: List[PermissionResponse] = []
permissions = db.query(Permission).all()
for permission in permissions:
response = to_response(permission)
results.append(response)
return results
+10 -4
View File
@@ -3,6 +3,7 @@ from fastapi import APIRouter, HTTPException, status
from sqlalchemy import select
from src.core.log_conf import logger
from src.core.security import CurrentUser
from src.db.models.admin import Profile
from src.db.repository.user import create_new_profile, get_profile_details
from src.db.session import SessionDep
@@ -11,8 +12,13 @@ from src.schema.user.profile import ProfileResponse, ProfileModel
router = APIRouter()
@router.get("/profile", response_model=ProfileModel)
async def read_profile(current_user: CurrentUser):
return current_user
@router.get("/profiles", response_model=List[ProfileResponse])
def get_all_profiles(db: SessionDep) -> List[ProfileResponse]: # type: ignore
def get_all_profiles(db: SessionDep) -> List[ProfileResponse]:
results: List[ProfileResponse] = []
profiles = db.scalars(select(Profile)).all()
for profile in profiles:
@@ -21,7 +27,7 @@ def get_all_profiles(db: SessionDep) -> List[ProfileResponse]: # type: ignore
return results
@router.get("/profiles/{profile_id}", response_model=ProfileResponse)
def get_profile(profile_id: str, db: SessionDep) -> ProfileResponse: # type: ignore
def get_profile(profile_id: str, db: SessionDep) -> ProfileResponse:
profile = db.get(Profile, profile_id)
if not profile:
raise HTTPException(status_code=404, detail="MediaActor could not be found")
@@ -37,8 +43,8 @@ def delete_profile(profile_id: str, db: SessionDep): # type: ignore
delete_profile(profile_id=profile_id, db=db)
@router.post("/profiles", status_code=status.HTTP_201_CREATED)
def add_profile(new_profile: ProfileModel, db: SessionDep) -> ProfileResponse: # type: ignore
logger.info(f"add profile {new_profile.user_name}")
def add_profile(new_profile: ProfileModel, db: SessionDep) -> ProfileResponse:
logger.info(f"add profile {new_profile.username}")
try:
profile: Profile = create_new_profile(new_profile, db)
except:
@@ -0,0 +1,19 @@
from typing import List
from fastapi import APIRouter
from src.db.models.admin import Token
from src.db.session import SessionDep
from src.schema.user.token import TokenResponse, to_response
router = APIRouter()
@router.get("/tokens", response_model=List[TokenResponse])
def get_all_profiles(db: SessionDep) -> List[TokenResponse]:
results: List[TokenResponse] = []
tokens = db.query(Token).all()
for token in tokens:
response = to_response(token)
results.append(response)
return results
+35
View File
@@ -0,0 +1,35 @@
import json
import time
from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware
from src.core.log_conf import logger
class RequestLoggingMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next) -> Response:
start_time = time.time()
path = request.url.path
if path != "/health":
# Log request info
request_info ={
"method": request.method,
"path": path,
"client_ip": request.client.host if request.client else "unknown"
}
logger.info("Incoming: %s", json.dumps(request_info))
# Process request
response = await call_next(request)
if path != "/health":
# Log response info
duration_ms = (time.time()- start_time)*1000
response_info = {
"status_code": response.status_code,
"duration_ms": round(duration_ms, 2)
}
logger.info("completed: %s", json.dumps(response_info))
return response
+1 -1
View File
@@ -38,7 +38,7 @@ def delete_profile(db: Session, profile_id: str):
def get_profile_details(profile: Profile) -> ProfileResponse:
reponse: ProfileResponse = ProfileResponse(
id=profile.id,
user_name=str(profile.user_name)
username=str(profile.user_name)
)
return reponse
+6 -4
View File
@@ -13,6 +13,7 @@ from src.db.utils import check_db_connected, check_db_disconnected
from src.webapps.base import api_router as web_app_router
from src.core.config import settings
from src.core.log_conf import logger
from src.core.middleware import RequestLoggingMiddleware
from src.db.models.base import Base
from src.db.session import engine
from src.db.utils import check_db_connected, check_db_disconnected
@@ -34,10 +35,10 @@ async def lifespan(app: FastAPI):
await check_db_disconnected()
def include_router(app: FastAPI):
app.include_router(api_router)
app.include_router(web_app_router)
app.include_router(health_router)
app.include_router(login_router)
app.include_router(api_router, tags=["api"])
app.include_router(web_app_router, tags=["webapp"])
app.include_router(health_router, tags=["admin"])
app.include_router(login_router, tags=["webapp"])
def configure_static(app: FastAPI):
@@ -52,6 +53,7 @@ def add_middle_ware(app: FastAPI):
allow_methods=["*"],
allow_headers=["*"],
)
app.add_middleware(RequestLoggingMiddleware)
def create_tables():
@@ -0,0 +1,9 @@
from pydantic import BaseModel
class HealthCheck(BaseModel):
"""
Health check model
"""
status: str = "ok"
+8
View File
@@ -0,0 +1,8 @@
from typing import Optional
from pydantic import BaseModel
class LoginRequest(BaseModel):
email: Optional[str] = None
password: Optional[str] = None
+13
View File
@@ -0,0 +1,13 @@
from typing import List, Optional
from pydantic import BaseModel
class Token(BaseModel):
access_token: str
token_type: str
class TokenData(BaseModel):
username: Optional[str] = None
scopes: List[str] = []
+10
View File
@@ -1,9 +1,19 @@
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
from src.db.models.comic import Issue
class IssueDetailsResponse(BaseModel):
id: str
created_date: datetime
last_modified_date: datetime
version: int
issue_number: str
title: Optional[str]
published_on: Optional[datetime]
in_stock: bool
is_read: bool
comic_id: str
@@ -11,3 +11,4 @@ class IssueDetailsResponse(BaseModel):
is_read: bool
comic: ComicResponse
volume: VolumeResponse | None
+30
View File
@@ -0,0 +1,30 @@
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
from src.db.models.comic import StoryArc
class StoryArcResponse(BaseModel):
id: str
created_date: datetime
last_modified_date: datetime
version: int
name: str
comic_id: str
volume_id: Optional[str]
class AddLink(BaseModel):
url: str
def to_response(storyarc: StoryArc) -> StoryArcResponse:
response: StoryArcResponse = StoryArcResponse(
id=storyarc.id,
created_date=storyarc.created_date,
last_modified_date=storyarc.last_modified_date,
version=storyarc.version,
name=storyarc.name,
comic_id=storyarc.comic_id,
volume_id=storyarc.volume_id
)
return response
+19
View File
@@ -1,6 +1,25 @@
from datetime import datetime
from pydantic import BaseModel
from src.db.models.comic import Volume
class VolumeResponse(BaseModel):
id: str
created_date: datetime
last_modified_date: datetime
version: int
name: str
comic_id: str
def to_response(volume: Volume) -> VolumeResponse:
response: VolumeResponse = VolumeResponse(
id=volume.id,
created_date=volume.created_date,
last_modified_date=volume.last_modified_date,
version=volume.version,
name=volume.name,
comic_id=volume.comic_id
)
return response
+4
View File
@@ -1,4 +1,8 @@
from datetime import datetime
from pydantic import BaseModel
from src.db.models.comic import WorkType
class AddWorkType(BaseModel):
worktype: str
+30
View File
@@ -0,0 +1,30 @@
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
from src.db.models.media import MediaArticle
class MediaArticleResponse(BaseModel):
id: str
created_date: datetime
last_modified_date: datetime
version: int
review: bool = False
title: Optional[str] = None
url: Optional[str] = None
class AddLink(BaseModel):
url: str
def to_response(video: MediaArticle) -> MediaArticleResponse:
response: MediaArticleResponse = MediaArticleResponse(
id=video.id,
created_date=video.created_date,
last_modified_date=video.last_modified_date,
version=video.version,
review=video.review,
title=video.title,
url=video.url,
)
return response
+33
View File
@@ -1,5 +1,38 @@
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
from src.db.models.media import MediaVideo
class MediaVideoResponse(BaseModel):
id: str
created_date: datetime
last_modified_date: datetime
version: int
cloud_link: Optional[str] = None
file_name: Optional[str] = None
path: Optional[str] = None
review: bool = False
title: Optional[str] = None
url: Optional[str] = None
should_download: bool = False
class AddLink(BaseModel):
url: str
def to_response(video: MediaVideo) -> MediaVideoResponse:
response: MediaVideoResponse = MediaVideoResponse(
id=video.id,
created_date=video.created_date,
last_modified_date=video.last_modified_date,
version=video.version,
cloud_link=video.cloud_link,
file_name=video.file_name,
path=video.path,
review=video.review,
title=video.title,
url=video.url,
should_download=video.should_download
)
return response
+26
View File
@@ -0,0 +1,26 @@
from datetime import datetime
from pydantic import BaseModel
from src.db.models.admin import Assignment
class AssignmentResponse(BaseModel):
id: str
created_date: datetime
last_modified_date: datetime
version: int
profile_id: str
permission_id: str
def to_response(assignment: Assignment) -> AssignmentResponse:
response: AssignmentResponse = AssignmentResponse(
id=assignment.id,
created_date=assignment.created_date,
last_modified_date=assignment.last_modified_date,
version=assignment.version,
profile_id=assignment.profile_id,
permission_id=assignment.permission_id
)
return response
+24
View File
@@ -0,0 +1,24 @@
from datetime import datetime
from pydantic import BaseModel
from src.db.models.admin import Permission
class PermissionResponse(BaseModel):
id: str
created_date: datetime
last_modified_date: datetime
version: int
name: str
def to_response(permission: Permission) -> PermissionResponse:
response: PermissionResponse = PermissionResponse(
id=permission.id,
created_date=permission.created_date,
last_modified_date=permission.last_modified_date,
version=permission.version,
name=permission.name
)
return response
+16 -2
View File
@@ -1,12 +1,26 @@
from pydantic import BaseModel
from src.db.models.admin import Profile
class ProfileResponse(BaseModel):
id: str
user_name: str
username: str
class ProfileModel(BaseModel):
user_name: str
username: str
email: str
first_name: str
last_name: str
active: bool
def to_model(profile: Profile) -> ProfileModel:
model: ProfileModel = ProfileModel(
username=profile.user_name,
email=profile.email,
first_name=profile.first_name,
last_name=profile.last_name,
active=profile.enabled,
)
return model
+32
View File
@@ -0,0 +1,32 @@
from datetime import datetime
from pydantic import BaseModel
from src.db.models.admin import Token
class TokenResponse(BaseModel):
id: str
created_date: datetime
last_modified_date: datetime
version: int
token: str
name: str
last_used_date: datetime
enabled: bool
profile_id: str
def to_response(token: Token) -> TokenResponse:
response: TokenResponse = TokenResponse(
id=token.id,
created_date=token.created_date,
last_modified_date=token.last_modified_date,
version=token.version,
token=token.token,
name=token.name,
last_used_date=token.last_used_date,
enabled=token.enabled,
profile_id=token.profile_id
)
return response
+1 -1
View File
@@ -17,6 +17,6 @@ api_router.include_router(route_videos.router)
api_router.include_router(route_login.router)
api_router.include_router(route_admin.router)
@api_router.get("/")
@api_router.get("/", tags=["webapp"])
def home(request: Request, msg: str | None = None):
return templates.TemplateResponse("index.html", {"request": request, "msg": msg})
+2 -2
View File
@@ -11,7 +11,7 @@ from src.schema.comics.comic import ComicSchema
from src.webapps.comic.forms.comic import ValidateComicForm
templates = Jinja2Templates(directory="src/templates")
router = APIRouter(include_in_schema=False, prefix="/comic")
router = APIRouter(include_in_schema=True, prefix="/comic")
@router.get("/comics")
def get_comics(db: SessionDep, request: Request, msg: str | None = None):
@@ -58,7 +58,7 @@ async def validate_comic(request: Request, db: SessionDep, comic_id: str, action
if form.is_valid():
try:
comic = ComicSchema(**form.__dict__)
comic = update_comic(comic=comic, comic_id=comic_id, db=db)
comic = update_comic(new_comic=comic, comic_id=comic_id, db=db)
return RedirectResponse(f"/comic/comics/{comic.id}", status_code=status.HTTP_303_SEE_OTHER)
except Exception as e:
print(e)
+3 -3
View File
@@ -8,7 +8,7 @@ import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import Session, sessionmaker
from src.apis.base import api_router
from src.db.models.base import Base
@@ -45,7 +45,7 @@ def app() -> Generator[FastAPI, Any, None]:
@pytest.fixture(scope="module")
def db_session(app: FastAPI) -> Generator[SessionTesting, Any, None]:
def db_session(app: FastAPI) -> Generator[Session, Any, None]:
connection = engine.connect()
transaction = connection.begin()
session = SessionTesting(bind=connection)
@@ -57,7 +57,7 @@ def db_session(app: FastAPI) -> Generator[SessionTesting, Any, None]:
@pytest.fixture(scope="module")
def client(
app: FastAPI, db_session: SessionTesting
app: FastAPI, db_session: Session
) -> Generator[TestClient, Any, None]:
"""
Create a new FastAPI TestClient that uses the `db_session` fixture to override
+1 -1
View File
@@ -43,7 +43,7 @@ MAPPING: Dict[str, str] = {
"permission": "api/user/permissions",
"assignment": "api/user/assignments",
"token": "api/user/tokens",
"mail_account": "api/admin/mailaccount",
"mail_account": "api/admin/mailaccounts",
}
class EndPointNotAvailableException(Exception):
+2 -2
View File
@@ -28,8 +28,8 @@ if __name__== "__main__":
try:
data = server.request(logger, table=table)
logger.info("%s: %s", table, len(data))
if len(data) == 1:
logger.info("show data: %s", data)
#if len(data) == 1:
# logger.info("show data: %s", data)
except EndPointNotAvailableException:
logger.info("Endpoint not implemented")
logger.info("kontor.sync finished")