Files
PROJECT-CONTORL/backend/tests/test_projects.py
beabigegg daca7798e3 feat: implement task management module
Backend (FastAPI):
- Database migration for spaces, projects, task_statuses, tasks tables
- SQLAlchemy models with relationships
- Pydantic schemas for CRUD operations
- Spaces API: CRUD with soft delete
- Projects API: CRUD with auto-created default statuses
- Tasks API: CRUD, status change, assign, subtask support
- Permission middleware with Security Level filtering
- Subtask depth limit (max 2 levels)

Frontend (React + Vite):
- Layout component with navigation
- Spaces list page
- Projects list page
- Tasks list page with status management

Fixes:
- auth_client.py: use 'username' field for external API
- config.py: extend JWT expiry to 7 days
- auth/router.py: sync Redis session with JWT expiry

Tests: 36 passed (unit + integration)
E2E: All APIs verified with real authentication

OpenSpec: add-task-management archived

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 00:31:34 +08:00

98 lines
3.5 KiB
Python

import pytest
from unittest.mock import MagicMock
from app.models import Project
from app.middleware.auth import check_project_access, check_project_edit_access
def get_mock_user(is_admin=False, department_id="dept-1"):
user = MagicMock()
user.id = "test-user-id"
user.is_system_admin = is_admin
user.department_id = department_id
return user
def get_mock_project(owner_id="owner-id", security_level="department", department_id="dept-1"):
project = MagicMock()
project.id = "project-id"
project.owner_id = owner_id
project.security_level = security_level
project.department_id = department_id
return project
class TestProjectModel:
"""Test Project model."""
def test_project_creation(self):
"""Test Project model can be instantiated."""
project = Project(
id="test-id",
space_id="space-id",
title="Test Project",
owner_id="owner-id",
security_level="department",
)
assert project.title == "Test Project"
assert project.security_level == "department"
class TestProjectSecurityLevel:
"""Test project access based on security level."""
def test_admin_bypasses_all(self):
"""Test that admin can access any project."""
admin = get_mock_user(is_admin=True)
project = get_mock_project(security_level="confidential")
assert check_project_access(admin, project) == True
assert check_project_edit_access(admin, project) == True
def test_owner_has_access(self):
"""Test that owner can access their project."""
user = get_mock_user()
project = get_mock_project(owner_id=user.id, security_level="confidential")
assert check_project_access(user, project) == True
def test_public_project_accessible_by_all(self):
"""Test that public projects are accessible by all users."""
user = get_mock_user(department_id="other-dept")
project = get_mock_project(security_level="public")
assert check_project_access(user, project) == True
def test_department_project_same_dept(self):
"""Test that department projects are accessible by same department."""
user = get_mock_user(department_id="dept-1")
project = get_mock_project(security_level="department", department_id="dept-1")
assert check_project_access(user, project) == True
def test_department_project_different_dept(self):
"""Test that department projects are not accessible by different department."""
user = get_mock_user(department_id="dept-2")
project = get_mock_project(security_level="department", department_id="dept-1")
assert check_project_access(user, project) == False
def test_confidential_project_non_owner(self):
"""Test that confidential projects are not accessible by non-owners."""
user = get_mock_user(department_id="dept-1")
project = get_mock_project(
owner_id="other-user",
security_level="confidential",
department_id="dept-1"
)
assert check_project_access(user, project) == False
def test_only_owner_can_edit(self):
"""Test that only owner can edit project."""
user = get_mock_user()
project = get_mock_project(owner_id="other-user", security_level="public")
assert check_project_access(user, project) == True # Can view
assert check_project_edit_access(user, project) == False # Cannot edit