Files
service-finder/backend/app/api/v1/endpoints/auth.py

92 lines
3.4 KiB
Python
Executable File

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"<h1>Szia {first_name}!</h1><p>Aktiváld a fiókod: <a href='{verify_link}'>{verify_link}</a></p>"
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!"}