Skip to content

Commit

Permalink
Merge pull request #8 from FinemechanicPub/dev
Browse files Browse the repository at this point in the history
Update
  • Loading branch information
FinemechanicPub authored Aug 24, 2024
2 parents 78f8c09 + 89647d6 commit 79148d2
Show file tree
Hide file tree
Showing 26 changed files with 857 additions and 101 deletions.
36 changes: 36 additions & 0 deletions backend/alembic/versions/1f37e3800cd9_add_menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Add Menu
Revision ID: 1f37e3800cd9
Revises: 81641f63833f
Create Date: 2024-08-24 02:39:40.192287
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '1f37e3800cd9'
down_revision: Union[str, None] = '81641f63833f'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('menu',
sa.Column('order', sa.SmallInteger(), nullable=False),
sa.Column('title', sa.String(), nullable=False),
sa.Column('query', sa.JSON(), nullable=False),
sa.Column('id', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('id', name=op.f('pk_menu'))
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('menu')
# ### end Alembic commands ###
59 changes: 59 additions & 0 deletions backend/app/api/endpoints/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from fastapi import APIRouter, Depends, status
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.user import superuser
from app.schemas.menu import MenuBase, MenuResponse, MenuUpdateRequest
from app.repositories.menu import menu_repository
from app.core.db import get_async_session
from app.api.exceptions import MenuNotFoundException

router = APIRouter(prefix="/main", tags=["Main"])


@router.get("/menu/", response_model=list[MenuResponse])
async def list_menu(session: AsyncSession = Depends(get_async_session)):
return await menu_repository.list(session)


@router.post(
"/menu/",
response_model=MenuResponse,
response_model_exclude_none=True,
status_code=status.HTTP_201_CREATED,
dependencies=[Depends(superuser)],
)
async def create_menu(
menu_data: MenuBase,
session: AsyncSession = Depends(get_async_session),
):
return await menu_repository.create(session, menu_data)


@router.patch(
"/menu/{menu_id}/",
response_model=MenuResponse,
dependencies=[Depends(superuser)],
)
async def update_menu(
menu_id: int,
menu_data: MenuUpdateRequest,
session: AsyncSession = Depends(get_async_session),
):
menu = await menu_repository.get(session, menu_id)
if not menu:
raise MenuNotFoundException
return await menu_repository.update(session, menu, menu_data)


@router.delete(
"/menu/{menu_id}/",
status_code=status.HTTP_204_NO_CONTENT,
dependencies=[Depends(superuser)],
)
async def delete_menu(
menu_id: int, session: AsyncSession = Depends(get_async_session)
):
menu = await menu_repository.get(session, menu_id)
if not menu:
raise MenuNotFoundException
await menu_repository.remove(session, menu)
7 changes: 7 additions & 0 deletions backend/app/api/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@ def __init__(self):
super().__init__(
status_code=status.HTTP_400_BAD_REQUEST, detail="User not verified"
)


class MenuNotFoundException(HTTPException):
def __init__(self):
super().__init__(
status_code=status.HTTP_404_NOT_FOUND, detail="Menu not found"
)
2 changes: 2 additions & 0 deletions backend/app/api/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from app.api.endpoints.cover import router as cover_router
from app.api.endpoints.game import router as game_router
from app.api.endpoints.main import router as main_page_router
from app.api.endpoints.piece import router as piece_router
from app.api.endpoints.play import router as play_router
from app.api.endpoints.user import router as user_router
Expand All @@ -11,6 +12,7 @@
main_router = APIRouter(prefix="/api/v1")
main_router.include_router(cover_router)
main_router.include_router(game_router)
main_router.include_router(main_page_router)
main_router.include_router(piece_router)
main_router.include_router(play_router)
main_router.include_router(user_router)
Expand Down
1 change: 1 addition & 0 deletions backend/app/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

from app.models.base import Base # noqa
from app.models.game import Game, GamePieces, Piece, PieceRotation # noqa
from app.models.menu import Menu # noqa
from app.models.user import User # noqa
1 change: 1 addition & 0 deletions backend/app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Settings(BaseSettings):
first_superuser_email: EmailStr | Literal[""] = ""
first_superuser_password: str = ""
unverified_user_can_login: bool = True
token_seconds_lifetime: int = 60 * 60 * 24 * 30
max_cells: int = 120
page_limit: int = 20
max_page: int = 100
Expand Down
4 changes: 3 additions & 1 deletion backend/app/core/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ def get_database_strategy(
get_access_token_db
),
) -> DatabaseStrategy:
return DatabaseStrategy(access_token_db, lifetime_seconds=3600)
return DatabaseStrategy(
access_token_db, lifetime_seconds=settings.token_seconds_lifetime
)


cookie_transport = CookieTransport(cookie_name="puzzleuserauth")
Expand Down
16 changes: 16 additions & 0 deletions backend/app/models/menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from sqlalchemy import JSON, SmallInteger
from sqlalchemy.orm import Mapped, mapped_column

from app.models.base import Base


class Menu(Base):
order: Mapped[int] = mapped_column(SmallInteger)
title: Mapped[str]
query: Mapped[dict[str, str]] = mapped_column(JSON)

def __repr__(self) -> str:
return (
f"Menu(id={self.id}, title={self.title}, "
f"query={self.query}, order={self.order})"
)
9 changes: 9 additions & 0 deletions backend/app/repositories/menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from app.models.menu import Menu
from app.repositories.repository import RepositoryBase


class MenuRepository(RepositoryBase[Menu]):
pass


menu_repository = MenuRepository(Menu)
4 changes: 2 additions & 2 deletions backend/app/schemas/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
computed_field,
field_validator,
)
from pydantic_core.core_schema import FieldValidationInfo
from pydantic_core.core_schema import ValidationInfo


class PieceColor(BaseModel):
piece_id: int
color: int | str

@field_validator("color")
def validate_color(cls, value, info: FieldValidationInfo):
def validate_color(cls, value, info: ValidationInfo):
if isinstance(value, str):
return int(value, 16)
if isinstance(value, int):
Expand Down
20 changes: 20 additions & 0 deletions backend/app/schemas/menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from typing import Optional
from pydantic import BaseModel, ConfigDict, Field


class MenuBase(BaseModel):
title: str = Field(..., min_length=1)
query: dict[str, str | int]
order: int = Field(..., ge=0)


class MenuUpdateRequest(BaseModel):
title: Optional[str] = Field(None, min_length=1)
query: Optional[dict[str, str | int]] = Field(None)
order: Optional[int] = Field(None, ge=0)


class MenuResponse(MenuBase):
id: int

model_config = ConfigDict(from_attributes=True)
2 changes: 1 addition & 1 deletion backend/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def create():
@click.argument("height", type=click.INT)
@click.argument("width", type=click.INT)
@click.argument("piece_size", type=click.INT)
@click.argument("limit", type=click.INT, default=100)
@click.argument("limit", type=click.INT, default=500)
def create_games(
height: int,
width: int,
Expand Down
76 changes: 75 additions & 1 deletion backend/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ black = "^24.8.0"

[tool.poetry.group.test.dependencies]
pytest = "^8.3.2"
httpx = "^0.27.0"
pytest-asyncio = "^0.24.0"
aiosqlite = "^0.20.0"

[build-system]
requires = ["poetry-core"]
Expand Down
5 changes: 5 additions & 0 deletions backend/test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
aiosqlite==0.20.0 ; python_version >= "3.10" and python_version < "4.0"
alembic==1.13.2 ; python_version >= "3.10" and python_version < "4.0"
annotated-types==0.7.0 ; python_version >= "3.10" and python_version < "4.0"
anyio==4.4.0 ; python_version >= "3.10" and python_version < "4.0"
Expand All @@ -7,6 +8,7 @@ async-timeout==4.0.3 ; python_version >= "3.10" and python_version < "3.12.0"
asyncpg==0.29.0 ; python_version >= "3.10" and python_version < "4.0"
bcrypt==4.1.2 ; python_version >= "3.10" and python_version < "4.0"
cachetools==5.4.0 ; python_version >= "3.10" and python_version < "4.0"
certifi==2024.7.4 ; python_version >= "3.10" and python_version < "4.0"
cffi==1.16.0 ; python_version >= "3.10" and python_version < "4.0"
click==8.1.7 ; python_version >= "3.10" and python_version < "4.0"
colorama==0.4.6 ; python_version >= "3.10" and python_version < "4.0" and (sys_platform == "win32" or platform_system == "Windows")
Expand All @@ -19,7 +21,9 @@ fastapi-users==13.0.0 ; python_version >= "3.10" and python_version < "4.0"
fastapi==0.112.0 ; python_version >= "3.10" and python_version < "4.0"
greenlet==3.0.3 ; python_version >= "3.10" and python_version < "4.0"
h11==0.14.0 ; python_version >= "3.10" and python_version < "4.0"
httpcore==1.0.5 ; python_version >= "3.10" and python_version < "4.0"
httptools==0.6.1 ; python_version >= "3.10" and python_version < "4.0"
httpx==0.27.0 ; python_version >= "3.10" and python_version < "4.0"
idna==3.7 ; python_version >= "3.10" and python_version < "4.0"
iniconfig==2.0.0 ; python_version >= "3.10" and python_version < "4.0"
makefun==1.15.4 ; python_version >= "3.10" and python_version < "4.0"
Expand All @@ -34,6 +38,7 @@ pydantic-core==2.20.1 ; python_version >= "3.10" and python_version < "4.0"
pydantic-settings==2.4.0 ; python_version >= "3.10" and python_version < "4.0"
pydantic==2.8.2 ; python_version >= "3.10" and python_version < "4.0"
pyjwt[crypto]==2.8.0 ; python_version >= "3.10" and python_version < "4.0"
pytest-asyncio==0.24.0 ; python_version >= "3.10" and python_version < "4.0"
pytest==8.3.2 ; python_version >= "3.10" and python_version < "4.0"
python-dotenv==1.0.1 ; python_version >= "3.10" and python_version < "4.0"
python-multipart==0.0.9 ; python_version >= "3.10" and python_version < "4.0"
Expand Down
Empty file.
Loading

0 comments on commit 79148d2

Please sign in to comment.