Files
PROJECT-CONTORL/backend/tests/test_spaces.py
beabigegg 35c90fe76b feat: implement 5 QA-driven security and quality proposals
Implemented proposals from comprehensive QA review:

1. extend-csrf-protection
   - Add POST to CSRF protected methods in frontend
   - Global CSRF middleware for all state-changing operations
   - Update tests with CSRF token fixtures

2. tighten-cors-websocket-security
   - Replace wildcard CORS with explicit method/header lists
   - Disable query parameter auth in production (code 4002)
   - Add per-user WebSocket connection limit (max 5, code 4005)

3. shorten-jwt-expiry
   - Reduce JWT expiry from 7 days to 60 minutes
   - Add refresh token support with 7-day expiry
   - Implement token rotation on refresh
   - Frontend auto-refresh when token near expiry (<5 min)

4. fix-frontend-quality
   - Add React.lazy() code splitting for all pages
   - Fix useCallback dependency arrays (Dashboard, Comments)
   - Add localStorage data validation in AuthContext
   - Complete i18n for AttachmentUpload component

5. enhance-backend-validation
   - Add SecurityAuditMiddleware for access denied logging
   - Add ErrorSanitizerMiddleware for production error messages
   - Protect /health/detailed with admin authentication
   - Add input length validation (comment 5000, desc 10000)

All 521 backend tests passing. Frontend builds successfully.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 23:19:05 +08:00

118 lines
3.6 KiB
Python

import pytest
from fastapi.testclient import TestClient
from unittest.mock import MagicMock, patch
from app.main import app
from app.models import User, Space
client = TestClient(app)
# Mock user for testing
def get_mock_user():
user = MagicMock(spec=User)
user.id = "test-user-id"
user.email = "test@example.com"
user.name = "Test User"
user.is_active = True
user.is_system_admin = False
user.department_id = "dept-1"
return user
def get_mock_admin_user():
user = get_mock_user()
user.is_system_admin = True
return user
class TestSpacesAPI:
"""Test Spaces API endpoints."""
@patch("app.api.spaces.router.get_current_user")
@patch("app.api.spaces.router.get_db")
def test_list_spaces_empty(self, mock_db, mock_get_user):
"""Test listing spaces when none exist."""
mock_user = get_mock_user()
mock_get_user.return_value = mock_user
mock_session = MagicMock()
mock_session.query.return_value.filter.return_value.all.return_value = []
mock_db.return_value = mock_session
# Skip actual auth for unit test
with patch("app.middleware.auth.get_current_user", return_value=mock_user):
response = client.get(
"/api/spaces",
headers={"Authorization": "Bearer test-token"}
)
# This will fail auth in real scenario, but tests the route exists
assert response.status_code in [200, 401]
@patch("app.api.spaces.router.get_current_user")
def test_create_space_requires_auth(self, mock_get_user):
"""Test that creating a space requires authentication."""
response = client.post(
"/api/spaces",
json={"name": "Test Space", "description": "Test"}
)
assert response.status_code == 401 # 401 for unauthenticated, 403 for unauthorized
def test_space_routes_exist(self):
"""Test that all space routes are registered."""
routes = [route.path for route in app.routes if hasattr(route, 'path')]
assert "/api/spaces" in routes
assert "/api/spaces/{space_id}" in routes
class TestSpaceModel:
"""Test Space model."""
def test_space_creation(self):
"""Test Space model can be instantiated."""
space = Space(
id="test-id",
name="Test Space",
description="A test space",
owner_id="owner-id",
is_active=True,
)
assert space.name == "Test Space"
assert space.is_active == True
class TestSpacePermissions:
"""Test space permission logic."""
def test_admin_has_access(self):
"""Test that admin users have access to all spaces."""
from app.middleware.auth import check_space_access, check_space_edit_access
admin = get_mock_admin_user()
space = MagicMock()
space.owner_id = "other-user"
assert check_space_access(admin, space) == True
assert check_space_edit_access(admin, space) == True
def test_owner_can_edit(self):
"""Test that space owner can edit."""
from app.middleware.auth import check_space_edit_access
user = get_mock_user()
space = MagicMock()
space.owner_id = user.id
assert check_space_edit_access(user, space) == True
def test_non_owner_cannot_edit(self):
"""Test that non-owner cannot edit."""
from app.middleware.auth import check_space_edit_access
user = get_mock_user()
space = MagicMock()
space.owner_id = "other-user-id"
assert check_space_edit_access(user, space) == False