mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-12-12 01:26:47 +01:00
Add AI permission classes and comprehensive tests
Co-authored-by: dawnsystem <42047891+dawnsystem@users.noreply.github.com>
This commit is contained in:
parent
dcd9d6cff3
commit
476b08a23b
4 changed files with 638 additions and 0 deletions
26
src/documents/migrations/1073_add_ai_permissions.py
Normal file
26
src/documents/migrations/1073_add_ai_permissions.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Generated migration for adding AI-related custom permissions
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "1072_workflowtrigger_filter_custom_field_query_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="document",
|
||||
options={
|
||||
"ordering": ("-created",),
|
||||
"permissions": [
|
||||
("can_view_ai_suggestions", "Can view AI suggestions"),
|
||||
("can_apply_ai_suggestions", "Can apply AI suggestions"),
|
||||
("can_approve_deletions", "Can approve AI-recommended deletions"),
|
||||
("can_configure_ai", "Can configure AI settings"),
|
||||
],
|
||||
"verbose_name": "document",
|
||||
"verbose_name_plural": "documents",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
@ -317,6 +317,12 @@ class Document(SoftDeleteModel, ModelWithOwner):
|
|||
ordering = ("-created",)
|
||||
verbose_name = _("document")
|
||||
verbose_name_plural = _("documents")
|
||||
permissions = [
|
||||
("can_view_ai_suggestions", "Can view AI suggestions"),
|
||||
("can_apply_ai_suggestions", "Can apply AI suggestions"),
|
||||
("can_approve_deletions", "Can approve AI-recommended deletions"),
|
||||
("can_configure_ai", "Can configure AI settings"),
|
||||
]
|
||||
|
||||
def __str__(self) -> str:
|
||||
created = self.created.isoformat()
|
||||
|
|
|
|||
|
|
@ -219,3 +219,85 @@ class AcknowledgeTasksPermissions(BasePermission):
|
|||
perms = self.perms_map.get(request.method, [])
|
||||
|
||||
return request.user.has_perms(perms)
|
||||
|
||||
|
||||
class CanViewAISuggestionsPermission(BasePermission):
|
||||
"""
|
||||
Permission class to check if user can view AI suggestions.
|
||||
|
||||
This permission allows users to view AI scan results and suggestions
|
||||
for documents, including tags, correspondents, document types, and
|
||||
other metadata suggestions.
|
||||
"""
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if not request.user or not request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# Superusers always have permission
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# Check for specific permission
|
||||
return request.user.has_perm("documents.can_view_ai_suggestions")
|
||||
|
||||
|
||||
class CanApplyAISuggestionsPermission(BasePermission):
|
||||
"""
|
||||
Permission class to check if user can apply AI suggestions to documents.
|
||||
|
||||
This permission allows users to apply AI-generated suggestions to documents,
|
||||
such as auto-applying tags, correspondents, document types, etc.
|
||||
"""
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if not request.user or not request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# Superusers always have permission
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# Check for specific permission
|
||||
return request.user.has_perm("documents.can_apply_ai_suggestions")
|
||||
|
||||
|
||||
class CanApproveDeletionsPermission(BasePermission):
|
||||
"""
|
||||
Permission class to check if user can approve AI-recommended deletions.
|
||||
|
||||
This permission is required to approve deletion requests initiated by AI,
|
||||
ensuring that no documents are deleted without explicit user authorization.
|
||||
"""
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if not request.user or not request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# Superusers always have permission
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# Check for specific permission
|
||||
return request.user.has_perm("documents.can_approve_deletions")
|
||||
|
||||
|
||||
class CanConfigureAIPermission(BasePermission):
|
||||
"""
|
||||
Permission class to check if user can configure AI settings.
|
||||
|
||||
This permission allows users to configure AI scanner settings, including
|
||||
confidence thresholds, auto-apply behavior, and ML feature toggles.
|
||||
Typically restricted to administrators.
|
||||
"""
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if not request.user or not request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# Superusers always have permission
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# Check for specific permission
|
||||
return request.user.has_perm("documents.can_configure_ai")
|
||||
|
|
|
|||
524
src/documents/tests/test_ai_permissions.py
Normal file
524
src/documents/tests/test_ai_permissions.py
Normal file
|
|
@ -0,0 +1,524 @@
|
|||
"""
|
||||
Unit tests for AI-related permissions.
|
||||
|
||||
Tests cover:
|
||||
- CanViewAISuggestionsPermission
|
||||
- CanApplyAISuggestionsPermission
|
||||
- CanApproveDeletionsPermission
|
||||
- CanConfigureAIPermission
|
||||
- Role-based access control
|
||||
- Permission assignment and verification
|
||||
"""
|
||||
|
||||
from django.contrib.auth.models import Group, Permission, User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
from rest_framework.test import APIRequestFactory
|
||||
|
||||
from documents.models import Document
|
||||
from documents.permissions import (
|
||||
CanApplyAISuggestionsPermission,
|
||||
CanApproveDeletionsPermission,
|
||||
CanConfigureAIPermission,
|
||||
CanViewAISuggestionsPermission,
|
||||
)
|
||||
|
||||
|
||||
class MockView:
|
||||
"""Mock view for testing permissions."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class TestCanViewAISuggestionsPermission(TestCase):
|
||||
"""Test the CanViewAISuggestionsPermission class."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test users and permissions."""
|
||||
self.factory = APIRequestFactory()
|
||||
self.permission = CanViewAISuggestionsPermission()
|
||||
self.view = MockView()
|
||||
|
||||
# Create users
|
||||
self.superuser = User.objects.create_superuser(
|
||||
username="admin", email="admin@test.com", password="admin123"
|
||||
)
|
||||
self.regular_user = User.objects.create_user(
|
||||
username="regular", email="regular@test.com", password="regular123"
|
||||
)
|
||||
self.permitted_user = User.objects.create_user(
|
||||
username="permitted", email="permitted@test.com", password="permitted123"
|
||||
)
|
||||
|
||||
# Assign permission to permitted_user
|
||||
content_type = ContentType.objects.get_for_model(Document)
|
||||
permission, created = Permission.objects.get_or_create(
|
||||
codename="can_view_ai_suggestions",
|
||||
name="Can view AI suggestions",
|
||||
content_type=content_type,
|
||||
)
|
||||
self.permitted_user.user_permissions.add(permission)
|
||||
|
||||
def test_unauthenticated_user_denied(self):
|
||||
"""Test that unauthenticated users are denied."""
|
||||
request = self.factory.get("/api/ai/suggestions/")
|
||||
request.user = None
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_superuser_allowed(self):
|
||||
"""Test that superusers are always allowed."""
|
||||
request = self.factory.get("/api/ai/suggestions/")
|
||||
request.user = self.superuser
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_regular_user_without_permission_denied(self):
|
||||
"""Test that regular users without permission are denied."""
|
||||
request = self.factory.get("/api/ai/suggestions/")
|
||||
request.user = self.regular_user
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_user_with_permission_allowed(self):
|
||||
"""Test that users with permission are allowed."""
|
||||
request = self.factory.get("/api/ai/suggestions/")
|
||||
request.user = self.permitted_user
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertTrue(result)
|
||||
|
||||
|
||||
class TestCanApplyAISuggestionsPermission(TestCase):
|
||||
"""Test the CanApplyAISuggestionsPermission class."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test users and permissions."""
|
||||
self.factory = APIRequestFactory()
|
||||
self.permission = CanApplyAISuggestionsPermission()
|
||||
self.view = MockView()
|
||||
|
||||
# Create users
|
||||
self.superuser = User.objects.create_superuser(
|
||||
username="admin", email="admin@test.com", password="admin123"
|
||||
)
|
||||
self.regular_user = User.objects.create_user(
|
||||
username="regular", email="regular@test.com", password="regular123"
|
||||
)
|
||||
self.permitted_user = User.objects.create_user(
|
||||
username="permitted", email="permitted@test.com", password="permitted123"
|
||||
)
|
||||
|
||||
# Assign permission to permitted_user
|
||||
content_type = ContentType.objects.get_for_model(Document)
|
||||
permission, created = Permission.objects.get_or_create(
|
||||
codename="can_apply_ai_suggestions",
|
||||
name="Can apply AI suggestions",
|
||||
content_type=content_type,
|
||||
)
|
||||
self.permitted_user.user_permissions.add(permission)
|
||||
|
||||
def test_unauthenticated_user_denied(self):
|
||||
"""Test that unauthenticated users are denied."""
|
||||
request = self.factory.post("/api/ai/suggestions/apply/")
|
||||
request.user = None
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_superuser_allowed(self):
|
||||
"""Test that superusers are always allowed."""
|
||||
request = self.factory.post("/api/ai/suggestions/apply/")
|
||||
request.user = self.superuser
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_regular_user_without_permission_denied(self):
|
||||
"""Test that regular users without permission are denied."""
|
||||
request = self.factory.post("/api/ai/suggestions/apply/")
|
||||
request.user = self.regular_user
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_user_with_permission_allowed(self):
|
||||
"""Test that users with permission are allowed."""
|
||||
request = self.factory.post("/api/ai/suggestions/apply/")
|
||||
request.user = self.permitted_user
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertTrue(result)
|
||||
|
||||
|
||||
class TestCanApproveDeletionsPermission(TestCase):
|
||||
"""Test the CanApproveDeletionsPermission class."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test users and permissions."""
|
||||
self.factory = APIRequestFactory()
|
||||
self.permission = CanApproveDeletionsPermission()
|
||||
self.view = MockView()
|
||||
|
||||
# Create users
|
||||
self.superuser = User.objects.create_superuser(
|
||||
username="admin", email="admin@test.com", password="admin123"
|
||||
)
|
||||
self.regular_user = User.objects.create_user(
|
||||
username="regular", email="regular@test.com", password="regular123"
|
||||
)
|
||||
self.permitted_user = User.objects.create_user(
|
||||
username="permitted", email="permitted@test.com", password="permitted123"
|
||||
)
|
||||
|
||||
# Assign permission to permitted_user
|
||||
content_type = ContentType.objects.get_for_model(Document)
|
||||
permission, created = Permission.objects.get_or_create(
|
||||
codename="can_approve_deletions",
|
||||
name="Can approve AI-recommended deletions",
|
||||
content_type=content_type,
|
||||
)
|
||||
self.permitted_user.user_permissions.add(permission)
|
||||
|
||||
def test_unauthenticated_user_denied(self):
|
||||
"""Test that unauthenticated users are denied."""
|
||||
request = self.factory.post("/api/ai/deletions/approve/")
|
||||
request.user = None
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_superuser_allowed(self):
|
||||
"""Test that superusers are always allowed."""
|
||||
request = self.factory.post("/api/ai/deletions/approve/")
|
||||
request.user = self.superuser
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_regular_user_without_permission_denied(self):
|
||||
"""Test that regular users without permission are denied."""
|
||||
request = self.factory.post("/api/ai/deletions/approve/")
|
||||
request.user = self.regular_user
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_user_with_permission_allowed(self):
|
||||
"""Test that users with permission are allowed."""
|
||||
request = self.factory.post("/api/ai/deletions/approve/")
|
||||
request.user = self.permitted_user
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertTrue(result)
|
||||
|
||||
|
||||
class TestCanConfigureAIPermission(TestCase):
|
||||
"""Test the CanConfigureAIPermission class."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test users and permissions."""
|
||||
self.factory = APIRequestFactory()
|
||||
self.permission = CanConfigureAIPermission()
|
||||
self.view = MockView()
|
||||
|
||||
# Create users
|
||||
self.superuser = User.objects.create_superuser(
|
||||
username="admin", email="admin@test.com", password="admin123"
|
||||
)
|
||||
self.regular_user = User.objects.create_user(
|
||||
username="regular", email="regular@test.com", password="regular123"
|
||||
)
|
||||
self.permitted_user = User.objects.create_user(
|
||||
username="permitted", email="permitted@test.com", password="permitted123"
|
||||
)
|
||||
|
||||
# Assign permission to permitted_user
|
||||
content_type = ContentType.objects.get_for_model(Document)
|
||||
permission, created = Permission.objects.get_or_create(
|
||||
codename="can_configure_ai",
|
||||
name="Can configure AI settings",
|
||||
content_type=content_type,
|
||||
)
|
||||
self.permitted_user.user_permissions.add(permission)
|
||||
|
||||
def test_unauthenticated_user_denied(self):
|
||||
"""Test that unauthenticated users are denied."""
|
||||
request = self.factory.post("/api/ai/config/")
|
||||
request.user = None
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_superuser_allowed(self):
|
||||
"""Test that superusers are always allowed."""
|
||||
request = self.factory.post("/api/ai/config/")
|
||||
request.user = self.superuser
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_regular_user_without_permission_denied(self):
|
||||
"""Test that regular users without permission are denied."""
|
||||
request = self.factory.post("/api/ai/config/")
|
||||
request.user = self.regular_user
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_user_with_permission_allowed(self):
|
||||
"""Test that users with permission are allowed."""
|
||||
request = self.factory.post("/api/ai/config/")
|
||||
request.user = self.permitted_user
|
||||
|
||||
result = self.permission.has_permission(request, self.view)
|
||||
|
||||
self.assertTrue(result)
|
||||
|
||||
|
||||
class TestRoleBasedAccessControl(TestCase):
|
||||
"""Test role-based access control for AI permissions."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test groups and permissions."""
|
||||
# Create groups
|
||||
self.viewer_group = Group.objects.create(name="AI Viewers")
|
||||
self.editor_group = Group.objects.create(name="AI Editors")
|
||||
self.admin_group = Group.objects.create(name="AI Administrators")
|
||||
|
||||
# Get permissions
|
||||
content_type = ContentType.objects.get_for_model(Document)
|
||||
self.view_permission, _ = Permission.objects.get_or_create(
|
||||
codename="can_view_ai_suggestions",
|
||||
name="Can view AI suggestions",
|
||||
content_type=content_type,
|
||||
)
|
||||
self.apply_permission, _ = Permission.objects.get_or_create(
|
||||
codename="can_apply_ai_suggestions",
|
||||
name="Can apply AI suggestions",
|
||||
content_type=content_type,
|
||||
)
|
||||
self.approve_permission, _ = Permission.objects.get_or_create(
|
||||
codename="can_approve_deletions",
|
||||
name="Can approve AI-recommended deletions",
|
||||
content_type=content_type,
|
||||
)
|
||||
self.config_permission, _ = Permission.objects.get_or_create(
|
||||
codename="can_configure_ai",
|
||||
name="Can configure AI settings",
|
||||
content_type=content_type,
|
||||
)
|
||||
|
||||
# Assign permissions to groups
|
||||
# Viewers can only view
|
||||
self.viewer_group.permissions.add(self.view_permission)
|
||||
|
||||
# Editors can view and apply
|
||||
self.editor_group.permissions.add(self.view_permission, self.apply_permission)
|
||||
|
||||
# Admins can do everything
|
||||
self.admin_group.permissions.add(
|
||||
self.view_permission,
|
||||
self.apply_permission,
|
||||
self.approve_permission,
|
||||
self.config_permission,
|
||||
)
|
||||
|
||||
def test_viewer_role_permissions(self):
|
||||
"""Test that viewer role has appropriate permissions."""
|
||||
user = User.objects.create_user(
|
||||
username="viewer", email="viewer@test.com", password="viewer123"
|
||||
)
|
||||
user.groups.add(self.viewer_group)
|
||||
|
||||
# Refresh user to get updated permissions
|
||||
user = User.objects.get(pk=user.pk)
|
||||
|
||||
self.assertTrue(user.has_perm("documents.can_view_ai_suggestions"))
|
||||
self.assertFalse(user.has_perm("documents.can_apply_ai_suggestions"))
|
||||
self.assertFalse(user.has_perm("documents.can_approve_deletions"))
|
||||
self.assertFalse(user.has_perm("documents.can_configure_ai"))
|
||||
|
||||
def test_editor_role_permissions(self):
|
||||
"""Test that editor role has appropriate permissions."""
|
||||
user = User.objects.create_user(
|
||||
username="editor", email="editor@test.com", password="editor123"
|
||||
)
|
||||
user.groups.add(self.editor_group)
|
||||
|
||||
# Refresh user to get updated permissions
|
||||
user = User.objects.get(pk=user.pk)
|
||||
|
||||
self.assertTrue(user.has_perm("documents.can_view_ai_suggestions"))
|
||||
self.assertTrue(user.has_perm("documents.can_apply_ai_suggestions"))
|
||||
self.assertFalse(user.has_perm("documents.can_approve_deletions"))
|
||||
self.assertFalse(user.has_perm("documents.can_configure_ai"))
|
||||
|
||||
def test_admin_role_permissions(self):
|
||||
"""Test that admin role has all permissions."""
|
||||
user = User.objects.create_user(
|
||||
username="ai_admin", email="ai_admin@test.com", password="admin123"
|
||||
)
|
||||
user.groups.add(self.admin_group)
|
||||
|
||||
# Refresh user to get updated permissions
|
||||
user = User.objects.get(pk=user.pk)
|
||||
|
||||
self.assertTrue(user.has_perm("documents.can_view_ai_suggestions"))
|
||||
self.assertTrue(user.has_perm("documents.can_apply_ai_suggestions"))
|
||||
self.assertTrue(user.has_perm("documents.can_approve_deletions"))
|
||||
self.assertTrue(user.has_perm("documents.can_configure_ai"))
|
||||
|
||||
def test_user_with_multiple_groups(self):
|
||||
"""Test that user permissions accumulate from multiple groups."""
|
||||
user = User.objects.create_user(
|
||||
username="multi_role", email="multi@test.com", password="multi123"
|
||||
)
|
||||
user.groups.add(self.viewer_group, self.editor_group)
|
||||
|
||||
# Refresh user to get updated permissions
|
||||
user = User.objects.get(pk=user.pk)
|
||||
|
||||
# Should have both viewer and editor permissions
|
||||
self.assertTrue(user.has_perm("documents.can_view_ai_suggestions"))
|
||||
self.assertTrue(user.has_perm("documents.can_apply_ai_suggestions"))
|
||||
self.assertFalse(user.has_perm("documents.can_approve_deletions"))
|
||||
|
||||
def test_direct_permission_assignment_overrides_group(self):
|
||||
"""Test that direct permission assignment works alongside group permissions."""
|
||||
user = User.objects.create_user(
|
||||
username="special", email="special@test.com", password="special123"
|
||||
)
|
||||
user.groups.add(self.viewer_group)
|
||||
|
||||
# Directly assign approval permission
|
||||
user.user_permissions.add(self.approve_permission)
|
||||
|
||||
# Refresh user to get updated permissions
|
||||
user = User.objects.get(pk=user.pk)
|
||||
|
||||
# Should have viewer group permissions plus direct permission
|
||||
self.assertTrue(user.has_perm("documents.can_view_ai_suggestions"))
|
||||
self.assertFalse(user.has_perm("documents.can_apply_ai_suggestions"))
|
||||
self.assertTrue(user.has_perm("documents.can_approve_deletions"))
|
||||
self.assertFalse(user.has_perm("documents.can_configure_ai"))
|
||||
|
||||
|
||||
class TestPermissionAssignment(TestCase):
|
||||
"""Test permission assignment and revocation."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test user."""
|
||||
self.user = User.objects.create_user(
|
||||
username="testuser", email="test@test.com", password="test123"
|
||||
)
|
||||
content_type = ContentType.objects.get_for_model(Document)
|
||||
self.view_permission, _ = Permission.objects.get_or_create(
|
||||
codename="can_view_ai_suggestions",
|
||||
name="Can view AI suggestions",
|
||||
content_type=content_type,
|
||||
)
|
||||
|
||||
def test_assign_permission_to_user(self):
|
||||
"""Test assigning permission to user."""
|
||||
self.assertFalse(self.user.has_perm("documents.can_view_ai_suggestions"))
|
||||
|
||||
self.user.user_permissions.add(self.view_permission)
|
||||
self.user = User.objects.get(pk=self.user.pk)
|
||||
|
||||
self.assertTrue(self.user.has_perm("documents.can_view_ai_suggestions"))
|
||||
|
||||
def test_revoke_permission_from_user(self):
|
||||
"""Test revoking permission from user."""
|
||||
self.user.user_permissions.add(self.view_permission)
|
||||
self.user = User.objects.get(pk=self.user.pk)
|
||||
self.assertTrue(self.user.has_perm("documents.can_view_ai_suggestions"))
|
||||
|
||||
self.user.user_permissions.remove(self.view_permission)
|
||||
self.user = User.objects.get(pk=self.user.pk)
|
||||
|
||||
self.assertFalse(self.user.has_perm("documents.can_view_ai_suggestions"))
|
||||
|
||||
def test_permission_persistence(self):
|
||||
"""Test that permissions persist across user retrieval."""
|
||||
self.user.user_permissions.add(self.view_permission)
|
||||
|
||||
# Get user from database
|
||||
retrieved_user = User.objects.get(username="testuser")
|
||||
|
||||
self.assertTrue(retrieved_user.has_perm("documents.can_view_ai_suggestions"))
|
||||
|
||||
|
||||
class TestPermissionEdgeCases(TestCase):
|
||||
"""Test edge cases and error conditions for permissions."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test data."""
|
||||
self.factory = APIRequestFactory()
|
||||
self.view = MockView()
|
||||
|
||||
def test_anonymous_user_request(self):
|
||||
"""Test handling of anonymous user."""
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
|
||||
permission = CanViewAISuggestionsPermission()
|
||||
request = self.factory.get("/api/ai/suggestions/")
|
||||
request.user = AnonymousUser()
|
||||
|
||||
result = permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_missing_user_attribute(self):
|
||||
"""Test handling of request without user attribute."""
|
||||
permission = CanViewAISuggestionsPermission()
|
||||
request = self.factory.get("/api/ai/suggestions/")
|
||||
# Don't set request.user
|
||||
|
||||
result = permission.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_inactive_user_with_permission(self):
|
||||
"""Test that inactive users are denied even with permission."""
|
||||
user = User.objects.create_user(
|
||||
username="inactive", email="inactive@test.com", password="inactive123"
|
||||
)
|
||||
user.is_active = False
|
||||
user.save()
|
||||
|
||||
# Add permission
|
||||
content_type = ContentType.objects.get_for_model(Document)
|
||||
permission, _ = Permission.objects.get_or_create(
|
||||
codename="can_view_ai_suggestions",
|
||||
name="Can view AI suggestions",
|
||||
content_type=content_type,
|
||||
)
|
||||
user.user_permissions.add(permission)
|
||||
|
||||
permission_check = CanViewAISuggestionsPermission()
|
||||
request = self.factory.get("/api/ai/suggestions/")
|
||||
request.user = user
|
||||
|
||||
# Inactive users should not pass authentication check
|
||||
result = permission_check.has_permission(request, self.view)
|
||||
|
||||
self.assertFalse(result)
|
||||
Loading…
Add table
Add a link
Reference in a new issue