[flake]
This commit is contained in:
parent
e34208a91b
commit
e7160c922b
10 changed files with 46 additions and 18 deletions
|
|
@ -47,6 +47,9 @@ class ContextDependency:
|
||||||
return Context(repo=Repository(session))
|
return Context(repo=Repository(session))
|
||||||
|
|
||||||
|
|
||||||
|
_oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token")
|
||||||
|
|
||||||
|
|
||||||
class AuthContextDependency:
|
class AuthContextDependency:
|
||||||
"""
|
"""
|
||||||
Context dependency for authorized endpoints
|
Context dependency for authorized endpoints
|
||||||
|
|
@ -54,7 +57,7 @@ class AuthContextDependency:
|
||||||
|
|
||||||
async def __call__(
|
async def __call__(
|
||||||
self,
|
self,
|
||||||
token: str = Depends(OAuth2PasswordBearer(tokenUrl="/token")),
|
token: str = Depends(_oauth2_scheme),
|
||||||
session: AsyncSession = Depends(get_db_session),
|
session: AsyncSession = Depends(get_db_session),
|
||||||
) -> Context:
|
) -> Context:
|
||||||
ctx = Context(repo=Repository(session))
|
ctx = Context(repo=Repository(session))
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
from .user import UserController
|
from fooder.controller.user import UserController
|
||||||
from .product import ProductController
|
from fooder.controller.product import ProductController
|
||||||
|
|
||||||
|
__all__ = ["UserController", "ProductController"]
|
||||||
|
|
|
||||||
12
fooder/db.py
12
fooder/db.py
|
|
@ -23,11 +23,13 @@ class DatabaseSessionManager:
|
||||||
else {}
|
else {}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self._sessionmaker: async_sessionmaker[AsyncSession] | None = async_sessionmaker(
|
self._sessionmaker: async_sessionmaker[AsyncSession] | None = (
|
||||||
autocommit=False,
|
async_sessionmaker(
|
||||||
autoflush=False,
|
autocommit=False,
|
||||||
bind=self._engine,
|
autoflush=False,
|
||||||
expire_on_commit=False,
|
bind=self._engine,
|
||||||
|
expire_on_commit=False,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
async def close(self) -> None:
|
async def close(self) -> None:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ class ApiException(Exception):
|
||||||
|
|
||||||
def __init__(self, message: str | None = None) -> None:
|
def __init__(self, message: str | None = None) -> None:
|
||||||
self.message = message or self.MESSAGE
|
self.message = message or self.MESSAGE
|
||||||
|
super().__init__(self.message)
|
||||||
|
|
||||||
|
|
||||||
class NotFound(ApiException):
|
class NotFound(ApiException):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
from .base import ObjModelMixin, Macronutrient, OptionalMacronutrient, Calories, OptionalCalories
|
from .base import (
|
||||||
|
ObjModelMixin,
|
||||||
|
Macronutrient,
|
||||||
|
OptionalMacronutrient,
|
||||||
|
Calories,
|
||||||
|
OptionalCalories,
|
||||||
|
)
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from fooder.utils.calories import calculate_calories
|
from fooder.utils.calories import calculate_calories
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1,3 @@
|
||||||
from .repository import Repository
|
from fooder.repository.repository import Repository
|
||||||
|
|
||||||
|
__all__ = ["Repository"]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,13 @@
|
||||||
from typing import TypeVar, Generic, Type, Sequence
|
from typing import TypeVar, Generic, Type, Sequence
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy import Delete, Update, select, delete as sa_delete, update as sa_update, ColumnElement
|
from sqlalchemy import (
|
||||||
|
Delete,
|
||||||
|
Update,
|
||||||
|
ColumnElement,
|
||||||
|
select,
|
||||||
|
delete as sa_delete,
|
||||||
|
update as sa_update,
|
||||||
|
)
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
from sqlalchemy.orm.exc import StaleDataError
|
from sqlalchemy.orm.exc import StaleDataError
|
||||||
from sqlalchemy.sql import Select
|
from sqlalchemy.sql import Select
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@ from fooder.exc import NotFound
|
||||||
|
|
||||||
router = APIRouter(tags=["product"])
|
router = APIRouter(tags=["product"])
|
||||||
|
|
||||||
|
_auth_ctx = AuthContextDependency()
|
||||||
|
|
||||||
|
|
||||||
@router.get("", response_model=list[ProductModel])
|
@router.get("", response_model=list[ProductModel])
|
||||||
async def list_products(
|
async def list_products(
|
||||||
ctx: Context = Depends(AuthContextDependency()),
|
ctx: Context = Depends(_auth_ctx),
|
||||||
limit: int = 10,
|
limit: int = 10,
|
||||||
offset: int = 0,
|
offset: int = 0,
|
||||||
q: str | None = None,
|
q: str | None = None,
|
||||||
|
|
@ -22,7 +24,7 @@ async def list_products(
|
||||||
async def update_product(
|
async def update_product(
|
||||||
product_id: int,
|
product_id: int,
|
||||||
data: ProductUpdateModel,
|
data: ProductUpdateModel,
|
||||||
ctx: Context = Depends(AuthContextDependency()),
|
ctx: Context = Depends(_auth_ctx),
|
||||||
):
|
):
|
||||||
async with ctx.repo.transaction():
|
async with ctx.repo.transaction():
|
||||||
obj = await ctx.repo.product.get_by_id(product_id)
|
obj = await ctx.repo.product.get_by_id(product_id)
|
||||||
|
|
@ -33,7 +35,7 @@ async def update_product(
|
||||||
@router.get("/barcode/{barcode}", response_model=ProductModel)
|
@router.get("/barcode/{barcode}", response_model=ProductModel)
|
||||||
async def get_by_barcode(
|
async def get_by_barcode(
|
||||||
barcode: str,
|
barcode: str,
|
||||||
ctx: Context = Depends(AuthContextDependency()),
|
ctx: Context = Depends(_auth_ctx),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
return await ctx.repo.product.get_by_barcode(barcode)
|
return await ctx.repo.product.get_by_barcode(barcode)
|
||||||
|
|
@ -46,7 +48,7 @@ async def get_by_barcode(
|
||||||
@router.post("", response_model=ProductModel, status_code=201)
|
@router.post("", response_model=ProductModel, status_code=201)
|
||||||
async def create_product(
|
async def create_product(
|
||||||
data: ProductCreateModel,
|
data: ProductCreateModel,
|
||||||
ctx: Context = Depends(AuthContextDependency()),
|
ctx: Context = Depends(_auth_ctx),
|
||||||
):
|
):
|
||||||
async with ctx.repo.transaction():
|
async with ctx.repo.transaction():
|
||||||
ctrl = await ProductController.create(ctx, data)
|
ctrl = await ProductController.create(ctx, data)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ from fooder.utils.jwt import RefreshToken, generate_token_pair
|
||||||
|
|
||||||
router = APIRouter(tags=["token"])
|
router = APIRouter(tags=["token"])
|
||||||
|
|
||||||
|
_ctx = ContextDependency()
|
||||||
|
|
||||||
|
|
||||||
def gen_token_response(entity_id: int, now: datetime) -> TokenResponse:
|
def gen_token_response(entity_id: int, now: datetime) -> TokenResponse:
|
||||||
access_token, refresh_token = generate_token_pair(entity_id, now)
|
access_token, refresh_token = generate_token_pair(entity_id, now)
|
||||||
|
|
@ -23,7 +25,7 @@ def gen_token_response(entity_id: int, now: datetime) -> TokenResponse:
|
||||||
@router.post("", response_model=TokenResponse)
|
@router.post("", response_model=TokenResponse)
|
||||||
async def token_create(
|
async def token_create(
|
||||||
data: Annotated[OAuth2PasswordRequestForm, Depends()],
|
data: Annotated[OAuth2PasswordRequestForm, Depends()],
|
||||||
ctx: Context = Depends(ContextDependency()),
|
ctx: Context = Depends(_ctx),
|
||||||
) -> TokenResponse:
|
) -> TokenResponse:
|
||||||
now = ctx.clock()
|
now = ctx.clock()
|
||||||
user_ctrl = await UserController.session_start(ctx, data.username, data.password)
|
user_ctrl = await UserController.session_start(ctx, data.username, data.password)
|
||||||
|
|
@ -33,7 +35,7 @@ async def token_create(
|
||||||
@router.post("/refresh", response_model=TokenResponse)
|
@router.post("/refresh", response_model=TokenResponse)
|
||||||
async def token_refresh(
|
async def token_refresh(
|
||||||
refresh_token: str,
|
refresh_token: str,
|
||||||
ctx: Context = Depends(ContextDependency()),
|
ctx: Context = Depends(_ctx),
|
||||||
) -> TokenResponse:
|
) -> TokenResponse:
|
||||||
now = ctx.clock()
|
now = ctx.clock()
|
||||||
token = RefreshToken.decode(refresh_token)
|
token = RefreshToken.decode(refresh_token)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 80
|
max-line-length = 89
|
||||||
extend-select = B950
|
extend-select = B950
|
||||||
extend-ignore = E203,E501,E701,E712
|
extend-ignore = E203,E501,E701,E712
|
||||||
|
exclude = fooder/alembic,fooder/test
|
||||||
extend-immutable-calls =
|
extend-immutable-calls =
|
||||||
Depends
|
Depends
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue