feat(core): add core module with mixins, services, and background jobs
- 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
This commit is contained in:
252
tests/apps/core/test_permissions.py
Normal file
252
tests/apps/core/test_permissions.py
Normal file
@@ -0,0 +1,252 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user