- Add Model Mixins: TimestampMixin, SoftDeleteMixin, AuditMixin, etc. - Add Base Services: BaseService, BulkOperationsMixin, QueryOptimizerMixin - Add Base ViewSets with bulk operations - Add BackgroundJob model for Celery task tracking - Add BaseAppCommand for management commands - Add permissions, pagination, filters, cache, logging - Migrate tests to factory_boy + faker - Add CHANGELOG.md - 297 tests passing
253 lines
8.1 KiB
Python
253 lines
8.1 KiB
Python
"""Tests for core permissions"""
|
|
|
|
from apps.core.permissions import (
|
|
IsAdmin,
|
|
IsAdminOrReadOnly,
|
|
IsOwner,
|
|
IsOwnerOrAdmin,
|
|
IsOwnerOrReadOnly,
|
|
IsSuperuser,
|
|
IsVerified,
|
|
)
|
|
from django.contrib.auth import get_user_model
|
|
from django.test import RequestFactory, TestCase
|
|
from rest_framework.views import APIView
|
|
|
|
from tests.apps.user.factories import UserFactory
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class MockObject:
|
|
"""Mock object for testing ownership"""
|
|
|
|
def __init__(self, user=None, owner=None):
|
|
self.user = user
|
|
self.owner = owner
|
|
|
|
|
|
class IsOwnerTest(TestCase):
|
|
"""Tests for IsOwner permission"""
|
|
|
|
def setUp(self):
|
|
self.factory = RequestFactory()
|
|
self.permission = IsOwner()
|
|
self.user = UserFactory.create_user()
|
|
self.other_user = UserFactory.create_user()
|
|
|
|
def test_owner_has_permission(self):
|
|
"""Test owner has permission to object"""
|
|
request = self.factory.get("/")
|
|
request.user = self.user
|
|
obj = MockObject(user=self.user)
|
|
|
|
result = self.permission.has_object_permission(request, APIView(), obj)
|
|
self.assertTrue(result)
|
|
|
|
def test_non_owner_denied(self):
|
|
"""Test non-owner is denied"""
|
|
request = self.factory.get("/")
|
|
request.user = self.other_user
|
|
obj = MockObject(user=self.user)
|
|
|
|
result = self.permission.has_object_permission(request, APIView(), obj)
|
|
self.assertFalse(result)
|
|
|
|
def test_owner_field_fallback(self):
|
|
"""Test fallback to 'owner' field"""
|
|
request = self.factory.get("/")
|
|
request.user = self.user
|
|
obj = MockObject(owner=self.user)
|
|
|
|
result = self.permission.has_object_permission(request, APIView(), obj)
|
|
self.assertTrue(result)
|
|
|
|
|
|
class IsOwnerOrReadOnlyTest(TestCase):
|
|
"""Tests for IsOwnerOrReadOnly permission"""
|
|
|
|
def setUp(self):
|
|
self.factory = RequestFactory()
|
|
self.permission = IsOwnerOrReadOnly()
|
|
self.user = UserFactory.create_user()
|
|
self.other_user = UserFactory.create_user()
|
|
|
|
def test_safe_methods_allowed_for_all(self):
|
|
"""Test GET/HEAD/OPTIONS allowed for non-owners"""
|
|
for method in ["get", "head", "options"]:
|
|
request = getattr(self.factory, method)("/")
|
|
request.user = self.other_user
|
|
obj = MockObject(user=self.user)
|
|
|
|
result = self.permission.has_object_permission(request, APIView(), obj)
|
|
self.assertTrue(result, f"{method.upper()} should be allowed")
|
|
|
|
def test_unsafe_methods_denied_for_non_owner(self):
|
|
"""Test POST/PUT/PATCH/DELETE denied for non-owners"""
|
|
for method in ["post", "put", "patch", "delete"]:
|
|
request = getattr(self.factory, method)("/")
|
|
request.user = self.other_user
|
|
obj = MockObject(user=self.user)
|
|
|
|
result = self.permission.has_object_permission(request, APIView(), obj)
|
|
self.assertFalse(result, f"{method.upper()} should be denied")
|
|
|
|
def test_unsafe_methods_allowed_for_owner(self):
|
|
"""Test unsafe methods allowed for owner"""
|
|
request = self.factory.put("/")
|
|
request.user = self.user
|
|
obj = MockObject(user=self.user)
|
|
|
|
result = self.permission.has_object_permission(request, APIView(), obj)
|
|
self.assertTrue(result)
|
|
|
|
|
|
class IsAdminOrReadOnlyTest(TestCase):
|
|
"""Tests for IsAdminOrReadOnly permission"""
|
|
|
|
def setUp(self):
|
|
self.factory = RequestFactory()
|
|
self.permission = IsAdminOrReadOnly()
|
|
self.user = UserFactory.create_user()
|
|
self.admin = UserFactory.create_user(is_staff=True)
|
|
|
|
def test_safe_methods_allowed_for_all(self):
|
|
"""Test GET allowed for non-admins"""
|
|
request = self.factory.get("/")
|
|
request.user = self.user
|
|
|
|
result = self.permission.has_permission(request, APIView())
|
|
self.assertTrue(result)
|
|
|
|
def test_unsafe_methods_denied_for_non_admin(self):
|
|
"""Test POST denied for non-admins"""
|
|
request = self.factory.post("/")
|
|
request.user = self.user
|
|
|
|
result = self.permission.has_permission(request, APIView())
|
|
self.assertFalse(result)
|
|
|
|
def test_unsafe_methods_allowed_for_admin(self):
|
|
"""Test POST allowed for admins"""
|
|
request = self.factory.post("/")
|
|
request.user = self.admin
|
|
|
|
result = self.permission.has_permission(request, APIView())
|
|
self.assertTrue(result)
|
|
|
|
|
|
class IsAdminTest(TestCase):
|
|
"""Tests for IsAdmin permission"""
|
|
|
|
def setUp(self):
|
|
self.factory = RequestFactory()
|
|
self.permission = IsAdmin()
|
|
self.user = UserFactory.create_user()
|
|
self.admin = UserFactory.create_user(is_staff=True)
|
|
|
|
def test_admin_has_permission(self):
|
|
"""Test admin has permission"""
|
|
request = self.factory.get("/")
|
|
request.user = self.admin
|
|
|
|
result = self.permission.has_permission(request, APIView())
|
|
self.assertTrue(result)
|
|
|
|
def test_non_admin_denied(self):
|
|
"""Test non-admin is denied"""
|
|
request = self.factory.get("/")
|
|
request.user = self.user
|
|
|
|
result = self.permission.has_permission(request, APIView())
|
|
self.assertFalse(result)
|
|
|
|
|
|
class IsSuperuserTest(TestCase):
|
|
"""Tests for IsSuperuser permission"""
|
|
|
|
def setUp(self):
|
|
self.factory = RequestFactory()
|
|
self.permission = IsSuperuser()
|
|
self.user = UserFactory.create_user()
|
|
self.superuser = UserFactory.create_superuser()
|
|
|
|
def test_superuser_has_permission(self):
|
|
"""Test superuser has permission"""
|
|
request = self.factory.get("/")
|
|
request.user = self.superuser
|
|
|
|
result = self.permission.has_permission(request, APIView())
|
|
self.assertTrue(result)
|
|
|
|
def test_non_superuser_denied(self):
|
|
"""Test non-superuser is denied"""
|
|
request = self.factory.get("/")
|
|
request.user = self.user
|
|
|
|
result = self.permission.has_permission(request, APIView())
|
|
self.assertFalse(result)
|
|
|
|
|
|
class IsVerifiedTest(TestCase):
|
|
"""Tests for IsVerified permission"""
|
|
|
|
def setUp(self):
|
|
self.factory = RequestFactory()
|
|
self.permission = IsVerified()
|
|
self.user = UserFactory.create_user(is_verified=False)
|
|
self.verified_user = UserFactory.create_user(is_verified=True)
|
|
|
|
def test_verified_user_has_permission(self):
|
|
"""Test verified user has permission"""
|
|
request = self.factory.get("/")
|
|
request.user = self.verified_user
|
|
|
|
result = self.permission.has_permission(request, APIView())
|
|
self.assertTrue(result)
|
|
|
|
def test_unverified_user_denied(self):
|
|
"""Test unverified user is denied"""
|
|
request = self.factory.get("/")
|
|
request.user = self.user
|
|
|
|
result = self.permission.has_permission(request, APIView())
|
|
self.assertFalse(result)
|
|
|
|
|
|
class IsOwnerOrAdminTest(TestCase):
|
|
"""Tests for IsOwnerOrAdmin permission"""
|
|
|
|
def setUp(self):
|
|
self.factory = RequestFactory()
|
|
self.permission = IsOwnerOrAdmin()
|
|
self.user = UserFactory.create_user()
|
|
self.other_user = UserFactory.create_user()
|
|
self.admin = UserFactory.create_user(is_staff=True)
|
|
|
|
def test_owner_has_permission(self):
|
|
"""Test owner has permission"""
|
|
request = self.factory.get("/")
|
|
request.user = self.user
|
|
obj = MockObject(user=self.user)
|
|
|
|
result = self.permission.has_object_permission(request, APIView(), obj)
|
|
self.assertTrue(result)
|
|
|
|
def test_admin_has_permission(self):
|
|
"""Test admin has permission to any object"""
|
|
request = self.factory.get("/")
|
|
request.user = self.admin
|
|
obj = MockObject(user=self.user)
|
|
|
|
result = self.permission.has_object_permission(request, APIView(), obj)
|
|
self.assertTrue(result)
|
|
|
|
def test_non_owner_non_admin_denied(self):
|
|
"""Test non-owner non-admin is denied"""
|
|
request = self.factory.get("/")
|
|
request.user = self.other_user
|
|
obj = MockObject(user=self.user)
|
|
|
|
result = self.permission.has_object_permission(request, APIView(), obj)
|
|
self.assertFalse(result)
|