wahnsinn vibe
This commit is contained in:
155
backend/apps/auth/__init__.py
Normal file
155
backend/apps/auth/__init__.py
Normal file
@@ -0,0 +1,155 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from pydantic import BaseModel, EmailStr
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from core.db import get_db
|
||||
from core.events import event_bus
|
||||
from core.security import (
|
||||
decode_token,
|
||||
get_current_user_id,
|
||||
hash_password,
|
||||
make_access_token,
|
||||
make_refresh_token,
|
||||
verify_password,
|
||||
)
|
||||
|
||||
from .models import User
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class RegisterIn(BaseModel):
|
||||
email: EmailStr
|
||||
password: str
|
||||
name: str = ""
|
||||
|
||||
|
||||
class LoginIn(BaseModel):
|
||||
email: EmailStr
|
||||
password: str
|
||||
|
||||
|
||||
class TokenOut(BaseModel):
|
||||
access_token: str
|
||||
refresh_token: str
|
||||
token_type: str = "bearer"
|
||||
role: str
|
||||
user_id: int
|
||||
|
||||
|
||||
class UserOut(BaseModel):
|
||||
id: int
|
||||
email: str
|
||||
name: str
|
||||
role: str
|
||||
locale: str
|
||||
|
||||
|
||||
class UpdateMeIn(BaseModel):
|
||||
name: str | None = None
|
||||
locale: str | None = None
|
||||
|
||||
|
||||
class ChangePasswordIn(BaseModel):
|
||||
old_password: str
|
||||
new_password: str
|
||||
|
||||
|
||||
@router.post("/register", response_model=TokenOut)
|
||||
def register(body: RegisterIn, db: Session = Depends(get_db)):
|
||||
if db.query(User).filter_by(email=body.email.lower()).first():
|
||||
raise HTTPException(400, "Email already registered")
|
||||
user = User(
|
||||
email=body.email.lower(),
|
||||
password_hash=hash_password(body.password),
|
||||
name=body.name,
|
||||
role="customer",
|
||||
)
|
||||
db.add(user)
|
||||
db.commit()
|
||||
db.refresh(user)
|
||||
event_bus.publish(
|
||||
"user.registered",
|
||||
{"user_id": user.id, "email": user.email},
|
||||
db=db,
|
||||
)
|
||||
return TokenOut(
|
||||
access_token=make_access_token(user.id, user.role),
|
||||
refresh_token=make_refresh_token(user.id, user.role),
|
||||
role=user.role,
|
||||
user_id=user.id,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/login", response_model=TokenOut)
|
||||
def login(body: LoginIn, db: Session = Depends(get_db)):
|
||||
user = db.query(User).filter_by(email=body.email.lower()).first()
|
||||
if not user or not verify_password(body.password, user.password_hash):
|
||||
raise HTTPException(401, "Invalid credentials")
|
||||
event_bus.publish("user.logged_in", {"user_id": user.id}, db=db)
|
||||
return TokenOut(
|
||||
access_token=make_access_token(user.id, user.role),
|
||||
refresh_token=make_refresh_token(user.id, user.role),
|
||||
role=user.role,
|
||||
user_id=user.id,
|
||||
)
|
||||
|
||||
|
||||
class RefreshIn(BaseModel):
|
||||
refresh_token: str
|
||||
|
||||
|
||||
@router.post("/refresh", response_model=TokenOut)
|
||||
def refresh(body: RefreshIn, db: Session = Depends(get_db)):
|
||||
claims = decode_token(body.refresh_token)
|
||||
if claims.get("type") != "refresh":
|
||||
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Not a refresh token")
|
||||
user_id = int(claims["sub"])
|
||||
user = db.get(User, user_id)
|
||||
if not user:
|
||||
raise HTTPException(401, "User gone")
|
||||
return TokenOut(
|
||||
access_token=make_access_token(user.id, user.role),
|
||||
refresh_token=make_refresh_token(user.id, user.role),
|
||||
role=user.role,
|
||||
user_id=user.id,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/me", response_model=UserOut)
|
||||
def me(user_id: int = Depends(get_current_user_id), db: Session = Depends(get_db)):
|
||||
user = db.get(User, user_id)
|
||||
if not user:
|
||||
raise HTTPException(404, "User not found")
|
||||
return UserOut(id=user.id, email=user.email, name=user.name, role=user.role, locale=user.locale)
|
||||
|
||||
|
||||
@router.put("/me", response_model=UserOut)
|
||||
def update_me(
|
||||
body: UpdateMeIn,
|
||||
user_id: int = Depends(get_current_user_id),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
user = db.get(User, user_id)
|
||||
if not user:
|
||||
raise HTTPException(404, "User not found")
|
||||
if body.name is not None:
|
||||
user.name = body.name
|
||||
if body.locale is not None:
|
||||
user.locale = body.locale
|
||||
db.commit()
|
||||
return UserOut(id=user.id, email=user.email, name=user.name, role=user.role, locale=user.locale)
|
||||
|
||||
|
||||
@router.post("/change-password")
|
||||
def change_password(
|
||||
body: ChangePasswordIn,
|
||||
user_id: int = Depends(get_current_user_id),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
user = db.get(User, user_id)
|
||||
if not user or not verify_password(body.old_password, user.password_hash):
|
||||
raise HTTPException(400, "Old password wrong")
|
||||
user.password_hash = hash_password(body.new_password)
|
||||
db.commit()
|
||||
return {"ok": True}
|
||||
Reference in New Issue
Block a user