Przejdź do głównej zawartości

Auth & Session

KomendaOpisTyp
check_alpha_accessSprawdza czy Alpha gate jest aktywnequery
check_first_user_existsSprawdza czy istnieje pierwszy adminquery
validate_alpha_codeWaliduje kod Alphaquery
create_first_admin_sessionTworzy pierwszego admina + sesjęwrite
login_userLogowanie email + hasłowrite
login_pin_sessionLogowanie PIN-emwrite
login_biometrics_sessionLogowanie biometrią (Touch ID)write
logout_sessionWylogowanie i zamknięcie sesjiwrite
get_session_userPobiera dane zalogowanego useraquery
check_invitation_validSprawdza ważność zaproszeniaquery
register_from_invitation_sessionRejestracja z zaproszeniawrite
complete_onboarding_sessionFinalizuje onboardingwrite
get_current_session_infoInformacje o bieżącej sesjiquery

Vista wspiera dwa flow rejestracji:

flowchart TD
START[🚀 Start aplikacji] --> CHECK{Czy istnieje<br/>pierwszy user?}
CHECK -->|Nie| FTS[FirstTimeSetup]
CHECK -->|Tak| INV{Czy jest<br/>zaproszenie?}
INV -->|Tak| IR[InvitationRegistration]
INV -->|Nie| LOGIN[Login Screen]
FTS --> ONBOARD[Onboarding]
IR --> ONBOARD
LOGIN --> |Success| DASH[Dashboard]
ONBOARD --> DASH

Pełny flow tworzenia pierwszego użytkownika w systemie:

sequenceDiagram
participant User
participant FTS as FirstTimeSetup
participant Tauri as Tauri Backend
participant DB as SQLite
User->>FTS: Otwiera aplikację
FTS->>Tauri: check_first_user_exists()
Tauri->>DB: SELECT COUNT(*) FROM users
DB-->>Tauri: count = 0
Tauri-->>FTS: false
Note over FTS: Pokazuje formularz rejestracji
alt Alpha Gate aktywne
FTS->>Tauri: check_alpha_access()
Tauri-->>FTS: { required: true }
User->>FTS: Wpisuje kod Alpha
FTS->>Tauri: validate_alpha_code(code)
Tauri-->>FTS: { valid: true }
end
User->>FTS: Wypełnia formularz (name, email, password)
FTS->>FTS: validateForm()
FTS->>Tauri: create_first_admin_session(request)
Tauri->>Tauri: validate_password (8+ znaków, complexity)
Tauri->>Tauri: bcrypt::hash(password, cost=12)
Tauri->>DB: INSERT INTO users (admin)
Tauri->>DB: INSERT INTO sessions
Tauri->>DB: INSERT INTO user_preferences (defaults)
DB-->>Tauri: OK
Tauri-->>FTS: { session_id, user }
FTS->>FTS: Navigate → Onboarding

check_first_user_exists

// Frontend
const exists = await safeInvoke<boolean>('check_first_user_exists');

check_alpha_access

// Frontend
const alphaStatus = await safeInvoke<AlphaAccessStatus>('check_alpha_access');
// { required: boolean, message?: string }

validate_alpha_code

// Frontend
const result = await safeInvoke<{ valid: boolean }>('validate_alpha_code', { code });

create_first_admin_session

// Frontend (src/components/auth/FirstTimeSetup/FirstTimeSetup.tsx)
interface CreateFirstAdminRequest {
name: string;
email: string;
password: string;
alpha_code?: string;
}
const result = await safeInvoke<CreateFirstAdminResponse>(
'create_first_admin_session',
{ request }
);
// Response
interface CreateFirstAdminResponse {
session_id: string;
user: User;
}

Flow dla użytkowników zaproszonych przez admina:

sequenceDiagram
participant User
participant IR as InvitationRegistration
participant Tauri as Tauri Backend
participant DB as SQLite
User->>IR: Otwiera link z tokenem
IR->>Tauri: check_invitation_valid(token)
Tauri->>DB: SELECT * FROM invitations WHERE token = ?
alt Token nieważny/wygasły
DB-->>Tauri: null / expired
Tauri-->>IR: { valid: false, reason }
IR->>User: Błąd: zaproszenie wygasło
else Token OK
DB-->>Tauri: invitation data
Tauri-->>IR: { valid: true, email, role, clinic_id }
Note over IR: Pre-fill email (readonly)
User->>IR: Wypełnia name, password
IR->>IR: validateForm()
IR->>Tauri: register_from_invitation_session(request)
Tauri->>Tauri: validate_password
Tauri->>Tauri: bcrypt::hash(password)
Tauri->>DB: INSERT INTO users
Tauri->>DB: UPDATE invitations SET used = true
Tauri->>DB: INSERT INTO sessions
DB-->>Tauri: OK
Tauri-->>IR: { session_id, user }
IR->>IR: Navigate → Onboarding
end

check_invitation_valid

// Frontend (src/components/auth/InvitationRegistration.tsx)
const result = await safeInvoke<InvitationValidation>(
'check_invitation_valid',
{ token }
);
interface InvitationValidation {
valid: boolean;
email?: string;
role?: string;
clinic_id?: string;
reason?: string; // jeśli invalid
}

register_from_invitation_session

interface RegisterFromInvitationRequest {
token: string;
name: string;
password: string;
}
const result = await safeInvoke<RegisterFromInvitationResponse>(
'register_from_invitation_session',
{ request }
);

Vista wspiera trzy metody logowania:

flowchart LR
subgraph Methods["Metody logowania"]
EMAIL[📧 Email + Hasło]
PIN[🔢 PIN]
BIO[👆 Touch ID]
end
EMAIL --> SESSION[🔐 Session]
PIN --> SESSION
BIO --> SESSION
SESSION --> DASH[Dashboard]

sequenceDiagram
participant User
participant Login as LoginScreen
participant Tauri as Tauri Backend
participant DB as SQLite
User->>Login: Wpisuje email + hasło
Login->>Login: validateForm()
Login->>Tauri: login_user({ email, password })
Tauri->>DB: SELECT * FROM users WHERE email = ?
alt User nie istnieje
DB-->>Tauri: null
Tauri-->>Login: Error: invalid_credentials
else User istnieje
DB-->>Tauri: user + password_hash
Tauri->>Tauri: bcrypt::verify(password, hash)
alt Hasło niepoprawne
Tauri-->>Login: Error: invalid_credentials
else Hasło OK
Tauri->>DB: INSERT INTO sessions
DB-->>Tauri: session_id
Tauri-->>Login: { session_id, user, requires_onboarding }
alt requires_onboarding = true
Login->>Login: Navigate → Onboarding
else
Login->>Login: Navigate → Dashboard
end
end
end

login_user

// Frontend (src/services/authService.ts)
interface LoginRequest {
email: string;
password: string;
}
const result = await safeInvoke<LoginResponse>('login_user', {
email,
password
});
interface LoginResponse {
session_id: string;
user: User;
requires_onboarding: boolean;
}

Szybkie logowanie dla użytkowników z ustawionym PIN-em:

// Frontend
const result = await safeInvoke<LoginResponse>(
'login_pin_session',
{ user_id, pin }
);

// Frontend (src/hooks/useBiometricAuth.ts)
// 1. Sprawdź dostępność
const available = await safeInvoke<boolean>('check_biometrics_available');
// 2. Jeśli dostępne, loguj
if (available) {
const result = await safeInvoke<LoginResponse>(
'login_biometrics_session',
{ user_id }
);
}

Pobiera dane zalogowanego użytkownika na podstawie session_id:

// Frontend (src/contexts/AuthContext.tsx)
const user = await safeInvoke<User | null>(
'get_session_user',
withSessionPayload({})
);

Szczegółowe informacje o sesji:

const sessionInfo = await safeInvoke<SessionInfo>(
'get_current_session_info',
withSessionPayload({})
);
interface SessionInfo {
session_id: string;
user_id: string;
created_at: string;
last_activity: string;
expires_at: string;
}
// Frontend
await safeInvoke('logout_session', withSessionPayload({}));
// Czyści sesję w DB i przekierowuje do Login

Po rejestracji użytkownik przechodzi przez wielokrokowy onboarding:

flowchart LR
S1[1. Zgody<br/>Terms & Privacy] --> S2[2. Practice Mode<br/>solo/team/demo]
S2 --> S3[3. AI Precision<br/>minimal/balanced/complete]
S3 --> S4[4. Tone of Voice<br/>neutral/warm/clinical]
S4 --> S5[5. Docs Style<br/>detailed/quick/keypoints]
S5 --> S6[6. Tech Profile<br/>innovator/practical/conservative]
S6 --> S7[7. Preview<br/>podsumowanie]
S7 --> DONE[✅ Complete]

Finalizuje onboarding i zapisuje wszystkie preferencje:

// Frontend (src/contexts/AuthContext.tsx)
interface OnboardingData {
terms_accepted: boolean;
privacy_accepted: boolean;
practice_mode: 'solo' | 'team' | 'demo';
ai_precision_level: 'minimal' | 'balanced' | 'complete';
tone_of_voice: 'neutral' | 'warm' | 'professional' | 'friendly' | 'clinical';
docs_style: 'detailed' | 'quick' | 'keypoints';
tech_profile: 'innovator' | 'practical' | 'conservative';
workday_style?: 'planned' | 'dynamic' | 'balanced';
}
await safeInvoke(
'complete_onboarding_session',
withSessionPayload({ preferences: onboardingData })
);
// Po sukcesie:
// 1. user_preferences zostają zaktualizowane
// 2. user.onboarding_completed = true
// 3. Redirect → Dashboard

KodOpisRozwiązanie
invalid_credentialsBłędny email lub hasłoSprawdź dane
user_not_foundUżytkownik nie istniejeSprawdź email
session_expiredSesja wygasłaZaloguj ponownie
pin_lockedPIN zablokowany (5 prób)Poczekaj 30 min lub użyj hasła
biometrics_not_availableTouch ID niedostępneUżyj hasła lub PIN
invitation_expiredZaproszenie wygasłoPoproś o nowe zaproszenie
invitation_already_usedZaproszenie już użyteZaloguj się lub skontaktuj admina
alpha_code_invalidNieprawidłowy kod AlphaSprawdź kod
password_too_weakHasło nie spełnia wymagańMin. 8 znaków + złożoność