Implement async db access in admin
This commit is contained in:
@ -1,10 +1,11 @@
|
||||
"""Frontend dependencies."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from collections.abc import Callable, Awaitable
|
||||
from collections.abc import AsyncGenerator, Callable, Awaitable
|
||||
from typing import Self
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from jinja2_fragments.fastapi import Jinja2Blocks
|
||||
from fastapi import Request
|
||||
|
||||
@ -14,6 +15,7 @@ from sshecret_admin.auth.models import User
|
||||
|
||||
UserTokenDep = Callable[[Request, Session], Awaitable[User]]
|
||||
UserLoginDep = Callable[[Request, Session], Awaitable[bool]]
|
||||
AsyncSessionDep = Callable[[], AsyncGenerator[AsyncSession, None]]
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -25,6 +27,7 @@ class FrontendDependencies(BaseDependencies):
|
||||
get_user_from_access_token: UserTokenDep
|
||||
get_user_from_refresh_token: UserTokenDep
|
||||
get_login_status: UserLoginDep
|
||||
get_async_session: AsyncSessionDep
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
@ -35,6 +38,7 @@ class FrontendDependencies(BaseDependencies):
|
||||
get_user_from_access_token: UserTokenDep,
|
||||
get_user_from_refresh_token: UserTokenDep,
|
||||
get_login_status: UserLoginDep,
|
||||
get_async_session: AsyncSessionDep
|
||||
) -> Self:
|
||||
"""Create from base dependencies."""
|
||||
return cls(
|
||||
@ -45,4 +49,5 @@ class FrontendDependencies(BaseDependencies):
|
||||
get_user_from_access_token=get_user_from_access_token,
|
||||
get_user_from_refresh_token=get_user_from_refresh_token,
|
||||
get_login_status=get_login_status,
|
||||
get_async_session=get_async_session,
|
||||
)
|
||||
|
||||
@ -19,6 +19,7 @@ from starlette.datastructures import URL
|
||||
from sshecret_admin.auth import PasswordDB, User, decode_token
|
||||
from sshecret_admin.core.dependencies import BaseDependencies
|
||||
from sshecret_admin.services.admin_backend import AdminBackend
|
||||
from sshecret_admin.core.db import DatabaseSessionManager
|
||||
|
||||
from .dependencies import FrontendDependencies
|
||||
from .exceptions import RedirectException
|
||||
@ -47,7 +48,9 @@ def create_router(dependencies: BaseDependencies) -> APIRouter:
|
||||
session: Annotated[Session, Depends(dependencies.get_db_session)]
|
||||
):
|
||||
"""Get admin backend API."""
|
||||
password_db = session.scalars(select(PasswordDB).where(PasswordDB.id == 1)).first()
|
||||
password_db = session.scalars(
|
||||
select(PasswordDB).where(PasswordDB.id == 1)
|
||||
).first()
|
||||
if not password_db:
|
||||
raise HTTPException(
|
||||
500, detail="Error: The password manager has not yet been set up."
|
||||
@ -116,6 +119,12 @@ def create_router(dependencies: BaseDependencies) -> APIRouter:
|
||||
return False
|
||||
return True
|
||||
|
||||
async def get_async_session():
|
||||
"""Get async session."""
|
||||
sessionmanager = DatabaseSessionManager(dependencies.settings.async_db_url)
|
||||
async with sessionmanager.session() as session:
|
||||
yield session
|
||||
|
||||
view_dependencies = FrontendDependencies.create(
|
||||
dependencies,
|
||||
get_admin_backend,
|
||||
@ -123,6 +132,7 @@ def create_router(dependencies: BaseDependencies) -> APIRouter:
|
||||
get_user_from_access_token,
|
||||
get_user_from_refresh_token,
|
||||
get_login_status,
|
||||
get_async_session,
|
||||
)
|
||||
|
||||
app.include_router(audit.create_router(view_dependencies))
|
||||
|
||||
@ -8,13 +8,13 @@ from fastapi import APIRouter, Depends, Query, Request, Response, status
|
||||
from fastapi.responses import RedirectResponse
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sshecret_admin.services import AdminBackend
|
||||
from starlette.datastructures import URL
|
||||
|
||||
from sshecret_admin.auth import (
|
||||
User,
|
||||
authenticate_user,
|
||||
authenticate_user_async,
|
||||
create_access_token,
|
||||
create_refresh_token,
|
||||
)
|
||||
@ -80,7 +80,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
async def login_user(
|
||||
request: Request,
|
||||
response: Response,
|
||||
session: Annotated[Session, Depends(dependencies.get_db_session)],
|
||||
session: Annotated[AsyncSession, Depends(dependencies.get_async_session)],
|
||||
admin: Annotated[AdminBackend, Depends(dependencies.get_admin_backend)],
|
||||
form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
|
||||
next: Annotated[str, Query()] = "/dashboard",
|
||||
@ -100,7 +100,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
},
|
||||
)
|
||||
|
||||
user = authenticate_user(session, form_data.username, form_data.password)
|
||||
user = await authenticate_user_async(session, form_data.username, form_data.password)
|
||||
login_failed = RedirectException(
|
||||
to=URL("/login").include_query_params(
|
||||
error_title="Login Error", error_message="Invalid username or password"
|
||||
|
||||
Reference in New Issue
Block a user