in django admin, new domain invitations are auto retrieved when user exists

This commit is contained in:
David Kennedy 2025-01-06 16:32:28 -05:00
parent 1e12459c10
commit 08efc6629e
No known key found for this signature in database
GPG key ID: 6528A5386E66B96B
2 changed files with 78 additions and 9 deletions

View file

@ -1434,6 +1434,26 @@ class DomainInvitationAdmin(ListHeaderAdmin):
# Get the filtered values # Get the filtered values
return super().changelist_view(request, extra_context=extra_context) return super().changelist_view(request, extra_context=extra_context)
def save_model(self, request, obj, form, change):
"""
Override the save_model method.
On creation of a new domain invitation, attempt to retrieve the invitation,
which will be successful if a user exists for that email; otherwise, will
raise a RuntimeError, and in this case can continue to create the invitation.
"""
# NOTE: is a future ticket accounting for a 'not member of this org' scenario
# to mirror the logic in DomainAddUser view?
if not change: # Domain Invitation creation
try:
User.objects.get(email=obj.email)
obj.retrieve()
except User.DoesNotExist:
# Proceed with invitation as new as exception indicates user does not exist
pass
# Call the parent save method to save the object
super().save_model(request, obj, form, change)
class PortfolioInvitationAdmin(ListHeaderAdmin): class PortfolioInvitationAdmin(ListHeaderAdmin):
"""Custom portfolio invitation admin class.""" """Custom portfolio invitation admin class."""

View file

@ -131,13 +131,11 @@ class TestDomainInvitationAdmin(TestCase):
tests have available superuser, client, and admin tests have available superuser, client, and admin
""" """
@classmethod
def setUpClass(cls):
cls.factory = RequestFactory()
cls.admin = ListHeaderAdmin(model=DomainInvitationAdmin, admin_site=AdminSite())
cls.superuser = create_superuser()
def setUp(self): def setUp(self):
self.factory = RequestFactory()
self.admin = ListHeaderAdmin(model=DomainInvitationAdmin, admin_site=AdminSite())
self.superuser = create_superuser()
self.domain = Domain.objects.create(name="example.com")
"""Create a client object""" """Create a client object"""
self.client = Client(HTTP_HOST="localhost:8080") self.client = Client(HTTP_HOST="localhost:8080")
@ -145,9 +143,6 @@ class TestDomainInvitationAdmin(TestCase):
"""Delete all DomainInvitation objects""" """Delete all DomainInvitation objects"""
DomainInvitation.objects.all().delete() DomainInvitation.objects.all().delete()
Contact.objects.all().delete() Contact.objects.all().delete()
@classmethod
def tearDownClass(self):
User.objects.all().delete() User.objects.all().delete()
@less_console_noise_decorator @less_console_noise_decorator
@ -168,6 +163,7 @@ class TestDomainInvitationAdmin(TestCase):
) )
self.assertContains(response, "Show more") self.assertContains(response, "Show more")
@less_console_noise_decorator
def test_get_filters(self): def test_get_filters(self):
"""Ensures that our filters are displaying correctly""" """Ensures that our filters are displaying correctly"""
with less_console_noise(): with less_console_noise():
@ -192,6 +188,59 @@ class TestDomainInvitationAdmin(TestCase):
self.assertContains(response, invited_html, count=1) self.assertContains(response, invited_html, count=1)
self.assertContains(response, retrieved_html, count=1) self.assertContains(response, retrieved_html, count=1)
@less_console_noise_decorator
def test_save_model_user_exists(self):
"""Test saving a domain invitation when the user exists.
Should attempt to retrieve the domain invitation."""
# Create a user with the same email
User.objects.create_user(email="test@example.com", password="password", username="username")
# Create a domain invitation instance
invitation = DomainInvitation(email="test@example.com", domain=self.domain)
admin_instance = DomainInvitationAdmin(DomainInvitation, admin_site=None)
# Create a request object
request = self.factory.post("/admin/registrar/DomainInvitation/add/")
request.user = self.superuser
# Patch the retrieve method
with patch.object(DomainInvitation, "retrieve") as mock_retrieve:
admin_instance.save_model(request, invitation, form=None, change=False)
# Assert retrieve was called
mock_retrieve.assert_called_once()
# Assert the invitation was saved
self.assertEqual(DomainInvitation.objects.count(), 1)
self.assertEqual(DomainInvitation.objects.first().email, "test@example.com")
@less_console_noise_decorator
def test_save_model_user_does_not_exist(self):
"""Test saving a domain invitation when the user does not exist.
Should not attempt to retrieve the domain invitation."""
# Create a domain invitation instance
invitation = DomainInvitation(email="nonexistent@example.com", domain=self.domain)
admin_instance = DomainInvitationAdmin(DomainInvitation, admin_site=None)
# Create a request object
request = self.factory.post("/admin/registrar/DomainInvitation/add/")
request.user = self.superuser
# Patch the retrieve method to ensure it is not called
with patch.object(DomainInvitation, "retrieve") as mock_retrieve:
admin_instance.save_model(request, invitation, form=None, change=False)
# Assert retrieve was not called
mock_retrieve.assert_not_called()
# Assert the invitation was saved
self.assertEqual(DomainInvitation.objects.count(), 1)
self.assertEqual(DomainInvitation.objects.first().email, "nonexistent@example.com")
class TestUserPortfolioPermissionAdmin(TestCase): class TestUserPortfolioPermissionAdmin(TestCase):
"""Tests for the PortfolioInivtationAdmin class""" """Tests for the PortfolioInivtationAdmin class"""