fix unit tests

This commit is contained in:
Rachid Mrad 2024-10-04 11:47:16 -04:00
commit dd96ae318b
No known key found for this signature in database
8 changed files with 108 additions and 19 deletions

View file

@ -86,6 +86,11 @@ urlpatterns = [
views.PortfolioMemberView.as_view(), views.PortfolioMemberView.as_view(),
name="member", name="member",
), ),
path(
"invitedmember/<int:pk>",
views.PortfolioInvitedMemberView.as_view(),
name="invitedmember",
),
# path( # path(
# "no-organization-members/", # "no-organization-members/",
# views.PortfolioNoMembersView.as_view(), # views.PortfolioNoMembersView.as_view(),

View file

@ -4,6 +4,7 @@ import logging
from django import forms from django import forms
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from registrar.models.portfolio_invitation import PortfolioInvitation
from registrar.models.user_portfolio_permission import UserPortfolioPermission from registrar.models.user_portfolio_permission import UserPortfolioPermission
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
@ -126,3 +127,30 @@ class PortfolioMemberForm(forms.ModelForm):
"additional_permissions", "additional_permissions",
] ]
class PortfolioInvitedMemberForm(forms.ModelForm):
"""
Form for updating a portfolio invited member.
"""
portfolio_roles = forms.MultipleChoiceField(
choices=UserPortfolioRoleChoices.choices,
widget=forms.SelectMultiple(attrs={'class': 'usa-select'}),
required=False,
label="Roles",
)
portfolio_additional_permissions = forms.MultipleChoiceField(
choices=UserPortfolioPermissionChoices.choices,
widget=forms.SelectMultiple(attrs={'class': 'usa-select'}),
required=False,
label="Additional Permissions",
)
class Meta:
model = PortfolioInvitation
fields = [
"portfolio_roles",
"portfolio_additional_permissions",
]

View file

@ -15,17 +15,22 @@
<h1>Member</h1> <h1>Member</h1>
<p>{{ user.first_name }}</p> <p>{{ member.first_name }}</p>
<hr> <hr>
<form class="usa-form usa-form--large" method="post" novalidate> <form class="usa-form usa-form--large" method="post" novalidate>
{% csrf_token %} {% csrf_token %}
{% if form.roles %}
{% input_with_errors form.roles %} {% comment - handling form fields for member %}
{% input_with_errors form.additional_permissions %} {% input_with_errors form.roles %}
{% input_with_errors form.additional_permissions %}
{% elif form.portfolio_roles %}
{% comment - handling form fields for invited member %}
{% input_with_errors form.portfolio_roles %}
{% input_with_errors form.portfolio_additional_permissions %}
{% endif %}
<button <button
type="submit" type="submit"
class="usa-button" class="usa-button"

View file

@ -817,7 +817,6 @@ class TestPortfolio(WebTest):
# Verify that view-only settings are sent in the dynamic HTML # Verify that view-only settings are sent in the dynamic HTML
response = self.client.get(reverse("get_portfolio_members_json") + f"?portfolio={self.portfolio.pk}") response = self.client.get(reverse("get_portfolio_members_json") + f"?portfolio={self.portfolio.pk}")
print(response.content)
self.assertContains(response, '"action_label": "View"') self.assertContains(response, '"action_label": "View"')
self.assertContains(response, '"svg_icon": "visibility"') self.assertContains(response, '"svg_icon": "visibility"')

View file

@ -86,14 +86,6 @@ def get_portfolio_members_json(request):
) )
# def get_member_ids_from_request(request, portfolio):
# """Given the current request,
# get all members that are associated with the given portfolio"""
# member_ids = []
# if portfolio:
# member_ids = UserPortfolioPermission.objects.filter(portfolio=portfolio).values_list("user__id", flat=True)
# return member_ids
def apply_search(data_list, request): def apply_search(data_list, request):
search_term = request.GET.get("search_term", "").lower() search_term = request.GET.get("search_term", "").lower()
@ -153,11 +145,15 @@ def serialize_members(request, portfolio, item, user):
view_only = not user.has_edit_members_portfolio_permission(portfolio) or not user_can_edit_other_users view_only = not user.has_edit_members_portfolio_permission(portfolio) or not user_can_edit_other_users
# ------- USER STATUSES # ------- USER STATUSES
is_admin = UserPortfolioRoleChoices.ORGANIZATION_ADMIN in item['roles'] is_admin = False
if item['roles']:
is_admin = UserPortfolioRoleChoices.ORGANIZATION_ADMIN in item['roles']
action_url = '#' action_url = '#'
if item['source'] == 'permission': if item['source'] == 'permission':
action_url = reverse("member", kwargs={"pk": item['id']}) action_url = reverse("member", kwargs={"pk": item['id']})
elif item['source'] == 'invitation':
action_url = reverse("invitedmember", kwargs={"pk": item['id']})
# ------- SERIALIZE # ------- SERIALIZE
member_json = { member_json = {

View file

@ -3,8 +3,9 @@ from django.http import Http404
from django.shortcuts import render from django.shortcuts import render
from django.urls import reverse from django.urls import reverse
from django.contrib import messages from django.contrib import messages
from registrar.forms.portfolio import PortfolioMemberForm, PortfolioOrgAddressForm, PortfolioSeniorOfficialForm from registrar.forms.portfolio import PortfolioInvitedMemberForm, PortfolioMemberForm, PortfolioOrgAddressForm, PortfolioSeniorOfficialForm
from registrar.models import Portfolio, User from registrar.models import Portfolio, User
from registrar.models.portfolio_invitation import PortfolioInvitation
from registrar.models.user_portfolio_permission import UserPortfolioPermission from registrar.models.user_portfolio_permission import UserPortfolioPermission
from registrar.models.utility.portfolio_helper import UserPortfolioRoleChoices from registrar.models.utility.portfolio_helper import UserPortfolioRoleChoices
from registrar.views.utility.permission_views import ( from registrar.views.utility.permission_views import (
@ -12,6 +13,7 @@ from registrar.views.utility.permission_views import (
PortfolioDomainsPermissionView, PortfolioDomainsPermissionView,
PortfolioBasePermissionView, PortfolioBasePermissionView,
NoPortfolioDomainsPermissionView, NoPortfolioDomainsPermissionView,
PortfolioInvitedMemberPermissionView,
PortfolioMemberPermissionView, PortfolioMemberPermissionView,
PortfolioMembersPermissionView, PortfolioMembersPermissionView,
) )
@ -65,7 +67,7 @@ class PortfolioMemberView(PortfolioMemberPermissionView, View):
return render(request, self.template_name, { return render(request, self.template_name, {
'form': form, 'form': form,
'user': user, 'member': user,
}) })
def post(self, request, pk): def post(self, request, pk):
@ -76,15 +78,41 @@ class PortfolioMemberView(PortfolioMemberPermissionView, View):
if form.is_valid(): if form.is_valid():
form.save() form.save()
return redirect('home') return redirect('members')
return render(request, self.template_name, { return render(request, self.template_name, {
'form': form, 'form': form,
'user': user, # Pass the user object again to the template 'member': user, # Pass the user object again to the template
}) })
class PortfolioInvitedMemberView(PortfolioInvitedMemberPermissionView, View):
template_name = "portfolio_member.html"
form_class = PortfolioInvitedMemberForm
def get(self, request, pk):
portfolio_invitation = get_object_or_404(PortfolioInvitation, pk=pk)
form = self.form_class(instance=portfolio_invitation)
return render(request, self.template_name, {
'form': form,
'member': None,
})
def post(self, request, pk):
portfolio_invitation = get_object_or_404(PortfolioInvitation, pk=pk)
form = self.form_class(request.POST, instance=portfolio_invitation)
if form.is_valid():
form.save()
return redirect('members')
return render(request, self.template_name, {
'form': form,
'member': None, # Pass the user object again to the template
})
class PortfolioNoDomainsView(NoPortfolioDomainsPermissionView, View): class PortfolioNoDomainsView(NoPortfolioDomainsPermissionView, View):
"""Some users have access to the underlying portfolio, but not any domains. """Some users have access to the underlying portfolio, but not any domains.

View file

@ -515,3 +515,22 @@ class PortfolioMemberPermission(PortfolioBasePermission):
return False return False
return super().has_permission() return super().has_permission()
class PortfolioInvitedMemberPermission(PortfolioBasePermission):
"""Permission mixin that allows access to portfolio invited member pages if user
has access, otherwise 403"""
def has_permission(self):
"""Check if this user has access to members for this portfolio.
The user is in self.request.user and the portfolio can be looked
up from the portfolio's primary key in self.kwargs["pk"]"""
portfolio = self.request.session.get("portfolio")
if not self.request.user.has_view_members_portfolio_permission(
portfolio
) and not self.request.user.has_edit_members_portfolio_permission(portfolio):
return False
return super().has_permission()

View file

@ -15,6 +15,7 @@ from .mixins import (
DomainRequestWizardPermission, DomainRequestWizardPermission,
PortfolioDomainRequestsPermission, PortfolioDomainRequestsPermission,
PortfolioDomainsPermission, PortfolioDomainsPermission,
PortfolioInvitedMemberPermission,
UserDeleteDomainRolePermission, UserDeleteDomainRolePermission,
UserProfilePermission, UserProfilePermission,
PortfolioBasePermission, PortfolioBasePermission,
@ -267,3 +268,11 @@ class PortfolioMemberPermissionView(PortfolioMemberPermission, PortfolioBasePerm
This abstract view cannot be instantiated. Actual views must specify This abstract view cannot be instantiated. Actual views must specify
`template_name`. `template_name`.
""" """
class PortfolioInvitedMemberPermissionView(PortfolioInvitedMemberPermission, PortfolioBasePermissionView, abc.ABC):
"""Abstract base view for portfolio member views that enforces permissions.
This abstract view cannot be instantiated. Actual views must specify
`template_name`.
"""