87 lines
2.5 KiB
Python
87 lines
2.5 KiB
Python
import unittest
|
|
from types import SimpleNamespace
|
|
|
|
from fastapi import HTTPException
|
|
|
|
from app.services.project_service import (
|
|
normalize_project_role,
|
|
require_project_roles,
|
|
require_project_write_access,
|
|
)
|
|
|
|
|
|
class _ScalarResult:
|
|
def __init__(self, value):
|
|
self.value = value
|
|
|
|
def scalar_one_or_none(self):
|
|
return self.value
|
|
|
|
|
|
class _RecordingDB:
|
|
def __init__(self, values):
|
|
self.values = iter(values)
|
|
|
|
async def execute(self, statement):
|
|
return _ScalarResult(next(self.values))
|
|
|
|
|
|
class ProjectPermissionsTest(unittest.IsolatedAsyncioTestCase):
|
|
def setUp(self):
|
|
self.project = SimpleNamespace(id=25, owner_id=1)
|
|
self.current_user = SimpleNamespace(id=2)
|
|
|
|
def test_normalize_project_role_handles_legacy_case(self):
|
|
self.assertEqual(normalize_project_role(" ADMIN "), "admin")
|
|
self.assertEqual(normalize_project_role("Editor"), "editor")
|
|
self.assertIsNone(normalize_project_role(None))
|
|
|
|
async def test_write_access_accepts_legacy_uppercase_admin(self):
|
|
db = _RecordingDB([
|
|
self.project,
|
|
SimpleNamespace(role="ADMIN"),
|
|
])
|
|
|
|
project, role = await require_project_write_access(db, 25, self.current_user)
|
|
|
|
self.assertEqual(project, self.project)
|
|
self.assertEqual(role, "admin")
|
|
|
|
async def test_write_access_accepts_legacy_uppercase_editor(self):
|
|
db = _RecordingDB([
|
|
self.project,
|
|
SimpleNamespace(role="EDITOR"),
|
|
])
|
|
|
|
project, role = await require_project_write_access(db, 25, self.current_user)
|
|
|
|
self.assertEqual(project, self.project)
|
|
self.assertEqual(role, "editor")
|
|
|
|
async def test_write_access_rejects_viewer(self):
|
|
db = _RecordingDB([
|
|
self.project,
|
|
SimpleNamespace(role="viewer"),
|
|
])
|
|
|
|
with self.assertRaises(HTTPException) as context:
|
|
await require_project_write_access(db, 25, self.current_user)
|
|
|
|
self.assertEqual(context.exception.status_code, 403)
|
|
|
|
async def test_admin_only_permission_rejects_editor(self):
|
|
db = _RecordingDB([
|
|
self.project,
|
|
SimpleNamespace(role="EDITOR"),
|
|
])
|
|
|
|
with self.assertRaises(HTTPException) as context:
|
|
await require_project_roles(
|
|
db,
|
|
25,
|
|
self.current_user,
|
|
allowed_roles=["admin"],
|
|
)
|
|
|
|
self.assertEqual(context.exception.status_code, 403)
|