Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@
"./backend/app/core",
"./src/obesitrack/db",
"./src/obesitrack"
],
"cursorpyright.analysis.extraPaths": [
"./backend/app/core",
"./src/obesitrack/db",
"./src/obesitrack"
]
}
202 changes: 0 additions & 202 deletions api.py

This file was deleted.

51 changes: 0 additions & 51 deletions api/__init__.py

This file was deleted.

Binary file removed api/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file modified backend/app/__pycache__/main.cpython-312.pyc
Binary file not shown.
Binary file added backend/app/api/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file added backend/app/api/__pycache__/deps.cpython-312.pyc
Binary file not shown.
Binary file added backend/app/api/__pycache__/users.cpython-312.pyc
Binary file not shown.
Binary file modified backend/app/core/__pycache__/config.cpython-312.pyc
Binary file not shown.
Binary file not shown.
13 changes: 6 additions & 7 deletions backend/app/core/config.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from pydantic import BaseSettings
from pydantic_settings import BaseSettings, SettingsConfigDict

class Settings(BaseSettings):
DATABASE_URL: str
SECRET_KEY: str
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24
ALGORITHM: str = "HS256"
DATABASE_URL: str = "sqlite+aiosqlite:///./obesitrack.db"
SECRET_KEY: str = "change-me"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24
ALGORITHM: str = "HS256"

class Config:
env_file = "../.env" # relatif à backend/app ; adapt if needed
model_config = SettingsConfigDict(env_file="../.env", env_file_encoding="utf-8")

settings = Settings()
52 changes: 18 additions & 34 deletions backend/app/core/security.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,32 @@
from datetime import datetime, timedelta, timezone
from jose import jwt, JWTError
from passlib.context import CryptContext
from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer

from app.db.session import get_db_session
from app.db.models import User
from app.core.config import settings # settings avec SECRET_KEY, ALGORITHM, ACCESS_TOKEN_EXPIRE_MINUTES
from app.core.config import settings

pwd_ctx = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2 = OAuth2PasswordBearer(tokenUrl="/auth/token")

# ----------------- Utils Hash -----------------
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_ctx.verify(plain_password, hashed_password)
return pwd_ctx.verify(plain_password, hashed_password)


def hash_password(password: str) -> str:
return pwd_ctx.hash(password)
return pwd_ctx.hash(password)


# ----------------- JWT -----------------
def create_access_token(sub: str, role: str, expires_minutes: int | None = None) -> str:
expire = datetime.now(timezone.utc) + timedelta(
minutes=expires_minutes or settings.ACCESS_TOKEN_EXPIRE_MINUTES
)
payload = {"sub": sub, "role": role, "exp": expire}
return jwt.encode(payload, settings.SECRET_KEY, algorithm=settings.ALGORITHM)

# ----------------- Dépendances FastAPI -----------------
def get_current_user(token: str = Depends(oauth2), db=Depends(get_db_session)) -> User:
credentials_exception = HTTPException(status_code=401, detail="Could not validate credentials")
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
username = payload.get("sub")
if username is None:
raise credentials_exception

user = db.query(User).filter_by(email=username).first()
if not user:
raise credentials_exception
return user
except JWTError:
raise credentials_exception

def require_admin(user: User = Depends(get_current_user)) -> User:
if user.role != "admin":
raise HTTPException(status_code=403, detail="Admin privilege required")
return user
expire = datetime.now(timezone.utc) + timedelta(
minutes=expires_minutes or settings.ACCESS_TOKEN_EXPIRE_MINUTES
)
payload = {"sub": sub, "role": role, "exp": expire}
return jwt.encode(payload, settings.SECRET_KEY, algorithm=settings.ALGORITHM)


def decode_access_token(token: str) -> dict | None:
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
return payload
except JWTError:
return None
Binary file modified backend/app/db/__pycache__/session.cpython-312.pyc
Binary file not shown.
26 changes: 11 additions & 15 deletions backend/app/db/session.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
from sqlite3 import SQLITE_LIMIT_COMPOUND_SELECT
from sqlalchemy.ext.asyncio import create_async_engine, AsyncEngine
from sqlalchemy.orm import sessionmaker
from obesitdb.database import SessionLocal
from sqlalchemy.ext.asyncio import create_async_engine, AsyncEngine, AsyncSession
from sqlalchemy.orm import sessionmaker, declarative_base
from app.core.config import settings
from session import AsyncSession


DATABASE_URL = settings.DATABASE_URL
# Ensure async driver for PostgreSQL if using psycopg2
if DATABASE_URL.startswith("postgresql+psycopg2"):
DATABASE_URL = DATABASE_URL.replace("postgresql+psycopg2", "postgresql+asyncpg")

engine: AsyncEngine = create_async_engine(DATABASE_URL, echo=True, future=True)
engine: AsyncEngine = create_async_engine(DATABASE_URL, echo=False, future=True)

async_session = sessionmaker(
engine, class_=AsyncSession, expire_on_commit=False
engine, class_=AsyncSession, expire_on_commit=False, autoflush=False, autocommit=False
)

Base = declarative_base()

async def init_db():
async with engine.begin() as conn:
await conn.run_sync(SQLITE_LIMIT_COMPOUND_SELECT.metadata.create_all)

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
from app.db import models # noqa: F401 - ensure models are imported for metadata
await conn.run_sync(Base.metadata.create_all)
Loading
Loading