Fix .gitignore and add missing authentication source files
This commit fixes overly broad .gitignore patterns that were excluding important source code files from version control. Previously, wildcard patterns like *auth*, *token*, *secret*, *connection*, and *credential* were excluding ALL files containing these words, including critical application code. Changes: - Updated .gitignore with specific patterns for sensitive config files (*.json, *.txt, *.yml, *.yaml extensions only) - Removed broad wildcards that excluded source code files Added missing source files: - shared/auth/ (9 files): Complete authentication system - JWT handler, middleware, auth service, models, routes - reports-app/backend/app/routers/auth.py: Authentication API router - reports-app/backend/app/auth_middleware_wrapper.py: Middleware wrapper - reports-app/frontend/src/stores/auth.js: Vue.js auth store - reports-app/frontend/tests/: E2E tests and fixtures for auth - reports-app/telegram-bot/app/auth/: Telegram auth linking module - deployment/windows/scripts/Setup-ClaudeAuth.ps1: Windows deployment script - security/secrets_scanner.py: Security scanning utility These files are essential for the application to function and should have been included in the initial commit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
231
shared/auth/models.py
Normal file
231
shared/auth/models.py
Normal file
@@ -0,0 +1,231 @@
|
||||
"""
|
||||
Authentication Pydantic Models pentru ROA2WEB
|
||||
|
||||
Acest modul definește toate modelele de date folosite în sistemul de autentificare,
|
||||
incluzând request/response models și modele pentru user data.
|
||||
|
||||
Modelele acoperă:
|
||||
- Login request și response
|
||||
- Token data și management
|
||||
- User information și permisiuni
|
||||
- Company access control
|
||||
"""
|
||||
|
||||
from pydantic import BaseModel, Field, validator, EmailStr
|
||||
from typing import List, Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class PermissionType(str, Enum):
|
||||
"""Tipurile de permisiuni disponibile în sistem"""
|
||||
READ = "read"
|
||||
WRITE = "write"
|
||||
DELETE = "delete"
|
||||
ADMIN = "admin"
|
||||
REPORTS = "reports"
|
||||
EXPORT = "export"
|
||||
|
||||
|
||||
class TokenType(str, Enum):
|
||||
"""Tipurile de token-uri JWT"""
|
||||
ACCESS = "access"
|
||||
REFRESH = "refresh"
|
||||
|
||||
|
||||
class LoginRequest(BaseModel):
|
||||
"""Model pentru request-ul de login"""
|
||||
username: str = Field(
|
||||
...,
|
||||
min_length=3,
|
||||
max_length=50,
|
||||
description="Numele utilizatorului",
|
||||
example="admin"
|
||||
)
|
||||
password: str = Field(
|
||||
...,
|
||||
min_length=1,
|
||||
description="Parola utilizatorului"
|
||||
)
|
||||
remember_me: bool = Field(
|
||||
default=False,
|
||||
description="Dacă să păstreze utilizatorul autentificat mai mult timp"
|
||||
)
|
||||
|
||||
@validator('username')
|
||||
def username_alphanumeric(cls, v):
|
||||
"""Validează că username-ul conține doar caractere permise (inclusiv spații)"""
|
||||
# Permitem litere, cifre, spații, _, și -
|
||||
allowed_chars = v.replace(' ', '').replace('_', '').replace('-', '')
|
||||
if not allowed_chars.isalnum():
|
||||
raise ValueError('Username-ul poate conține doar litere, cifre, spații, _ și -')
|
||||
return v.upper() # Convertim la uppercase pentru consistență cu Oracle
|
||||
|
||||
|
||||
class TokenResponse(BaseModel):
|
||||
"""Model pentru răspunsul de autentificare cu token-uri"""
|
||||
access_token: str = Field(description="JWT access token")
|
||||
refresh_token: Optional[str] = Field(
|
||||
default=None,
|
||||
description="JWT refresh token (opțional)"
|
||||
)
|
||||
token_type: str = Field(
|
||||
default="bearer",
|
||||
description="Tipul token-ului (întotdeauna 'bearer')"
|
||||
)
|
||||
expires_in: int = Field(
|
||||
description="Timpul de expirare al access token-ului în secunde"
|
||||
)
|
||||
user: 'CurrentUser' = Field(description="Informațiile utilizatorului autentificat")
|
||||
|
||||
|
||||
class RefreshTokenRequest(BaseModel):
|
||||
"""Model pentru request-ul de refresh token"""
|
||||
refresh_token: str = Field(description="Refresh token-ul valid")
|
||||
|
||||
|
||||
class LogoutRequest(BaseModel):
|
||||
"""Model pentru request-ul de logout"""
|
||||
refresh_token: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Refresh token de invalidat (opțional)"
|
||||
)
|
||||
|
||||
|
||||
class CurrentUser(BaseModel):
|
||||
"""Model pentru utilizatorul curent autentificat"""
|
||||
username: str = Field(description="Numele utilizatorului")
|
||||
user_id: Optional[int] = Field(
|
||||
default=None,
|
||||
description="ID-ul utilizatorului în baza de date"
|
||||
)
|
||||
email: Optional[EmailStr] = Field(
|
||||
default=None,
|
||||
description="Email-ul utilizatorului"
|
||||
)
|
||||
companies: List[str] = Field(
|
||||
default_factory=list,
|
||||
description="Lista codurilor firmelor la care utilizatorul are acces"
|
||||
)
|
||||
permissions: List[PermissionType] = Field(
|
||||
default_factory=lambda: [PermissionType.READ],
|
||||
description="Lista permisiunilor utilizatorului"
|
||||
)
|
||||
is_active: bool = Field(
|
||||
default=True,
|
||||
description="Dacă utilizatorul este activ"
|
||||
)
|
||||
last_login: Optional[datetime] = Field(
|
||||
default=None,
|
||||
description="Data ultimei autentificări"
|
||||
)
|
||||
|
||||
@validator('companies')
|
||||
def companies_not_empty_if_active(cls, v, values):
|
||||
"""Validează că utilizatorii activi au cel puțin o firmă"""
|
||||
if values.get('is_active', True) and not v:
|
||||
raise ValueError('Utilizatorii activi trebuie să aibă acces la cel puțin o firmă')
|
||||
return v
|
||||
|
||||
|
||||
class UserCompany(BaseModel):
|
||||
"""Model pentru o firmă la care utilizatorul are acces"""
|
||||
code: str = Field(description="Codul firmei (schema Oracle)")
|
||||
name: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Numele firmei (dacă este disponibil)"
|
||||
)
|
||||
permissions: List[PermissionType] = Field(
|
||||
default_factory=lambda: [PermissionType.READ],
|
||||
description="Permisiunile utilizatorului pentru această firmă"
|
||||
)
|
||||
is_default: bool = Field(
|
||||
default=False,
|
||||
description="Dacă aceasta este firma implicită pentru utilizator"
|
||||
)
|
||||
|
||||
|
||||
class CompanyAccessRequest(BaseModel):
|
||||
"""Model pentru verificarea accesului la o firmă"""
|
||||
company_code: str = Field(description="Codul firmei de verificat")
|
||||
required_permissions: Optional[List[PermissionType]] = Field(
|
||||
default=None,
|
||||
description="Permisiunile necesare (opțional)"
|
||||
)
|
||||
|
||||
|
||||
class CompanyAccessResponse(BaseModel):
|
||||
"""Model pentru răspunsul de verificare acces firmă"""
|
||||
has_access: bool = Field(description="Dacă utilizatorul are acces")
|
||||
company: Optional[UserCompany] = Field(
|
||||
default=None,
|
||||
description="Detaliile firmei dacă utilizatorul are acces"
|
||||
)
|
||||
missing_permissions: Optional[List[PermissionType]] = Field(
|
||||
default=None,
|
||||
description="Permisiunile lipsă (dacă aplicabil)"
|
||||
)
|
||||
|
||||
|
||||
class AuthError(BaseModel):
|
||||
"""Model pentru erorile de autentificare"""
|
||||
error: str = Field(description="Tipul erorii")
|
||||
error_description: str = Field(description="Descrierea detaliată a erorii")
|
||||
error_code: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Codul de eroare pentru procesare automată"
|
||||
)
|
||||
|
||||
|
||||
class AuthStats(BaseModel):
|
||||
"""Model pentru statisticile de autentificare"""
|
||||
total_users: int = Field(description="Numărul total de utilizatori")
|
||||
active_sessions: int = Field(description="Sesiuni active curente")
|
||||
cache_hit_ratio: float = Field(
|
||||
description="Rata de hit a cache-ului pentru date utilizatori"
|
||||
)
|
||||
last_cleanup: Optional[datetime] = Field(
|
||||
default=None,
|
||||
description="Ultima curățare a cache-ului"
|
||||
)
|
||||
|
||||
|
||||
class PasswordChangeRequest(BaseModel):
|
||||
"""Model pentru schimbarea parolei (pentru viitor)"""
|
||||
current_password: str = Field(description="Parola curentă")
|
||||
new_password: str = Field(
|
||||
min_length=8,
|
||||
description="Noua parolă (minim 8 caractere)"
|
||||
)
|
||||
confirm_password: str = Field(description="Confirmarea noii parole")
|
||||
|
||||
@validator('confirm_password')
|
||||
def passwords_match(cls, v, values):
|
||||
"""Validează că parolele coincid"""
|
||||
if 'new_password' in values and v != values['new_password']:
|
||||
raise ValueError('Parolele nu coincid')
|
||||
return v
|
||||
|
||||
|
||||
class SessionInfo(BaseModel):
|
||||
"""Model pentru informațiile despre sesiune"""
|
||||
session_id: str = Field(description="ID-ul sesiunii")
|
||||
username: str = Field(description="Numele utilizatorului")
|
||||
created_at: datetime = Field(description="Data creării sesiunii")
|
||||
last_activity: datetime = Field(description="Ultima activitate")
|
||||
ip_address: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Adresa IP a utilizatorului"
|
||||
)
|
||||
user_agent: Optional[str] = Field(
|
||||
default=None,
|
||||
description="User agent-ul browserului"
|
||||
)
|
||||
is_active: bool = Field(
|
||||
default=True,
|
||||
description="Dacă sesiunea este încă activă"
|
||||
)
|
||||
|
||||
|
||||
# Update la forward references pentru TokenResponse
|
||||
TokenResponse.model_rebuild()
|
||||
Reference in New Issue
Block a user