manage.get.gov/src/registrar/views/member_domains_json.py
Rachid Mrad 14d6196b4a
lint
2024-12-18 18:07:43 -05:00

183 lines
8 KiB
Python

import logging
from django.db import models
from django.http import JsonResponse
from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404
from django.views import View
from registrar.models import UserDomainRole, Domain, DomainInformation, User
from django.urls import reverse
from django.db.models import Q
from registrar.models.domain_invitation import DomainInvitation
from registrar.views.utility.mixins import PortfolioMemberDomainsPermission
logger = logging.getLogger(__name__)
class PortfolioMemberDomainsJson(PortfolioMemberDomainsPermission, View):
def get(self, request):
"""Given the current request,
get all domains that are associated with the portfolio, or
associated with the member/invited member"""
domain_ids = self.get_domain_ids_from_request(request)
objects = Domain.objects.filter(id__in=domain_ids).select_related("domain_info__sub_organization")
unfiltered_total = objects.count()
objects = self.apply_search(objects, request)
objects = self.apply_sorting(objects, request)
paginator = Paginator(objects, self.get_page_size(request))
page_number = request.GET.get("page")
page_obj = paginator.get_page(page_number)
member_id = request.GET.get("member_id")
domains = [self.serialize_domain(domain, member_id, request.user) for domain in page_obj.object_list]
return JsonResponse(
{
"domains": domains,
"page": page_obj.number,
"num_pages": paginator.num_pages,
"has_previous": page_obj.has_previous(),
"has_next": page_obj.has_next(),
"total": paginator.count,
"unfiltered_total": unfiltered_total,
}
)
def get_page_size(self, request):
"""Gets the page size.
If member_only, need to return the entire result set every time, so need
to set to a very large page size. If not member_only, this can be adjusted
to provide a smaller page size"""
member_only = request.GET.get("member_only", "false").lower() in ["true", "1"]
if member_only:
# This number needs to remain very high as the entire result set
# must be returned when member_only
return 1000
else:
# This number can be adjusted if we want to add pagination to the result page
# later
return 1000
def get_domain_ids_from_request(self, request):
"""Get domain ids from request.
request.get.email - email address of invited member
request.get.member_id - member id of member
request.get.portfolio - portfolio id of portfolio
request.get.member_only - whether to return only domains associated with member
or to return all domains in the portfolio
"""
portfolio = request.GET.get("portfolio")
email = request.GET.get("email")
member_id = request.GET.get("member_id")
member_only = request.GET.get("member_only", "false").lower() in ["true", "1"]
if member_only:
if member_id:
member = get_object_or_404(User, pk=member_id)
domain_info_ids = DomainInformation.objects.filter(portfolio=portfolio).values_list(
"domain_id", flat=True
)
user_domain_roles = UserDomainRole.objects.filter(user=member).values_list("domain_id", flat=True)
return domain_info_ids.intersection(user_domain_roles)
elif email:
domain_info_ids = DomainInformation.objects.filter(portfolio=portfolio).values_list(
"domain_id", flat=True
)
domain_invitations = DomainInvitation.objects.filter(
email=email, status=DomainInvitation.DomainInvitationStatus.INVITED
).values_list("domain_id", flat=True)
return domain_info_ids.intersection(domain_invitations)
else:
domain_infos = DomainInformation.objects.filter(portfolio=portfolio)
return domain_infos.values_list("domain_id", flat=True)
logger.warning("Invalid search criteria, returning empty results list")
return []
def apply_search(self, queryset, request):
search_term = request.GET.get("search_term")
if search_term:
queryset = queryset.filter(Q(name__icontains=search_term))
return queryset
def apply_sorting(self, queryset, request):
# Get the sorting parameters from the request
sort_by = request.GET.get("sort_by", "name")
order = request.GET.get("order", "asc")
# Sort by 'checked' if specified, otherwise by the given field
if sort_by == "checked":
# Get list of checked ids from the request
checked_ids = request.GET.get("checkedDomainIds")
if checked_ids:
# Split the comma-separated string into a list of integers
checked_ids = [int(id.strip()) for id in checked_ids.split(",") if id.strip().isdigit()]
else:
# If no value is passed, set checked_ids to an empty list
checked_ids = []
# Annotate each object with a 'checked' value based on whether its ID is in checkedIds
queryset = queryset.annotate(
checked=models.Case(
models.When(id__in=checked_ids, then=models.Value(True)),
default=models.Value(False),
output_field=models.BooleanField(),
)
)
# Add ordering logic for 'checked'
if order == "desc":
queryset = queryset.order_by("-checked", "name")
else:
queryset = queryset.order_by("checked", "name")
else:
# Handle other fields as normal
if order == "desc":
sort_by = f"-{sort_by}"
queryset = queryset.order_by(sort_by)
return queryset
def serialize_domain(self, domain, member_id, user):
suborganization_name = None
try:
domain_info = domain.domain_info
if domain_info:
suborganization = domain_info.sub_organization
if suborganization:
suborganization_name = suborganization.name
except Domain.domain_info.RelatedObjectDoesNotExist:
domain_info = None
logger.debug(f"Issue in domains_json: We could not find domain_info for {domain}")
# Check if there is a UserDomainRole for this domain and user
user_domain_role_exists = UserDomainRole.objects.filter(domain_id=domain.id, user=user).exists()
view_only = not user_domain_role_exists or domain.state in [Domain.State.DELETED, Domain.State.ON_HOLD]
# Check if the specified member is the only member assigned as manager of domain
only_member_assigned_to_domain = False
if member_id:
member_domain_role_count = UserDomainRole.objects.filter(
domain_id=domain.id, role=UserDomainRole.Roles.MANAGER
).count()
member_domain_role_exists = UserDomainRole.objects.filter(
domain_id=domain.id, user_id=member_id, role=UserDomainRole.Roles.MANAGER
).exists()
only_member_assigned_to_domain = member_domain_role_exists and member_domain_role_count == 1
return {
"id": domain.id,
"name": domain.name,
"member_is_only_manager": only_member_assigned_to_domain,
"expiration_date": domain.expiration_date,
"state": domain.state,
"state_display": domain.state_display(),
"get_state_help_text": domain.get_state_help_text(),
"action_url": reverse("domain", kwargs={"pk": domain.id}),
"action_label": ("View" if view_only else "Manage"),
"svg_icon": ("visibility" if view_only else "settings"),
"domain_info__sub_organization": suborganization_name,
}