from fastapi import APIRouter, Depends, HTTPException, Request from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, text from datetime import datetime, timedelta import hashlib, secrets from app.db.session import get_db from app.models.user import User from app.core.security import get_password_hash from app.services.email_manager import email_manager from app.services.config_service import config router = APIRouter() @router.post("/register") async def register( request: Request, email: str, password: str, first_name: str, last_name: str, db: AsyncSession = Depends(get_db) ): ip = request.client.host # 1. BOT-VÉDELEM throttle_min = await config.get_setting('registration_throttle_minutes', default=10) check_throttle = await db.execute(text(""" SELECT count(*) FROM data.audit_logs WHERE ip_address = :ip AND action = 'USER_REGISTERED' AND created_at > :t """), {'ip': ip, 't': datetime.utcnow() - timedelta(minutes=int(throttle_min))}) if check_throttle.scalar() > 0: raise HTTPException(status_code=429, detail="Túl sok próbálkozás. Várj pár percet!") # 2. REGISZTRÁCIÓ res = await db.execute(select(User).where(User.email == email)) if res.scalars().first(): raise HTTPException(status_code=400, detail="Ez az email már foglalt.") new_user = User( email=email, hashed_password=get_password_hash(password), first_name=first_name, last_name=last_name, is_active=False ) db.add(new_user) await db.flush() # 3. TOKEN & LOG raw_token = secrets.token_urlsafe(48) token_hash = hashlib.sha256(raw_token.encode()).hexdigest() await db.execute(text(""" INSERT INTO data.verification_tokens (user_id, token_hash, token_type, expires_at) VALUES (:u, :t, 'email_verify', :e) """), {'u': new_user.id, 't': token_hash, 'e': datetime.utcnow() + timedelta(days=2)}) await db.execute(text(""" INSERT INTO data.audit_logs (user_id, action, endpoint, method, ip_address) VALUES (:u, 'USER_REGISTERED', '/register', 'POST', :ip) """), {'u': new_user.id, 'ip': ip}) # 4. EMAIL KÜLDÉS verify_link = f"http://{request.headers.get('host')}/api/v1/auth/verify?token={raw_token}" email_body = f"

Szia {first_name}!

Aktiváld a fiókod: {verify_link}

" await email_manager.send_email( recipient=email, subject="Regisztráció megerősítése", body=email_body, email_type="registration", user_id=new_user.id ) await db.commit() return {"message": "Sikeres regisztráció! Ellenőrizd az email fiókodat."} @router.get("/verify") async def verify_account(token: str, db: AsyncSession = Depends(get_db)): token_hash = hashlib.sha256(token.encode()).hexdigest() query = text("SELECT user_id FROM data.verification_tokens WHERE token_hash = :t AND is_used = False") res = await db.execute(query, {'t': token_hash}) row = res.fetchone() if not row: raise HTTPException(status_code=400, detail="Érvénytelen aktiváló link") await db.execute(text("UPDATE data.users SET is_active = True WHERE id = :id"), {'id': row[0]}) await db.execute(text("UPDATE data.verification_tokens SET is_used = True WHERE token_hash = :t"), {'t': token_hash}) await db.commit() return {"message": "Fiók aktiválva!"}