mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-16 17:47:02 +02:00
Convert investigator id to investigator name in descriptive subheader on admin lists, update unit test, linting
This commit is contained in:
parent
257db0fae5
commit
10b0700657
5 changed files with 81 additions and 21 deletions
|
@ -41,17 +41,45 @@ class ListHeaderAdmin(AuditedAdmin):
|
||||||
return super().changelist_view(request, extra_context=extra_context)
|
return super().changelist_view(request, extra_context=extra_context)
|
||||||
|
|
||||||
def get_filters(self, request):
|
def get_filters(self, request):
|
||||||
|
"""Retrieve the current set of parameters being used to filter the table
|
||||||
|
Returns:
|
||||||
|
dictionary objects in the format {parameter_name: string,
|
||||||
|
parameter_value: string}
|
||||||
|
TODO: convert investigator id to investigator username
|
||||||
|
"""
|
||||||
|
|
||||||
filters = []
|
filters = []
|
||||||
# Retrieve the filter parameters
|
# Retrieve the filter parameters
|
||||||
for param in request.GET.keys():
|
for param in request.GET.keys():
|
||||||
# Exclude the default search parameter 'q'
|
# Exclude the default search parameter 'q'
|
||||||
if param != "q" and param != "o":
|
if param != "q" and param != "o":
|
||||||
# Append the filter parameter and its value to the list
|
parameter_name = (
|
||||||
|
param.replace("__exact", "")
|
||||||
|
.replace("_type", "")
|
||||||
|
.replace("__id", " id")
|
||||||
|
)
|
||||||
|
|
||||||
|
if parameter_name == "investigator id":
|
||||||
|
# Retrieves the corresponding contact from Users
|
||||||
|
id_value = request.GET.get(param)
|
||||||
|
try:
|
||||||
|
contact = models.User.objects.get(id=id_value)
|
||||||
|
investigator_name = contact.first_name + " " + contact.last_name
|
||||||
|
|
||||||
filters.append(
|
filters.append(
|
||||||
{
|
{
|
||||||
"parameter_name": param.replace("__exact", "")
|
"parameter_name": "investigator",
|
||||||
.replace("_type", "")
|
"parameter_value": investigator_name,
|
||||||
.replace("__id", " id"),
|
}
|
||||||
|
)
|
||||||
|
except models.User.DoesNotExist:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# For other parameter names, append a dictionary with the original
|
||||||
|
# parameter_name and the corresponding parameter_value
|
||||||
|
filters.append(
|
||||||
|
{
|
||||||
|
"parameter_name": parameter_name,
|
||||||
"parameter_value": request.GET.get(param),
|
"parameter_value": request.GET.get(param),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -128,6 +156,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
|
|
||||||
"""Customize the applications listing view."""
|
"""Customize the applications listing view."""
|
||||||
|
|
||||||
|
# Columns
|
||||||
list_display = [
|
list_display = [
|
||||||
"requested_domain",
|
"requested_domain",
|
||||||
"status",
|
"status",
|
||||||
|
@ -136,7 +165,11 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
"submitter",
|
"submitter",
|
||||||
"investigator",
|
"investigator",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Filters
|
||||||
list_filter = ("status", "organization_type", "investigator")
|
list_filter = ("status", "organization_type", "investigator")
|
||||||
|
|
||||||
|
# Search
|
||||||
search_fields = [
|
search_fields = [
|
||||||
"requested_domain__name",
|
"requested_domain__name",
|
||||||
"submitter__email",
|
"submitter__email",
|
||||||
|
@ -144,6 +177,8 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
"submitter__last_name",
|
"submitter__last_name",
|
||||||
]
|
]
|
||||||
search_help_text = "Search by domain or submitter."
|
search_help_text = "Search by domain or submitter."
|
||||||
|
|
||||||
|
# Detail view
|
||||||
fieldsets = [
|
fieldsets = [
|
||||||
(None, {"fields": ["status", "investigator", "creator"]}),
|
(None, {"fields": ["status", "investigator", "creator"]}),
|
||||||
(
|
(
|
||||||
|
@ -192,6 +227,8 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
{"fields": ["is_policy_acknowledged"]},
|
{"fields": ["is_policy_acknowledged"]},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Read only that we'll leverage for CISA Analysts
|
||||||
readonly_fields = [
|
readonly_fields = [
|
||||||
"creator",
|
"creator",
|
||||||
"type_of_work",
|
"type_of_work",
|
||||||
|
@ -240,7 +277,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
def get_readonly_fields(self, request, obj=None):
|
def get_readonly_fields(self, request, obj=None):
|
||||||
if request.user.is_superuser:
|
if request.user.is_superuser:
|
||||||
# Superusers have full access, no fields are read-only
|
# Superusers have full access, no fields are read-only
|
||||||
return ()
|
return []
|
||||||
else:
|
else:
|
||||||
# Regular users can only view the specified fields
|
# Regular users can only view the specified fields
|
||||||
return self.readonly_fields
|
return self.readonly_fields
|
||||||
|
|
|
@ -91,11 +91,11 @@ INSTALLED_APPS = [
|
||||||
# vv Required by django.contrib.admin vv
|
# vv Required by django.contrib.admin vv
|
||||||
# the "user" model! *\o/*
|
# the "user" model! *\o/*
|
||||||
"django.contrib.auth",
|
"django.contrib.auth",
|
||||||
# generic interface for Django models
|
# audit logging of changes to models
|
||||||
"auditlog",
|
|
||||||
# library to simplify form templating
|
|
||||||
# it needs to be listed before django.contrib.contenttypes
|
# it needs to be listed before django.contrib.contenttypes
|
||||||
# for a ContentType query in fixtures.py
|
# for a ContentType query in fixtures.py
|
||||||
|
"auditlog",
|
||||||
|
# generic interface for Django models
|
||||||
"django.contrib.contenttypes",
|
"django.contrib.contenttypes",
|
||||||
# required for CSRF protection and many other things
|
# required for CSRF protection and many other things
|
||||||
"django.contrib.sessions",
|
"django.contrib.sessions",
|
||||||
|
@ -108,7 +108,7 @@ INSTALLED_APPS = [
|
||||||
"django.contrib.staticfiles",
|
"django.contrib.staticfiles",
|
||||||
# application used for integrating with Login.gov
|
# application used for integrating with Login.gov
|
||||||
"djangooidc",
|
"djangooidc",
|
||||||
# audit logging of changes to models
|
# library to simplify form templating
|
||||||
"widget_tweaks",
|
"widget_tweaks",
|
||||||
# library for Finite State Machine statuses
|
# library for Finite State Machine statuses
|
||||||
"django_fsm",
|
"django_fsm",
|
||||||
|
|
|
@ -65,6 +65,11 @@ class UserFixture:
|
||||||
"first_name": "Rachid-Analyst",
|
"first_name": "Rachid-Analyst",
|
||||||
"last_name": "Mrad-Analyst",
|
"last_name": "Mrad-Analyst",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"username": "b6a15987-5c88-4e26-8de2-ca71a0bdb2cd",
|
||||||
|
"first_name": "Alysia-Analyst",
|
||||||
|
"last_name": "Alysia-Analyst",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
STAFF_PERMISSIONS = [
|
STAFF_PERMISSIONS = [
|
||||||
|
@ -99,7 +104,7 @@ class UserFixture:
|
||||||
logger.debug("User object created for %s" % admin["first_name"])
|
logger.debug("User object created for %s" % admin["first_name"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(e)
|
logger.warning(e)
|
||||||
logger.debug("All superusers loaded.")
|
logger.info("All superusers loaded.")
|
||||||
|
|
||||||
logger.info("Going to load %s CISA analysts (staff)" % str(len(cls.STAFF)))
|
logger.info("Going to load %s CISA analysts (staff)" % str(len(cls.STAFF)))
|
||||||
for staff in cls.STAFF:
|
for staff in cls.STAFF:
|
||||||
|
@ -150,7 +155,7 @@ class UserFixture:
|
||||||
logger.debug("User object created for %s" % staff["first_name"])
|
logger.debug("User object created for %s" % staff["first_name"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(e)
|
logger.warning(e)
|
||||||
logger.debug("All CISA analysts (staff) loaded.")
|
logger.info("All CISA analysts (staff) loaded.")
|
||||||
|
|
||||||
|
|
||||||
class DomainApplicationFixture:
|
class DomainApplicationFixture:
|
||||||
|
|
|
@ -8,7 +8,7 @@ from typing import List, Dict
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model, login
|
from django.contrib.auth import get_user_model, login
|
||||||
|
|
||||||
from registrar.models import Contact, DraftDomain, Website, DomainApplication
|
from registrar.models import Contact, DraftDomain, Website, DomainApplication, User
|
||||||
|
|
||||||
|
|
||||||
def get_handlers():
|
def get_handlers():
|
||||||
|
@ -157,3 +157,17 @@ def completed_application(
|
||||||
application.alternative_domains.add(alt)
|
application.alternative_domains.add(alt)
|
||||||
|
|
||||||
return application
|
return application
|
||||||
|
|
||||||
|
def mock_user():
|
||||||
|
"""A simple user."""
|
||||||
|
user_kwargs = dict(
|
||||||
|
id = 4,
|
||||||
|
first_name = "Rachid",
|
||||||
|
last_name = "Mrad",
|
||||||
|
)
|
||||||
|
|
||||||
|
user, _ = User.objects.get_or_create(
|
||||||
|
**user_kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
|
@ -2,7 +2,7 @@ from django.test import TestCase, RequestFactory, Client
|
||||||
from django.contrib.admin.sites import AdminSite
|
from django.contrib.admin.sites import AdminSite
|
||||||
from registrar.admin import DomainApplicationAdmin, ListHeaderAdmin
|
from registrar.admin import DomainApplicationAdmin, ListHeaderAdmin
|
||||||
from registrar.models import DomainApplication, DomainInformation, User
|
from registrar.models import DomainApplication, DomainInformation, User
|
||||||
from .common import completed_application
|
from .common import completed_application, mock_user
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -184,12 +184,15 @@ class TestDomainApplicationAdmin(TestCase):
|
||||||
p = "adminpassword"
|
p = "adminpassword"
|
||||||
self.client.login(username="admin", password=p)
|
self.client.login(username="admin", password=p)
|
||||||
|
|
||||||
|
# Mock a user
|
||||||
|
user = mock_user()
|
||||||
|
|
||||||
# Make the request using the Client class
|
# Make the request using the Client class
|
||||||
# which handles CSRF
|
# which handles CSRF
|
||||||
# Follow=True handles the redirect
|
# Follow=True handles the redirect
|
||||||
response = self.client.get(
|
response = self.client.get(
|
||||||
"/admin/registrar/domainapplication/",
|
"/admin/registrar/domainapplication/",
|
||||||
{"status__exact": "started", "investigator__id__exact": "4", "q": "Hello"},
|
{"status__exact": "started", "investigator__id__exact": user.id, "q": "Hello"},
|
||||||
follow=True,
|
follow=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -204,7 +207,7 @@ class TestDomainApplicationAdmin(TestCase):
|
||||||
filters,
|
filters,
|
||||||
[
|
[
|
||||||
{"parameter_name": "status", "parameter_value": "started"},
|
{"parameter_name": "status", "parameter_value": "started"},
|
||||||
{"parameter_name": "investigator id", "parameter_value": "4"},
|
{"parameter_name": "investigator", "parameter_value": user.first_name + " " + user.last_name},
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -212,7 +215,7 @@ class TestDomainApplicationAdmin(TestCase):
|
||||||
# Create a mock request object
|
# Create a mock request object
|
||||||
request = self.factory.get("/admin/yourmodel/")
|
request = self.factory.get("/admin/yourmodel/")
|
||||||
# Set the GET parameters for testing
|
# Set the GET parameters for testing
|
||||||
request.GET = {"status": "started", "investigator id": "4", "q": "search_value"}
|
request.GET = {"status": "started", "investigator": "Rachid Mrad", "q": "search_value"}
|
||||||
# Call the get_filters method
|
# Call the get_filters method
|
||||||
filters = self.admin.get_filters(request)
|
filters = self.admin.get_filters(request)
|
||||||
|
|
||||||
|
@ -221,11 +224,12 @@ class TestDomainApplicationAdmin(TestCase):
|
||||||
filters,
|
filters,
|
||||||
[
|
[
|
||||||
{"parameter_name": "status", "parameter_value": "started"},
|
{"parameter_name": "status", "parameter_value": "started"},
|
||||||
{"parameter_name": "investigator id", "parameter_value": "4"},
|
{"parameter_name": "investigator", "parameter_value": "Rachid Mrad"},
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# delete any applications too
|
# delete any applications too
|
||||||
DomainApplication.objects.all().delete()
|
DomainApplication.objects.all().delete()
|
||||||
|
User.objects.all().delete()
|
||||||
self.superuser.delete()
|
self.superuser.delete()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue