feat: Space Booking System - MVP complet

Sistem web pentru rezervarea de birouri și săli de ședință
cu flux de aprobare administrativă.

Stack: FastAPI + Vue.js 3 + SQLite + TypeScript

Features implementate:
- Autentificare JWT + Self-registration cu email verification
- CRUD Spații, Utilizatori, Settings (Admin)
- Calendar interactiv (FullCalendar) cu drag-and-drop
- Creare rezervări cu validare (durată, program, overlap, max/zi)
- Rezervări recurente (săptămânal)
- Admin: aprobare/respingere/anulare cereri
- Admin: creare directă rezervări (bypass approval)
- Admin: editare orice rezervare
- User: editare/anulare rezervări proprii
- Notificări in-app (bell icon + dropdown)
- Notificări email (async SMTP cu BackgroundTasks)
- Jurnal acțiuni administrative (audit log)
- Rapoarte avansate (utilizare, top users, approval rate)
- Șabloane rezervări (booking templates)
- Atașamente fișiere (upload/download)
- Conflict warnings (verificare disponibilitate real-time)
- Integrare Google Calendar (OAuth2)
- Suport timezone (UTC storage + user preference)
- 225+ teste backend

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-02-09 17:51:29 +00:00
commit df4031d99c
113 changed files with 24491 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
"""Tests for authentication endpoints."""
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from app.models.user import User
def test_login_success(client: TestClient, test_user: User) -> None:
"""Test successful login."""
response = client.post(
"/api/auth/login",
json={"email": "test@example.com", "password": "testpassword"},
)
assert response.status_code == 200
data = response.json()
assert "access_token" in data
assert data["token_type"] == "bearer"
def test_login_wrong_password(client: TestClient, test_user: User) -> None:
"""Test login with wrong password."""
response = client.post(
"/api/auth/login",
json={"email": "test@example.com", "password": "wrongpassword"},
)
assert response.status_code == 401
assert "Incorrect email or password" in response.json()["detail"]
def test_login_nonexistent_user(client: TestClient) -> None:
"""Test login with non-existent user."""
response = client.post(
"/api/auth/login",
json={"email": "nonexistent@example.com", "password": "password"},
)
assert response.status_code == 401
def test_login_inactive_user(client: TestClient, test_user: User, db: Session) -> None:
"""Test login with inactive user."""
test_user.is_active = False
db.commit()
response = client.post(
"/api/auth/login",
json={"email": "test@example.com", "password": "testpassword"},
)
assert response.status_code == 403
assert "disabled" in response.json()["detail"].lower()
def test_protected_endpoint_without_token(client: TestClient) -> None:
"""Test accessing protected endpoint without token."""
# HTTPBearer returns 403 when no Authorization header is provided
response = client.get("/api/bookings/my")
assert response.status_code == 403