-
- {{ permission.user.email }}
+ |
+ {{ item.permission.user.email }}
+ {% if item.has_admin_flag %}Admin{% endif %}
|
- {{ permission.role|title }} |
+ {% if not portfolio %}{{ item.permission.role|title }} | {% endif %}
{% if can_delete_users %}
Domain managers
Remove
{# Display a custom message if the user is trying to delete themselves #}
- {% if permission.user.email == current_user_email %}
+ {% if item.permission.user.email == current_user_email %}
Domain managers
aria-describedby="You will be removed from this domain"
data-force-action
>
-
@@ -111,7 +121,7 @@ Domain managers
- {% if domain.invitations.exists %}
+ {% if invitations %}
Invitations
@@ -120,21 +130,22 @@ Invitations
Email |
Date created |
- Status |
+ {% if not portfolio %}Status | {% endif %}
Action |
- {% for invitation in domain.invitations.all %}
+ {% for invitation in invitations %}
-
- {{ invitation.email }}
+ |
+ {{ invitation.domain_invitation.email }}
+ {% if invitation.has_admin_flag %}Admin{% endif %}
|
- {{ invitation.created_at|date }} |
- {{ invitation.status|title }} |
+ {{ invitation.domain_invitation.created_at|date }} |
+ {% if not portfolio %}{{ invitation.domain_invitation.status|title }} | {% endif %}
- {% if invitation.status == invitation.DomainInvitationStatus.INVITED %}
-
{% endif %}
diff --git a/src/registrar/tests/test_views_domain.py b/src/registrar/tests/test_views_domain.py
index a375493be..1b7731222 100644
--- a/src/registrar/tests/test_views_domain.py
+++ b/src/registrar/tests/test_views_domain.py
@@ -370,6 +370,17 @@ def setUpClass(cls):
]
AllowedEmail.objects.bulk_create(allowed_emails)
+ def setUp(self):
+ super().setUp()
+ # Add portfolio in order to test portfolio view
+ self.portfolio = Portfolio.objects.create(creator=self.user, organization_name="Ice Cream")
+ # Add the portfolio to the domain_information object
+ self.domain_information.portfolio = self.portfolio
+ # Add portfolio perms to the user object
+ self.portfolio_permission, _ = UserPortfolioPermission.objects.get_or_create(
+ user=self.user, portfolio=self.portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
+ )
+
@classmethod
def tearDownClass(cls):
super().tearDownClass()
@@ -383,13 +394,22 @@ def tearDown(self):
def test_domain_managers(self):
response = self.client.get(reverse("domain-users", kwargs={"pk": self.domain.id}))
self.assertContains(response, "Domain managers")
+ self.assertContains(response, "Add a domain manager")
+ # assert that the non-portfolio view contains Role column and doesn't contain Admin
+ self.assertContains(response, "Role")
+ self.assertNotContains(response, "Admin")
+ self.assertContains(response, "This domain has one manager. Adding more can prevent issues.")
@less_console_noise_decorator
- def test_domain_managers_add_link(self):
- """Button to get to user add page works."""
- management_page = self.app.get(reverse("domain-users", kwargs={"pk": self.domain.id}))
- add_page = management_page.click("Add a domain manager")
- self.assertContains(add_page, "Add a domain manager")
+ @override_flag("organization_feature", active=True)
+ def test_domain_managers_portfolio_view(self):
+ response = self.client.get(reverse("domain-users", kwargs={"pk": self.domain.id}))
+ self.assertContains(response, "Domain managers")
+ self.assertContains(response, "Add a domain manager")
+ # assert that the portfolio view doesn't contain Role column and does contain Admin
+ self.assertNotContains(response, "Role")
+ self.assertContains(response, "Admin")
+ self.assertContains(response, "This domain has one manager. Adding more can prevent issues.")
@less_console_noise_decorator
def test_domain_user_add(self):
diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py
index 6e85c9ffb..c378feeb9 100644
--- a/src/registrar/views/domain.py
+++ b/src/registrar/views/domain.py
@@ -28,6 +28,7 @@
UserPortfolioPermission,
PublicContact,
)
+from registrar.models.utility.portfolio_helper import UserPortfolioRoleChoices
from registrar.utility.enums import DefaultEmail
from registrar.utility.errors import (
GenericError,
@@ -841,11 +842,86 @@ def get_context_data(self, **kwargs):
# Add modal buttons to the context (such as for delete)
context = self._add_modal_buttons_to_context(context)
+ # Get portfolio from session (if set)
+ portfolio = self.request.session.get("portfolio")
+
+ # Add domain manager roles separately in order to also pass admin status
+ context = self._add_domain_manager_roles_to_context(context, portfolio)
+
+ # Add domain invitations separately in order to also pass admin status
+ context = self._add_invitations_to_context(context, portfolio)
+
# Get the email of the current user
context["current_user_email"] = self.request.user.email
return context
+ def get(self, request, *args, **kwargs):
+ """Get method for DomainUsersView."""
+ # Call the parent class's `get` method to get the response and context
+ response = super().get(request, *args, **kwargs)
+
+ # Ensure context is available after the parent call
+ context = response.context_data if hasattr(response, "context_data") else {}
+
+ # Check if context contains `domain_managers_roles` and its length is 1
+ if context.get("domain_manager_roles") and len(context["domain_manager_roles"]) == 1:
+ # Add an info message
+ messages.info(request, "This domain has one manager. Adding more can prevent issues.")
+
+ return response
+
+ def _add_domain_manager_roles_to_context(self, context, portfolio):
+ """Add domain_manager_roles to context separately, as roles need admin indicator."""
+
+ # Prepare a list to store roles with an admin flag
+ domain_manager_roles = []
+
+ for permission in self.object.permissions.all():
+ # Determine if the user has the ORGANIZATION_ADMIN role
+ has_admin_flag = any(
+ UserPortfolioRoleChoices.ORGANIZATION_ADMIN in portfolio_permission.roles
+ and portfolio == portfolio_permission.portfolio
+ for portfolio_permission in permission.user.portfolio_permissions.all()
+ )
+
+ # Add the role along with the computed flag to the list
+ domain_manager_roles.append({"permission": permission, "has_admin_flag": has_admin_flag})
+
+ # Pass roles_with_flags to the context
+ context["domain_manager_roles"] = domain_manager_roles
+
+ return context
+
+ def _add_invitations_to_context(self, context, portfolio):
+ """Add invitations to context separately as invitations needs admin indicator."""
+
+ # Prepare a list to store invitations with an admin flag
+ invitations = []
+
+ for domain_invitation in self.object.invitations.all():
+ # Check if there are any PortfolioInvitations linked to the same portfolio with the ORGANIZATION_ADMIN role
+ has_admin_flag = False
+
+ # Query PortfolioInvitations linked to the same portfolio and check roles
+ portfolio_invitations = PortfolioInvitation.objects.filter(
+ portfolio=portfolio, email=domain_invitation.email
+ )
+
+ # If any of the PortfolioInvitations have the ORGANIZATION_ADMIN role, set the flag to True
+ for portfolio_invitation in portfolio_invitations:
+ if UserPortfolioRoleChoices.ORGANIZATION_ADMIN in portfolio_invitation.roles:
+ has_admin_flag = True
+ break # Once we find one match, no need to check further
+
+ # Add the role along with the computed flag to the list
+ invitations.append({"domain_invitation": domain_invitation, "has_admin_flag": has_admin_flag})
+
+ # Pass roles_with_flags to the context
+ context["invitations"] = invitations
+
+ return context
+
def _add_booleans_to_context(self, context):
# Determine if the current user can delete managers
domain_pk = None
| |