Formatting everything with black

This commit is contained in:
Ian Roddis committed 2026-06-22 14:56:51 -03:00
1 parent 42a11c0dc6
commit a3539beda9
20 files changed
+173 -18

No files matched your search

+9 -3
View File
@@ -52,7 +52,9 @@ async def get_role(
):
role = await role_crud.get(db, role_id)
if role is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Role not found")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Role not found"
)
return role
@@ -65,7 +67,9 @@ async def update_role(
):
role = await role_crud.get(db, role_id)
if role is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Role not found")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Role not found"
)
return await role_crud.update(db, role, payload.model_dump(exclude_unset=True))
@@ -77,5 +81,7 @@ async def delete_role(
):
role = await role_crud.get(db, role_id)
if role is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Role not found")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Role not found"
)
await role_crud.delete(db, role)
+9 -3
View File
@@ -53,7 +53,9 @@ async def get_user(
):
user = await user_crud.get(db, user_id)
if user is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
)
return user
@@ -66,7 +68,9 @@ async def update_user(
):
user = await user_crud.get(db, user_id)
if user is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
)
return await user_crud.update(db, user, payload.model_dump(exclude_unset=True))
@@ -78,5 +82,7 @@ async def delete_user(
):
user = await user_crud.get(db, user_id)
if user is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
)
await user_crud.delete(db, user)
+1
View File
@@ -3,6 +3,7 @@
Settings are read from environment variables first, then from a `.env` file.
Environment variables always take precedence over the file.
"""
from functools import lru_cache
from pydantic_settings import BaseSettings, SettingsConfigDict
+1
View File
@@ -2,6 +2,7 @@
Works with SQLite (aiosqlite) or Postgres (asyncpg) depending on DATABASE_URL.
"""
from collections.abc import AsyncGenerator
from sqlalchemy.ext.asyncio import (
+3
View File
@@ -1,4 +1,5 @@
"""Password hashing and JWT token helpers."""
import hashlib
import uuid
from datetime import UTC, datetime, timedelta
@@ -14,6 +15,7 @@ REFRESH_TOKEN_TYPE = "refresh"
# --- Passwords ---------------------------------------------------------------
def hash_password(password: str) -> str:
return bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
@@ -27,6 +29,7 @@ def verify_password(password: str, hashed: str) -> bool:
# --- JWT ---------------------------------------------------------------------
def _create_token(
subject: str | int,
expires_delta: timedelta,
+1
View File
@@ -66,6 +66,7 @@ async def delete(db: AsyncSession, role: Role) -> None:
# --- Permissions -------------------------------------------------------------
async def list_permissions(db: AsyncSession) -> list[Permission]:
result = await db.execute(select(Permission).order_by(Permission.name))
return list(result.scalars().all())
+3
View File
@@ -1,4 +1,5 @@
"""Shared FastAPI dependencies: DB session, current user, RBAC enforcement."""
import jwt
from fastapi import Depends, HTTPException, Request, status
from fastapi.security import OAuth2PasswordBearer
@@ -44,6 +45,7 @@ async def _user_from_token(token: str | None, db: AsyncSession) -> User | None:
# --- JSON API auth -----------------------------------------------------------
async def get_current_user(
request: Request,
bearer: str | None = Depends(oauth2_scheme),
@@ -86,6 +88,7 @@ def require_superuser(user: User = Depends(get_current_user)) -> User:
# --- Web (HTMX) auth ---------------------------------------------------------
async def get_current_web_user(
request: Request,
db: AsyncSession = Depends(get_db),
+1
View File
@@ -1,4 +1,5 @@
"""Import all models so they register with ``Base.metadata``."""
from app.models.associations import role_permissions, user_roles
from app.models.permission import Permission
from app.models.refresh_token import RefreshToken
+6 -1
View File
@@ -1,4 +1,5 @@
"""Many-to-many association tables for RBAC."""
from sqlalchemy import Column, ForeignKey, Table
from app.core.database import Base
@@ -14,5 +15,9 @@ role_permissions = Table(
"role_permissions",
Base.metadata,
Column("role_id", ForeignKey("roles.id", ondelete="CASCADE"), primary_key=True),
Column("permission_id", ForeignKey("permissions.id", ondelete="CASCADE"), primary_key=True),
Column(
"permission_id",
ForeignKey("permissions.id", ondelete="CASCADE"),
primary_key=True,
),
)
+4 -1
View File
@@ -1,4 +1,5 @@
"""Token issuance / rotation shared by the JSON API and the HTMX UI."""
import jwt
from sqlalchemy.ext.asyncio import AsyncSession
@@ -30,7 +31,9 @@ class RefreshError(Exception):
pass
async def rotate_refresh_token(db: AsyncSession, raw_refresh: str) -> tuple[str, str, User]:
async def rotate_refresh_token(
db: AsyncSession, raw_refresh: str
) -> tuple[str, str, User]:
"""Validate a refresh token, revoke it, and issue a fresh pair.
Raises ``RefreshError`` if the token is invalid, expired, or already revoked.
+7 -1
View File
@@ -1,4 +1,5 @@
"""HTMX-driven admin dashboard for users and roles."""
from fastapi import APIRouter, Depends, Form, HTTPException, Request, status
from fastapi.responses import HTMLResponse, RedirectResponse, Response
from sqlalchemy.ext.asyncio import AsyncSession
@@ -34,6 +35,7 @@ async def admin_home():
# --- Users -------------------------------------------------------------------
@router.get("/users", response_class=HTMLResponse)
async def users_page(
request: Request,
@@ -74,7 +76,10 @@ async def create_user(
return templates.TemplateResponse(
request,
"admin/_users_table.html",
{"users": await user_crud.list_users(db), "roles": await role_crud.list_roles(db)},
{
"users": await user_crud.list_users(db),
"roles": await role_crud.list_roles(db),
},
)
@@ -152,6 +157,7 @@ async def delete_user(
# --- Roles -------------------------------------------------------------------
@router.get("/roles", response_class=HTMLResponse)
async def roles_page(
request: Request,
+1 -3
View File
@@ -30,9 +30,7 @@ async def dashboard(
request: Request,
user: User = Depends(get_current_web_user),
):
return templates.TemplateResponse(
request, "dashboard.html", {"user": user}
)
return templates.TemplateResponse(request, "dashboard.html", {"user": user})
@router.get("/login", response_class=HTMLResponse)