# 🔐 Teljes Regisztrációs Folyamat Audit — 2026-06-07
## 📋 Összefoglaló
A Service Finder regisztrációs rendszere **4 fázisból** áll, amelyek a Lite regisztrációtól a teljes KYC-n át a felhasználói fiók aktiválásáig vezetnek. A folyamat **több rétegű** (frontend → backend → adatbázis → e-mail), és **Shadow Identity** kezeléssel, **Device Fingerprinting**-gel, valamint **dinamikus konfigurációval** bővül.
---
## 🧭 1. Regisztrációs Folyamat Áttekintése (4 Fázis)
```mermaid
flowchart LR
A[Lite Regisztráció
1. Fázis] -->|Email + Jelszó| B[Email Verifikáció
Magic Link
2. Fázis]
B -->|Auto-login JWT| C[KYC 1. lépés
Cím - Soft KYC
3. Fázis]
C --> D[KYC 2. lépés
Személyes adatok
4. Fázis]
D --> E[Fiók Aktiválva
Szervezet + Pénztárca]
```
---
## 📦 2. Fázis 1: Lite Regisztráció
### 2.1 Frontend: LoginModal.vue
- **Belépési pont:** A `LoginModal.vue` 3D kártya-forgató (CSS rotateY/rotateX) a `register` oldallapon.
- **Gyűjtött mezők:** `lastName`, `firstName`, `regEmail`, `regPassword` (min. 8 karakter)
- **FingerprintJS:** A böngésző eszköz-ujjlenyomatát a `FingerprintJS` komponens generálja (`deviceFingerprint`).
- **Regisztráció utáni állapot:** Az email mentésre kerül `localStorage`-ba (`pending_verification_email` kulccsal), és a felhasználó átirányításra kerül a `/verify` oldalra.
- **60 másodperces cooldown:** Az újraküldés gomb 60 másodpercig inaktív (időzítés a localStorage-ban).
### 2.2 API Végpont: POST /auth/register
**Fájl:** `backend/app/api/v1/endpoints/auth.py:21`
```python
@router.post("/register", status_code=status.HTTP_201_CREATED)
async def register(user_in: UserLiteRegister, db: AsyncSession = Depends(get_db)):
```
**Bemenő adatok (Pydantic UserLiteRegister):**
| Mező | Típus | Kötelező | Megjegyzés |
|------|-------|----------|------------|
| `email` | `EmailStr` | Igen | Unique constraint |
| `password` | `str` | Igen | Min 8 karakter (dinamikus) |
| `first_name` | `str` | Igen | |
| `last_name` | `str` | Igen | |
| `region_code` | `str` | Nem | Példa: "HU", "AT" |
| `lang` | `str` | Nem | Nyelvi preferencia |
| `timezone` | `str` | Nem | |
| `referred_by_code` | `str` | Nem | P2P referral kód |
**Válasz:** `{"status": "success", "user_id": int, "email": str}`
### 2.3 Backend Szolgáltatás: AuthService.register_lite()
**Fájl:** `backend/app/services/auth_service.py:62`
**Folyamat:**
1. **Dinamikus konfiguráció lekérése** a `system.system_parameters` táblából:
- `auth_min_password_length` → alapértelmezett `8`
- `auth_default_role` → alapértelmezett `"user"`
- `auth_registration_hours` → alapértelmezett `48`
2. **Jelszó komplexitás ellenőrzése** (`_validate_password_complexity`):
- Minimális hossz (dinamikus)
- Nagybetű, kisbetű, szám követelmény?
- Regionális beállítások (pl. speciális karakterek)
3. **Email egyediség ellenőrzése** — `UniqueViolation` kezelés Sentinel audit loggal
4. **Person rekord létrehozása** (`identity.persons`):
```python
person = Person(
first_name=user_in.first_name,
last_name=user_in.last_name,
is_ghost=False, # Valódi személy
)
```
5. **User rekord létrehozása** (`identity.users`):
```python
user = User(
email=user_in.email,
hashed_password=pwd_context.hash(password),
role=default_role,
person=person, # Kapcsolat
is_active=False, # Inaktív amíg nem verifikálta az emailt
preferred_language=user_in.lang,
region_code=user_in.region_code,
referral_code=generate_secure_slug(),
)
```
6. **VerificationToken létrehozása** (`identity.verification_tokens`):
```python
token = VerificationToken(
user_id=user.id,
token_type="registration", # vagy "email_verification"
expires_at=utcnow() + timedelta(hours=reg_token_hours), # 48h
)
```
7. **Token slug generálása** (`security.generate_secure_slug()`)
8. **Email küldés** (`EmailManager.send_email()`):
- `template_key`: `"registration_verification"`
- Címzett: `user.email`
- Változók: `verification_url`, `user_name`, `expiry_hours`
9. **Sentinel Audit log:** `EVENT.REGISTRATION_INITIATED`
### 2.4 Adatbázis Írások (Fázis 1)
| Tábla | Séma | Művelet | Státusz |
|-------|------|---------|---------|
| `persons` | `identity` | `INSERT` | `is_active=False`, `is_ghost=False` |
| `users` | `identity` | `INSERT` | `is_active=False`, `role='user'` |
| `verification_tokens` | `identity` | `INSERT` | `token_type='registration'`, `expires_at=now+48h` |
---
## 📧 3. Fázis 2: Email Verifikáció (Magic Link)
### 3.1 Frontend: VerifyEmailView.vue
**Három állapot:**
| Állapot | Leírás |
|---------|--------|
| `isVerifying` | Spinner + "Email verifikálása..." szöveg, amíg a backend válaszol |
| `verifySuccess` | Zöld pipa animáció + 3 másodperces visszaszámlálás, majd átirányítás `/complete-kyc` |
| `default` | Email cím megadása + újraküldés gomb (cooldown-nal) |
**Magic Link működése:**
- A link token-t tartalmaz URL paraméterként (`?token=...`)
- A `VerifyEmailView` a token-t kiolvassa a query paraméterből
- Meghívja az `authStore.verifyAccount(token)` metódust
- Automatikusan generál egy új `deviceFingerprint`-et a FingerprintJS-el
### 3.2 Auth Store Metódus: verifyAccount()
```typescript
async function verifyAccount(verificationToken: string, deviceFingerprint?: string) {
const response = await api.post('/auth/verify-email', {
token: verificationToken,
device_fingerprint: deviceFingerprint
});
// Ha a válasz JWT token-t tartalmaz -> auto-login
if (response.data.access_token) {
// Token-ek elmentése localStorage-be
token.value = response.data.access_token;
refreshToken.value = response.data.refresh_token;
// Felhasználói profil betöltése
await fetchUser();
}
}
```
### 3.3 API Végpont: POST /auth/verify-email
**Fájl:** `backend/app/api/v1/endpoints/auth.py:142`
**Válasz:** `Token` séma (`access_token`, `refresh_token`, `token_type`, `is_active`)
### 3.4 Backend Szolgáltatás: AuthService.verify_email()
**Fájl:** `backend/app/services/auth_service.py:319`
1. **Token validálás:**
- UUID formátum ellenőrzése
- Létezik-e a token a `verification_tokens` táblában
- `is_used=False` — még nem használták fel
- `expires_at > now()` — nem járt le
2. **User aktiválás:**
```python
user.is_active = True
person.is_active = True
token.is_used = True
```
3. **Device Fingerprint rögzítés:**
```python
# Ha device_fingerprint érkezett:
device = await get_or_create_device(db, device_fingerprint)
await create_user_device_link(db, user.id, device.id)
```
4. **JWT Token generálás** (auto-login):
```python
access_token, refresh_token = create_tokens(
data={"sub": str(user.id), "role": user.role.value},
remember_me=False # Magic Link esetén nincs remember_me
)
```
5. **Sentinel Audit log:** `EVENT.EMAIL_VERIFIED`
### 3.5 Adatbázis Írások (Fázis 2)
| Tábla | Séma | Művelet | Változás |
|-------|------|---------|----------|
| `users` | `identity` | `UPDATE` | `is_active=False → True` |
| `persons` | `identity` | `UPDATE` | `is_active=False → True` |
| `verification_tokens` | `identity` | `UPDATE` | `is_used=False → True` |
| `devices` | `identity` | `INSERT/SELECT` | Ha új eszköz → létrehozás |
| `user_device_links` | `identity` | `INSERT` | User-Device kapcsolat |
---
## 🏠 4. Fázis 3: KYC 1. Lépés — Cím (Soft KYC)
### 4.1 Frontend: CompleteKycView.vue — 1. Lépés
**Gyűjtött mezők:**
| Mező | Típus | Kötelező |
|------|-------|----------|
| `country` | Select | Igen (HU/AT/SK/DE/RO/CZ) |
| `zip_code` | Input | Igen |
| `city` | Input | Igen (auto-fill zip lookup-ból) |
| `street_name` | Input | Nem |
| `street_type` | Select | Nem (utca, tér, stb.) |
| `street_number` | Input | Nem |
| `building` | Input | Nem |
| `staircase` | Input | Nem |
| `floor` | Input | Nem |
| `door` | Input | Nem |
**Speciális funkciók:**
- **Irányítószám keresés:** `/api/v1/system/zip-lookup` — automatikus város kitöltés
- **Skip gomb:** Csak irányítószám + város megadása kötelező, a többi opcionális
- **Cím adatbázis:** A `GeoService` a `data.zip_codes`, `data.streets`, `data.street_types`, `data.addresses` táblákat használja
### 4.2 API Végpont: POST /auth/complete-kyc
**Fájl:** `backend/app/api/v1/endpoints/auth.py:289`
```python
@router.post("/complete-kyc")
async def complete_kyc(
kyc_in: UserKYCComplete,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user)
):
```
### 4.3 Backend Szolgáltatás: AuthService.complete_kyc()
**Fájl:** `backend/app/services/auth_service.py:177`
**Bemenő adatok (Pydantic UserKYCComplete):**
| Mező | Típus | Kötelező |
|------|-------|----------|
| `phone` | `str` | Igen |
| `birth_place` | `str` | Igen |
| `birth_date` | `date` | Igen |
| `mothers_name` | `str` | Igen |
| `address` | nested | Igen (zip_code + city minimum) |
| `identity_docs` | `list[dict]` | Nem (ID card + driver's license) |
| `ice_contact` | `ICEContact` | Nem |
| `preferred_language` | `str` | Nem |
| `preferred_currency` | `str` | Nem |
| `device_fingerprint` | `str` | Nem |
**Alapértelmezett mezők a UserKYCComplete-ben:**
```python
phone: Optional[str] = None
birth_place: Optional[str] = None
birth_date: Optional[date] = None
mothers_name: Optional[str] = None
identity_docs: Optional[List[dict]] = None
ice_contact: Optional[ICEContact] = None
preferred_language: Optional[str] = None
preferred_currency: Optional[str] = None
```
---
## 🏢 5. Fázis 4: KYC 2. Lépés — Teljes Aktiválás
### 5.1 Frontend: CompleteKycView.vue — 2. Lépés
**Gyűjtött mezők:**
- `phone` — Telefonszám
- `identity_docs` — Dokumentumok:
- `id_card_number` + `id_card_expiry`
- `driver_license_number` + `driver_license_expiry`
- `preferred_language` / `preferred_currency` — Nyelv és pénznem preferencia
### 5.2 Auth Store Metódus: completeKyc()
```typescript
async function completeKyc(kycData: Record): Promise {
try {
await api.post('/auth/complete-kyc', kycData);
await fetchUser(); // Profil frissítése
return true;
} catch (err) {
// Hibakezelés
return false;
}
}
```
### 5.3 Backend Szolgáltatás: AuthService.complete_kyc() — Teljes logika
```mermaid
flowchart TD
A[KYC adatok érkeznek] --> B[Shadow Identity keresés]
B --> C{Van duplicate Person?}
C -->|Igen| D[Merge Person rekordok]
C -->|Nem| E[Folytatás jelenlegi Person-nal]
D --> E
E --> F[Cím létrehozása GeoService]
F --> G[Personal Organization létrehozása]
G --> H[Wallet létrehozása]
H --> I[Branch létrehozása]
I --> J[OrganizationMember létrehozása]
J --> K[Gamification XP award]
K --> L[P2P referral XP (ha van)]
L --> M[Sikeres válasz]
```
#### Részletes lépések:
1. **Shadow Identity keresés és merge:**
```python
# Ellenőrzi, hogy a person rekordhoz tartozik-e másik User
# Ha igen, összefésüli az adatokat (identity_hash alapján)
existing_person = await check_shadow_person(db, kyc_in)
if existing_person and existing_person.id != current_user.person_id:
# Merge logika: a régebbi person adatai átkerülnek az újra
await merge_persons(db, source_id=existing_person.id, target_id=current_user.person_id)
```
2. **Cím létrehozása** (GeoService.get_or_create_full_address()):
```python
address = await GeoService.get_or_create_full_address(
db, kyc_in.address.dict(), user_id=current_user.id
)
current_user.person.address_id = address.id
```
3. **Personal Organization létrehozása:**
```python
org = Organization(
name=f"{person.first_name} {person.last_name} Személyes",
org_type="personal",
owner_id=current_user.id,
is_verified=True,
)
```
4. **Wallet létrehozása** (`finance.wallets`):
```python
wallet = Wallet(
user_id=current_user.id,
earned_credits=0,
purchased_credits=0,
service_coins=0,
currency=kyc_in.preferred_currency or "HUF",
)
```
5. **Branch létrehozása** (`data.branches`):
```python
branch = Branch(
organization_id=org.id,
address_id=address.id,
name="Központi telephely",
branch_type="headquarters",
)
```
6. **OrganizationMember létrehozása** (`data.organization_members`):
```python
member = OrganizationMember(
organization_id=org.id,
user_id=current_user.id,
role="owner",
)
```
7. **Gamification XP award:**
- `ProfileCompleted` esemény → +50 XP
- `EmailVerified` + `ProfileCompleted` kombó → +100 XP (first_login bonus)
8. **P2P referral XP:**
- Ha `referred_by_id` be van állítva a User-en:
- A referrer +100 XP-t kap (`ReferralUsed` esemény)
9. **Sentinel Audit log:** `EVENT.KYC_COMPLETED`
### 5.4 Adatbázis Írások (Fázis 4)
| Tábla | Séma | Művelet |
|-------|------|---------|
| `persons` | `identity` | `UPDATE` (phone, birth_data, address_id, identity_docs, ice_contact) |
| `addresses` | `data` | `INSERT` |
| `zip_codes` | `data` | `INSERT/SELECT` (auto-learning) |
| `streets` | `data` | `INSERT/SELECT` (auto-learning) |
| `organizations` | `data` | `INSERT` (personal org) |
| `wallets` | `finance` | `INSERT` |
| `branches` | `data` | `INSERT` (headquarters) |
| `organization_members` | `data` | `INSERT` (owner role) |
| `gamification_events` | `gamification` | `INSERT` (XP award) |
---
## 🔑 6. Token Élettartamok és Kezelés
### 6.1 JWT Token-ek
**Forrás:** `backend/app/core/security.py:17`
```python
def create_tokens(data: Dict[str, Any], remember_me: bool = False) -> Tuple[str, str]:
# Access Token
access_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) # 30 perc
access_token = create_access_token(data=data, expires_delta=access_expires)
# Refresh Token
refresh_days = settings.REFRESH_TOKEN_EXPIRE_DAYS # 7 nap (alap)
if remember_me:
refresh_days = 30 # 30 nap ha "Emlékezz rám"
refresh_expires = timedelta(days=refresh_days)
refresh_token = create_refresh_token(data=data, expires_delta=refresh_expires)
return access_token, refresh_token
```
| Token | Élettartam | Beállítási Forrás |
|-------|-----------|-------------------|
| **Access Token** | **30 perc** | `settings.ACCESS_TOKEN_EXPIRE_MINUTES` (static) |
| **Refresh Token** (alap) | **1 nap** | `settings.REFRESH_TOKEN_EXPIRE_DAYS=7` → runtime override: 1 nap |
| **Refresh Token** (remember_me) | **30 nap** | Runtime override `remember_me=True` |
| **Verification Token** (regisztráció) | **48 óra** | `system_parameters.auth_registration_hours` (dinamikus) |
| **Verification Token** (jelszó reset) | **2 óra** | `system_parameters.auth_password_reset_hours` (dinamikus) |
### 6.2 Token Használati Minta
```
Regisztráció → Nincs token (csak user_id + email vissza)
Email verifikáció → Access (30p) + Refresh (1d/30d) → Auto-login
Bejelentkezés → Access (30p) + Refresh (1d/30d)
Jelszó reset → Nincs token (csak sikeres üzenet)
```
### 6.3 Dekódolás és Validáció
**Forrás:** `backend/app/core/security.py:43`
```python
def decode_token(token: str) -> Optional[Dict[str, Any]]:
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[ALGORITHM])
return payload
except JWTError:
return None
```
### 6.4 Dependency Injection: get_current_user()
**Fájl:** `backend/app/api/deps.py:55`
```python
async def get_current_user(
token: str = Depends(oauth2_scheme), # Authorization: Bearer
db: AsyncSession = Depends(get_db),
) -> User:
payload = decode_token(token)
if payload is None:
raise HTTPException(status_code=401, detail="INVALID_TOKEN")
user = await db.get(User, int(payload.get("sub")))
if user is None:
raise HTTPException(status_code=401, detail="USER_NOT_FOUND")
return user
```
---
## 🖥️ 7. Frontend Felületek Részletes Leírása
### 7.1 LoginModal.vue — 3D Kártya-forgató
**Technológia:** CSS 3D transzformációk (`rotateY`, `rotateX`)
**Négy oldal:**
| Oldal | CSS Osztály | Trigger |
|-------|-------------|---------|
| **Login** | `.card-face-front` | Alapértelmezett |
| **Register** | `.card-face-back` | "Regisztráció" gomb |
| **Forgot Password** | `.card-face-left` | "Elfelejtett jelszó" link |
| **Resend Verification** | `.card-face-top` | "Újraküldés" link |
**Login folyamat:**
1. `email` + `password` → `authStore.login()`
2. Ha `isKycComplete` = false → `/complete-kyc` redirect
3. Ha `isKycComplete` = true → `/dashboard` redirect
**Remember Me:** localStorage-ban tárolva (`login_remember`)
### 7.2 VerifyEmailView.vue — Verifikációs Oldal
**URL:** `/verify?token=...`
**3 állapot:**
1. **Verifying** (`isVerifying = true`):
- Spinner komponens
- "Email cím ellenőrzése..." szöveg
- Token kiolvasása a URL-ből
2. **Success** (`verifySuccess = true`):
- Zöld pipa animáció (CSS)
- "Email cím sikeresen megerősítve!"
- 3 másodperces countdown → `/complete-kyc`
3. **Default** (nincs token a URL-ben):
- Email input mező
- "Újraküldés" gomb
- 60 másodperes cooldown
### 7.3 CompleteKycView.vue — 2-lépéses KYC
**Védett route:** Csak hitelesített felhasználók számára (`requiresAuth` guard).
**Step 1 — Cím adatok:**
- Ország választó (HU/AT/SK/DE/RO/CZ flag-ekkel)
- Irányítószám + automatikus város kitöltés
- Utca, házszám, épület, lépcsőház, emelet, ajtó (opcionális)
- "Kihagyás" gomb (ha csak zip+city van megadva)
**Step 2 — Személyes adatok:**
- Telefonszám
- Születési hely, dátum
- Anyja neve
- Dokumentumok (személyi + jogosítvány)
- ICE kapcsolattartó
- Nyelv és pénznem preferencia
### 7.4 Router Guardok
**Fájl:** `frontend/src/router/index.ts:49`
```typescript
router.beforeEach(async (to, _from, next) => {
const authStore = useAuthStore();
await authStore.init(); // Token-ek betöltése localStorage-ból
if (to.meta.requiresAuth && !authStore.isAuthenticated) {
next('/'); // Vissza a Landing-re
} else if (to.path === '/' && authStore.isAuthenticated) {
next('/dashboard'); // Már bejelentkezett → dashboard
} else {
next();
}
});
```
---
## 🗄️ 8. Adatbázis Séma Részletek
### 8.1 Person — `identity.persons`
| Mező | Típus | Default | Megjegyzés |
|------|-------|---------|------------|
| `id` | `BigInt` PK | auto | |
| `uuid` | `UUID` | `uuid4()` | Publikus azonosító |
| `address_id` | `Int FK` | `NULL` | → `data.addresses.id` |
| `first_name` | `String(100)` | | |
| `last_name` | `String(100)` | | |
| `middle_name` | `String(100)` | `NULL` | |
| `phone` | `String(20)` | `NULL` | |
| `birth_place` | `String(200)` | `NULL` | |
| `birth_date` | `Date` | `NULL` | |
| `mothers_name` | `String(200)` | `NULL` | |
| `identity_hash` | `String(64)` | `NULL` | SHA-256 hash a deduplikációhoz |
| `identity_docs` | `JSON` | `NULL` | Dokumentumok listája |
| `ice_contact` | `JSON` | `NULL` | ICE kapcsolattartó |
| `avatar_url` | `String(500)` | `NULL` | |
| `lifetime_xp` | `Integer` | `0` | Gamification |
| `penalty_points` | `Integer` | `0` | |
| `social_reputation` | `Float` | `0.0` | |
| `is_sales_agent` | `Boolean` | `False` | |
| `is_active` | `Boolean` | `False` | Aktiválás után `True` |
| `is_ghost` | `Boolean` | `False` | Ideiglenes rekord |
| `merged_into_id` | `Int FK` | `NULL` | Shadow Identity merge cél |
| `created_at` | `DateTime` | `utcnow()` | |
| `updated_at` | `DateTime` | `utcnow()` | |
**Relációk:**
- `users: List[User]` — Egy személyhez több User tartozhat
- `active_user_account: User` — Az aktív User
- `address: Address` — Lakcím
- `owned_business_entities: List[Organization]` — Tulajdonolt szervezetek
### 8.2 User — `identity.users`
| Mező | Típus | Default | Megjegyzés |
|------|-------|---------|------------|
| `id` | `Int` PK | auto | |
| `email` | `String(255)` | | **UNIQUE**, login azonosító |
| `hashed_password` | `String(255)` | | bcrypt hash |
| `role` | `Enum(UserRole)` | `user` | `user`, `admin`, `superadmin`, `manager`, `agent`, `api` |
| `person_id` | `BigInt FK` | `NULL` | → `identity.persons.id` |
| `subscription_plan` | `String(50)` | `NULL` | |
| `is_vip` | `Boolean` | `False` | |
| `referral_code` | `String(20)` | `NULL` | **UNIQUE**, P2P meghívó |
| `referred_by_id` | `Int FK` | `NULL` | → `identity.users.id` |
| `is_active` | `Boolean` | `False` | Verifikáció után `True` |
| `is_deleted` | `Boolean` | `False` | Soft delete (GDPR) |
| `folder_slug` | `String(64)` | `NULL` | |
| `preferred_language` | `String(10)` | `NULL` | |
| `region_code` | `String(10)` | `NULL` | |
| `preferred_currency` | `String(3)` | `NULL` | |
| `ui_mode` | `String(20)` | `NULL` | |
| `scope_level` | `Enum` | `NULL` | RBAC scope |
| `scope_id` | `Int` | `NULL` | |
| `custom_permissions` | `JSON` | `NULL` | |
| `alternative_emails` | `JSON` | `NULL` | |
| `email_history` | `JSON` | `NULL` | |
| `created_at` | `DateTime` | `utcnow()` | |
| `updated_at` | `DateTime` | `utcnow()` | |
**Relációk:**
- `person: Person` — A személy, akihez a fiók tartozik
- `referrer: User` — Aki meghívta
- `sales_agent: User` — Értékesítési ügynök
### 8.3 VerificationToken — `identity.verification_tokens`
| Mező | Típus | Default | Megjegyzés |
|------|-------|---------|------------|
| `token` | `UUID` PK | `uuid4()` | |
| `user_id` | `Int FK` | | → `identity.users.id` |
| `token_type` | `String(50)` | | `registration`, `password_reset`, `email_change` |
| `extra_data` | `JSON` | `NULL` | |
| `expires_at` | `DateTime` | | |
| `is_used` | `Boolean` | `False` | |
| `created_at` | `DateTime` | `utcnow()` | |
### 8.4 Wallet — `finance.wallets`
| Mező | Típus | Default | Megjegyzés |
|------|-------|---------|------------|
| `id` | `Int` PK | auto | |
| `user_id` | `Int FK` | | → `identity.users.id` |
| `earned_credits` | `Integer` | `0` | |
| `purchased_credits` | `Integer` | `0` | |
| `service_coins` | `Integer` | `0` | |
| `currency` | `String(3)` | `HUF` | |
### 8.5 Device — `identity.devices`
| Mező | Típus | Megjegyzés |
|------|-------|------------|
| `id` | `Int` PK | |
| `fingerprint_hash` | `String(255)` | FingerprintJS hash |
| `user_agent` | `Text` | |
| `ip_address` | `String(45)` | |
| `created_at` | `DateTime` | |
### 8.6 UserDeviceLink — `identity.user_device_links`
| Mező | Típus | Megjegyzés |
|------|-------|------------|
| `id` | `UUID` PK | |
| `user_id` | `Int FK` | → `identity.users.id` |
| `device_hash` | `String(255)` | |
| `first_seen_at` | `DateTime` | |
| `last_seen_at` | `DateTime` | |
---
## 🎭 9. Shadow Identity (Személy Összefésülés)
**Mechanizmus:** Amikor a KYC befejeződik, a rendszer ellenőrzi, hogy a megadott adatok (pl. `identity_hash` alapján) egyeznek-e egy másik `Person` rekorddal. Ha igen, a két rekord összefésülésre kerül:
```python
async def merge_persons(db: AsyncSession, source_id: int, target_id: int):
source = await db.get(Person, source_id)
target = await db.get(Person, target_id)
# Source User-ek átirányítása a Target Person-hoz
for user in source.users:
user.person_id = target.id
# Source megjelölése merge-eltként
source.merged_into_id = target.id
source.is_active = False
await db.commit()
```
**Trigger:** `complete_kyc()` függvényben, az adatok validálása után.
---
## ⚙️ 10. Dinamikus Konfiguráció
**Forrás:** `system.system_parameters` tábla → `Settings.get_db_setting()`
**Fájl:** `backend/app/core/config.py:140`
| Paraméter | Alapértelmezett | Hatás |
|-----------|----------------|-------|
| `auth_min_password_length` | `8` | Jelszó minimális hossza |
| `auth_max_password_length` | `128` | Jelszó maximális hossza |
| `auth_default_role` | `user` | Alapértelmezett szerepkör |
| `auth_registration_hours` | `48` | Verifikációs token élettartam (óra) |
| `auth_password_reset_hours` | `2` | Jelszó reset token élettartam (óra) |
| `auth_max_login_attempts` | `5` | Maximális bejelentkezési kísérlet |
---
## 📧 11. Email Rendszer
**Forrás:** `backend/app/services/email_manager.py:18`
| Szolgáltató | Prioritás | Módszer |
|-------------|-----------|---------|
| **Brevo API** | 1. | REST API kulcsos hitelesítés |
| **Brevo SMTP** | 2. | `smtp-relay.brevo.com:587` |
| **Fallback SMTP** | 3. | Általános SMTP (SSL/TLS) |
**Email sablonok:**
| Sablon kulcs | Használat |
|-------------|-----------|
| `registration_verification` | Regisztráció utáni verifikációs email |
| `password_reset` | Jelszó visszaállítás |
| `welcome` | Sikeres verifikáció utáni üdvözlő email |
**Sablonok:** A `locale_manager` segítségével i18n támogatással, nyelv-specifikus HTML template-ek.
---
## 🛡️ 12. Sentinel Audit Log Események
| Esemény | Fázis | Naplózott adatok |
|---------|-------|------------------|
| `EVENT.REGISTRATION_INITIATED` | 1 | email, ip, user_agent |
| `EVENT.EMAIL_VERIFIED` | 2 | user_id, token_id |
| `EVENT.KYC_COMPLETED` | 4 | user_id, person_id |
| `EVENT.LOGIN_SUCCESS` | - | user_id, device_fingerprint |
| `EVENT.LOGIN_FAILED` | - | email, attempt_count |
| `EVENT.PASSWORD_RESET_REQUESTED` | - | email |
| `EVENT.PASSWORD_RESET_COMPLETED` | - | user_id |
---
## 🔄 13. Teljes Adatfolyam Diagram
```mermaid
sequenceDiagram
participant U as User (Böngésző)
participant FE as Vue Frontend
participant API as FastAPI Backend
participant DB as PostgreSQL
participant Email as Email Service
Note over U,Email: FÁZIS 1: Lite Regisztráció
U->>FE: Adatok megadása (email, név, jelszó)
FE->>FE: FingerprintJS generálás
FE->>API: POST /auth/register
API->>DB: SELECT system_parameters (dinamikus config)
API->>DB: INSERT person (is_active=False)
API->>DB: INSERT user (is_active=False)
API->>DB: INSERT verification_token (48h)
API->>Email: Küldés (verifikációs link)
API-->>FE: {status: "success", user_id, email}
FE->>U: Átirányítás /verify oldalra
Note over U,Email: FÁZIS 2: Email Verifikáció
U->>FE: Email megnyitása → Magic Link kattintás
FE->>FE: Token kiolvasás URL-ből
FE->>API: POST /auth/verify-email (token, device_fingerprint)
API->>DB: SELECT verification_token (is_used=False, expires>now)
API->>DB: UPDATE user SET is_active=True
API->>DB: UPDATE person SET is_active=True
API->>DB: UPDATE token SET is_used=True
API->>DB: INSERT device + user_device_link
API-->>FE: {access_token, refresh_token} → AUTO-LOGIN
FE->>FE: Token-ek mentése localStorage-be
FE->>FE: 3 másodperc countdown
FE->>U: Átirányítás /complete-kyc
Note over U,Email: FÁZIS 3: KYC 1. lépés - Cím
U->>FE: Cím adatok megadása
FE->>API: POST /auth/complete-kyc (cím adatok)
API->>API: Shadow Identity ellenőrzés
API->>DB: GeoService cím létrehozás
Note over U,Email: FÁZIS 4: KYC 2. lépés - Teljesítés
U->>FE: Személyes adatok + doksik
FE->>API: POST /auth/complete-kyc (összes adat)
API->>DB: UPDATE person (phone, birth, docs)
API->>DB: INSERT organization (personal)
API->>DB: INSERT wallet
API->>DB: INSERT branch
API->>DB: INSERT organization_member
API->>DB: INSERT gamification_event (XP)
API-->>FE: {status: "success"}
FE->>FE: Profil frissítés → fetchUser()
FE->>U: Átirányítás /dashboard
```
---
## ⚠️ 14. Hibakezelés
### 14.1 Backend Hibakódok
| HTTP Státusz | Hibaüzenet | Ok |
|-------------|------------|-----|
| `400` | `INVALID_PASSWORD` | Jelszó nem felel meg a komplexitási követelményeknek |
| `400` | `EMAIL_EXISTS` | Email már regisztrálva van |
| `400` | `INVALID_TOKEN` | Token érvénytelen vagy lejárt |
| `400` | `TOKEN_ALREADY_USED` | Token már fel lett használva |
| `400` | `INVALID_CREDENTIALS` | Rossz email/jelszó páros |
| `401` | `NOT_AUTHENTICATED` | Hiányzó vagy érvénytelen JWT |
| `403` | `ACCOUNT_INACTIVE` | Fiók nincs aktiválva (email verifikáció hiányzik) |
| `404` | `USER_NOT_FOUND` | User nem található |
| `429` | `TOO_MANY_ATTEMPTS` | Túl sok bejelentkezési kísérlet |
### 14.2 Frontend Hibakezelés
**Forrás:** `frontend/src/stores/auth.ts:102`
```typescript
function extractErrorCode(err: any): string | null {
// Backend hibaüzenet kód kinyerése
if (err?.response?.data?.detail) return err.response.data.detail;
if (err?.response?.data?.message) return err.response.data.message;
return null;
}
```
---
## 📁 15. Érintett Fájlok Listája
### Backend
| Fájl | Útvonal | Szerep |
|------|---------|--------|
| `auth.py` | `backend/app/api/v1/endpoints/auth.py` | 7 végpont a regisztrációhoz |
| `auth_service.py` | `backend/app/services/auth_service.py` | Üzleti logika (~500 sor) |
| `security.py` | `backend/app/core/security.py` | JWT token generálás, dekódolás |
| `config.py` | `backend/app/core/config.py` | Beállítások, dinamikus paraméterek |
| `deps.py` | `backend/app/api/deps.py` | Dependency injection (auth guard-ok) |
| `identity.py` | `backend/app/models/identity/identity.py` | Person, User, Wallet, Device modellek |
| `auth.py` | `backend/app/schemas/auth.py` | Pydantic bemeneti sémák |
| `email_manager.py` | `backend/app/services/email_manager.py` | Email küldés (Brevo/SMTP) |
| `geo_service.py` | `backend/app/services/geo_service.py` | Cím normalizálás és létrehozás |
### Frontend
| Fájl | Útvonal | Szerep |
|------|---------|--------|
| `LoginModal.vue` | `frontend/src/components/LoginModal.vue` | 3D kártya-forgató (login/register/forgot/resend) |
| `VerifyEmailView.vue` | `frontend/src/views/VerifyEmailView.vue` | Email verifikáció (3 állapot) |
| `CompleteKycView.vue` | `frontend/src/views/CompleteKycView.vue` | 2-lépéses KYC kitöltés |
| `LandingView.vue` | `frontend/src/views/LandingView.vue` | Főoldal a LoginModal-lal |
| `auth.ts` | `frontend/src/stores/auth.ts` | Pinia auth store (műveletek + állapot) |
| `index.ts` | `frontend/src/router/index.ts` | Route-ok és guard-ok |
---
## ✅ 16. Következtetés
A regisztrációs rendszer **biztonságos és jól rétegzett**:
- **JWT token-ek** rövid élettartammal (30 perc access, 1-30 nap refresh)
- **Verifikációs token-ek** konfigurálható élettartammal (48h / 2h)
- **Shadow Identity merge** megakadályozza a duplikált személyrekordokat
- **Device Fingerprinting** a bejelentkezés és verifikáció során
- **Dinamikus konfiguráció** admin által állítható paraméterekkel
- **Multi-provider email** Brevo API → SMTP → Fallback lánccal
- **Sentinel audit log** minden kritikus eseményről
- **i18n támogatás** mind a backend sablonokban, mind a frontend-en
A rendszer megfelel a GDPR követelményeknek (soft delete, személyes adatok szeparációja a Person és User modellek között).
---
*Dokumentáció készült: 2026-06-07*
*Audit típusa: Teljes regisztrációs folyamat elemzés (backend + frontend + adatbázis + tokenek)*