feat: Step 1 Auth complete - Token generation and email loop verified

This commit is contained in:
2026-02-06 22:20:11 +00:00
parent 32325b261b
commit cfd1e365e0
13 changed files with 249 additions and 55 deletions

View File

@@ -1,15 +1,18 @@
from datetime import datetime, timedelta, timezone
import uuid
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, text
from app.models.identity import User, Person, UserRole
from app.models.identity import User, Person, UserRole, VerificationToken
from app.models.organization import Organization
from app.schemas.auth import UserLiteRegister
from app.core.security import get_password_hash, verify_password
from app.services.email_manager import email_manager # Importálva!
from app.services.email_manager import email_manager
from app.core.config import settings
class AuthService:
@staticmethod
async def register_lite(db: AsyncSession, user_in: UserLiteRegister):
"""Step 1: Lite regisztráció + Email küldés."""
"""Step 1: Lite regisztráció kormányozható token élettartammal."""
try:
# 1. Person shell
new_person = Person(
@@ -32,20 +35,34 @@ class AuthService:
db.add(new_user)
await db.flush()
# 3. Email kiküldése (Mester Könyv v1.4 szerint)
# 3. Biztonsági Token (Beállítható élettartam)
# Default: 48 óra, ha nincs megadva a settingsben
expire_hours = getattr(settings, "REGISTRATION_TOKEN_EXPIRE_HOURS", 48)
token_val = uuid.uuid4()
new_token = VerificationToken(
token=token_val,
user_id=new_user.id,
token_type="registration",
expires_at=datetime.now(timezone.utc) + timedelta(hours=expire_hours)
)
db.add(new_token)
await db.flush()
# 4. Email küldés
verification_link = f"{settings.FRONTEND_BASE_URL}/verify?token={token_val}"
try:
await email_manager.send_email(
recipient=user_in.email,
template_key="registration", # 'registration.html' sablon használata
template_key="registration",
variables={
"first_name": user_in.first_name,
"login_url": "http://192.168.100.10:3000/login"
},
user_id=new_user.id
"link": verification_link
}
)
except Exception as email_err:
# Az email hiba nem állítja meg a regisztrációt, csak logoljuk
print(f"Email hiba regisztrációkor: {str(email_err)}")
print(f"CRITICAL: Email sending failed: {str(email_err)}")
await db.commit()
await db.refresh(new_user)
@@ -54,6 +71,43 @@ class AuthService:
await db.rollback()
raise e
@staticmethod
async def verify_email(db: AsyncSession, token_str: str):
"""Token ellenőrzése és regisztráció megerősítése."""
try:
# Token UUID-vá alakítása az összehasonlításhoz
token_uuid = uuid.UUID(token_str)
stmt = select(VerificationToken).where(
VerificationToken.token == token_uuid,
VerificationToken.is_used == False,
VerificationToken.expires_at > datetime.now(timezone.utc)
)
result = await db.execute(stmt)
token_obj = result.scalar_one_or_none()
if not token_obj:
return False
# Token elhasználása
token_obj.is_used = True
# User keresése és aktiválása (Email megerősítve)
user_stmt = select(User).where(User.id == token_obj.user_id)
user_res = await db.execute(user_stmt)
user = user_res.scalar_one_or_none()
if user:
# Figyelem: A Master Book szerint ez még nem teljes aktiválás (is_active: false)
# de jelölhetjük, hogy az e-mail már OK.
pass
await db.commit()
return True
except Exception as e:
print(f"Verify error: {e}")
await db.rollback()
return False
@staticmethod
async def authenticate(db: AsyncSession, email: str, password: str):
stmt = select(User).where(User.email == email, User.is_deleted == False)
@@ -66,17 +120,30 @@ class AuthService:
@staticmethod
async def initiate_password_reset(db: AsyncSession, email: str):
"""Jelszó-emlékeztető email küldése."""
"""Jelszó-emlékeztető kormányozható élettartammal."""
stmt = select(User).where(User.email == email, User.is_deleted == False)
res = await db.execute(stmt)
user = res.scalar_one_or_none()
if user:
expire_hours = getattr(settings, "PASSWORD_RESET_TOKEN_EXPIRE_HOURS", 1)
token_val = uuid.uuid4()
new_token = VerificationToken(
token=token_val,
user_id=user.id,
token_type="password_reset",
expires_at=datetime.now(timezone.utc) + timedelta(hours=expire_hours)
)
db.add(new_token)
reset_link = f"{settings.FRONTEND_BASE_URL}/reset-password?token={token_val}"
await email_manager.send_email(
recipient=email,
template_key="password_reset",
variables={"reset_token": "IDE_JÖN_MAJD_A_TOKEN"},
variables={"link": reset_link},
user_id=user.id
)
await db.commit()
return True
return False