314 lines
11 KiB
Python
314 lines
11 KiB
Python
"""
|
|
Unit tests for permission classes
|
|
Tests IsAuthenticatedAndActive, HasTenantAccess, IsViewerOrAbove, IsEditorOrAbove, IsAdminOrOwner
|
|
"""
|
|
from django.test import TestCase
|
|
from rest_framework.test import APIRequestFactory
|
|
from rest_framework.views import APIView
|
|
from igny8_core.api.permissions import (
|
|
IsAuthenticatedAndActive, HasTenantAccess, IsViewerOrAbove,
|
|
IsEditorOrAbove, IsAdminOrOwner
|
|
)
|
|
from igny8_core.auth.models import User, Account, Plan
|
|
|
|
|
|
class PermissionsTestCase(TestCase):
|
|
"""Test cases for permission classes"""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures"""
|
|
self.factory = APIRequestFactory()
|
|
self.view = APIView()
|
|
|
|
# Create test plan
|
|
self.plan = Plan.objects.create(
|
|
name="Test Plan",
|
|
slug="test-plan",
|
|
price=0,
|
|
credits_per_month=1000
|
|
)
|
|
|
|
# Create owner user first (Account needs owner)
|
|
self.owner_user = User.objects.create_user(
|
|
username='owner',
|
|
email='owner@test.com',
|
|
password='testpass123',
|
|
role='owner'
|
|
)
|
|
|
|
# Create test account with owner
|
|
self.account = Account.objects.create(
|
|
name="Test Account",
|
|
slug="test-account",
|
|
plan=self.plan,
|
|
owner=self.owner_user
|
|
)
|
|
|
|
# Update owner user to have account
|
|
self.owner_user.account = self.account
|
|
self.owner_user.save()
|
|
|
|
self.admin_user = User.objects.create_user(
|
|
username='admin',
|
|
email='admin@test.com',
|
|
password='testpass123',
|
|
role='admin',
|
|
account=self.account
|
|
)
|
|
|
|
self.editor_user = User.objects.create_user(
|
|
username='editor',
|
|
email='editor@test.com',
|
|
password='testpass123',
|
|
role='editor',
|
|
account=self.account
|
|
)
|
|
|
|
self.viewer_user = User.objects.create_user(
|
|
username='viewer',
|
|
email='viewer@test.com',
|
|
password='testpass123',
|
|
role='viewer',
|
|
account=self.account
|
|
)
|
|
|
|
# Create another account for tenant isolation testing
|
|
self.other_owner = User.objects.create_user(
|
|
username='other_owner',
|
|
email='other_owner@test.com',
|
|
password='testpass123',
|
|
role='owner'
|
|
)
|
|
|
|
self.other_account = Account.objects.create(
|
|
name="Other Account",
|
|
slug="other-account",
|
|
plan=self.plan,
|
|
owner=self.other_owner
|
|
)
|
|
|
|
self.other_owner.account = self.other_account
|
|
self.other_owner.save()
|
|
|
|
self.other_user = User.objects.create_user(
|
|
username='other',
|
|
email='other@test.com',
|
|
password='testpass123',
|
|
role='owner',
|
|
account=self.other_account
|
|
)
|
|
|
|
def test_is_authenticated_and_active_authenticated(self):
|
|
"""Test IsAuthenticatedAndActive allows authenticated users"""
|
|
permission = IsAuthenticatedAndActive()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.owner_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_is_authenticated_and_active_unauthenticated(self):
|
|
"""Test IsAuthenticatedAndActive denies unauthenticated users"""
|
|
permission = IsAuthenticatedAndActive()
|
|
request = self.factory.get('/test/')
|
|
request.user = None
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertFalse(result)
|
|
|
|
def test_is_authenticated_and_active_inactive_user(self):
|
|
"""Test IsAuthenticatedAndActive denies inactive users"""
|
|
permission = IsAuthenticatedAndActive()
|
|
self.owner_user.is_active = False
|
|
self.owner_user.save()
|
|
|
|
request = self.factory.get('/test/')
|
|
request.user = self.owner_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertFalse(result)
|
|
|
|
def test_has_tenant_access_same_account(self):
|
|
"""Test HasTenantAccess allows users from same account"""
|
|
permission = HasTenantAccess()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.owner_user
|
|
request.account = self.account
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_has_tenant_access_different_account(self):
|
|
"""Test HasTenantAccess denies users from different account"""
|
|
permission = HasTenantAccess()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.owner_user
|
|
request.account = self.other_account
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertFalse(result)
|
|
|
|
def test_has_tenant_access_admin_bypass(self):
|
|
"""Test HasTenantAccess allows admin/developer to bypass"""
|
|
permission = HasTenantAccess()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.admin_user
|
|
request.account = self.other_account # Different account
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result) # Admin should bypass
|
|
|
|
def test_has_tenant_access_system_account(self):
|
|
"""Test HasTenantAccess allows system account users to bypass"""
|
|
# Create system account owner
|
|
system_owner = User.objects.create_user(
|
|
username='system_owner_test',
|
|
email='system_owner_test@test.com',
|
|
password='testpass123',
|
|
role='owner'
|
|
)
|
|
|
|
# Create system account
|
|
system_account = Account.objects.create(
|
|
name="AWS Admin",
|
|
slug="aws-admin",
|
|
plan=self.plan,
|
|
owner=system_owner
|
|
)
|
|
|
|
system_owner.account = system_account
|
|
system_owner.save()
|
|
|
|
system_user = User.objects.create_user(
|
|
username='system',
|
|
email='system@test.com',
|
|
password='testpass123',
|
|
role='viewer',
|
|
account=system_account
|
|
)
|
|
|
|
permission = HasTenantAccess()
|
|
request = self.factory.get('/test/')
|
|
request.user = system_user
|
|
request.account = self.account # Different account
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result) # System account user should bypass
|
|
|
|
def test_is_viewer_or_above_viewer(self):
|
|
"""Test IsViewerOrAbove allows viewer role"""
|
|
permission = IsViewerOrAbove()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.viewer_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_is_viewer_or_above_editor(self):
|
|
"""Test IsViewerOrAbove allows editor role"""
|
|
permission = IsViewerOrAbove()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.editor_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_is_viewer_or_above_admin(self):
|
|
"""Test IsViewerOrAbove allows admin role"""
|
|
permission = IsViewerOrAbove()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.admin_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_is_viewer_or_above_owner(self):
|
|
"""Test IsViewerOrAbove allows owner role"""
|
|
permission = IsViewerOrAbove()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.owner_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_is_editor_or_above_viewer_denied(self):
|
|
"""Test IsEditorOrAbove denies viewer role"""
|
|
permission = IsEditorOrAbove()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.viewer_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertFalse(result)
|
|
|
|
def test_is_editor_or_above_editor_allowed(self):
|
|
"""Test IsEditorOrAbove allows editor role"""
|
|
permission = IsEditorOrAbove()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.editor_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_is_editor_or_above_admin_allowed(self):
|
|
"""Test IsEditorOrAbove allows admin role"""
|
|
permission = IsEditorOrAbove()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.admin_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_is_admin_or_owner_viewer_denied(self):
|
|
"""Test IsAdminOrOwner denies viewer role"""
|
|
permission = IsAdminOrOwner()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.viewer_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertFalse(result)
|
|
|
|
def test_is_admin_or_owner_editor_denied(self):
|
|
"""Test IsAdminOrOwner denies editor role"""
|
|
permission = IsAdminOrOwner()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.editor_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertFalse(result)
|
|
|
|
def test_is_admin_or_owner_admin_allowed(self):
|
|
"""Test IsAdminOrOwner allows admin role"""
|
|
permission = IsAdminOrOwner()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.admin_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_is_admin_or_owner_owner_allowed(self):
|
|
"""Test IsAdminOrOwner allows owner role"""
|
|
permission = IsAdminOrOwner()
|
|
request = self.factory.get('/test/')
|
|
request.user = self.owner_user
|
|
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertTrue(result)
|
|
|
|
def test_all_permissions_unauthenticated_denied(self):
|
|
"""Test all permissions deny unauthenticated users"""
|
|
permissions = [
|
|
IsAuthenticatedAndActive(),
|
|
HasTenantAccess(),
|
|
IsViewerOrAbove(),
|
|
IsEditorOrAbove(),
|
|
IsAdminOrOwner()
|
|
]
|
|
|
|
request = self.factory.get('/test/')
|
|
request.user = None
|
|
|
|
for permission in permissions:
|
|
result = permission.has_permission(request, self.view)
|
|
self.assertFalse(result, f"{permission.__class__.__name__} should deny unauthenticated users")
|
|
|