mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-19 19:09:22 +02:00
Merge pull request #1977 from cisagov/za/1924-remove-domain-info-for-analysts
Ticket #1924: Remove domain info for analysts
This commit is contained in:
commit
07f0fd9b93
5 changed files with 163 additions and 10 deletions
|
@ -1436,6 +1436,13 @@ class DomainInformationInline(admin.StackedInline):
|
||||||
"submitter",
|
"submitter",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
"""Custom has_change_permission override so that we can specify that
|
||||||
|
analysts can edit this through this inline, but not through the model normally"""
|
||||||
|
if request.user.has_perm("registrar.analyst_access_permission"):
|
||||||
|
return True
|
||||||
|
return super().has_change_permission(request, obj)
|
||||||
|
|
||||||
def formfield_for_manytomany(self, db_field, request, **kwargs):
|
def formfield_for_manytomany(self, db_field, request, **kwargs):
|
||||||
"""customize the behavior of formfields with manytomany relationships. the customized
|
"""customize the behavior of formfields with manytomany relationships. the customized
|
||||||
behavior includes sorting of objects in lists as well as customizing helper text"""
|
behavior includes sorting of objects in lists as well as customizing helper text"""
|
||||||
|
|
37
src/registrar/migrations/0081_create_groups_v10.py
Normal file
37
src/registrar/migrations/0081_create_groups_v10.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# This migration creates the create_full_access_group and create_cisa_analyst_group groups
|
||||||
|
# It is dependent on 0079 (which populates federal agencies)
|
||||||
|
# If permissions on the groups need changing, edit CISA_ANALYST_GROUP_PERMISSIONS
|
||||||
|
# in the user_group model then:
|
||||||
|
# [NOT RECOMMENDED]
|
||||||
|
# step 1: docker-compose exec app ./manage.py migrate --fake registrar 0035_contenttypes_permissions
|
||||||
|
# step 2: docker-compose exec app ./manage.py migrate registrar 0036_create_groups
|
||||||
|
# step 3: fake run the latest migration in the migrations list
|
||||||
|
# [RECOMMENDED]
|
||||||
|
# Alternatively:
|
||||||
|
# step 1: duplicate the migration that loads data
|
||||||
|
# step 2: docker-compose exec app ./manage.py migrate
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
from registrar.models import UserGroup
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
# For linting: RunPython expects a function reference,
|
||||||
|
# so let's give it one
|
||||||
|
def create_groups(apps, schema_editor) -> Any:
|
||||||
|
UserGroup.create_cisa_analyst_group(apps, schema_editor)
|
||||||
|
UserGroup.create_full_access_group(apps, schema_editor)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("registrar", "0080_create_groups_v09"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
create_groups,
|
||||||
|
reverse_code=migrations.RunPython.noop,
|
||||||
|
atomic=True,
|
||||||
|
),
|
||||||
|
]
|
|
@ -26,11 +26,6 @@ class UserGroup(Group):
|
||||||
"model": "contact",
|
"model": "contact",
|
||||||
"permissions": ["change_contact"],
|
"permissions": ["change_contact"],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"app_label": "registrar",
|
|
||||||
"model": "domaininformation",
|
|
||||||
"permissions": ["change_domaininformation"],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"app_label": "registrar",
|
"app_label": "registrar",
|
||||||
"model": "domainrequest",
|
"model": "domainrequest",
|
||||||
|
|
|
@ -129,6 +129,83 @@ class TestDomainAdmin(MockEppLib, WebTest):
|
||||||
)
|
)
|
||||||
mock_add_message.assert_has_calls([expected_call], 1)
|
mock_add_message.assert_has_calls([expected_call], 1)
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
def test_analyst_can_see_inline_domain_information_in_domain_change_form(self):
|
||||||
|
"""Tests if an analyst can still see the inline domain information form"""
|
||||||
|
|
||||||
|
# Create fake creator
|
||||||
|
_creator = User.objects.create(
|
||||||
|
username="MrMeoward",
|
||||||
|
first_name="Meoward",
|
||||||
|
last_name="Jones",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a fake domain request
|
||||||
|
_domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW, user=_creator)
|
||||||
|
|
||||||
|
# Creates a Domain and DomainInformation object
|
||||||
|
_domain_request.approve()
|
||||||
|
|
||||||
|
domain_information = DomainInformation.objects.filter(domain_request=_domain_request).get()
|
||||||
|
domain_information.organization_name = "MonkeySeeMonkeyDo"
|
||||||
|
domain_information.save()
|
||||||
|
|
||||||
|
# We use filter here rather than just domain_information.domain just to get the latest data.
|
||||||
|
domain = Domain.objects.filter(domain_info=domain_information).get()
|
||||||
|
|
||||||
|
p = "userpass"
|
||||||
|
self.client.login(username="staffuser", password=p)
|
||||||
|
response = self.client.get(
|
||||||
|
"/admin/registrar/domain/{}/change/".format(domain.pk),
|
||||||
|
follow=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure the page loaded, and that we're on the right page
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(response, domain.name)
|
||||||
|
|
||||||
|
# Test for data. We only need to test one since its all interconnected.
|
||||||
|
expected_organization_name = "MonkeySeeMonkeyDo"
|
||||||
|
self.assertContains(response, expected_organization_name)
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
def test_admin_can_see_inline_domain_information_in_domain_change_form(self):
|
||||||
|
"""Tests if an admin can still see the inline domain information form"""
|
||||||
|
# Create fake creator
|
||||||
|
_creator = User.objects.create(
|
||||||
|
username="MrMeoward",
|
||||||
|
first_name="Meoward",
|
||||||
|
last_name="Jones",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a fake domain request
|
||||||
|
_domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW, user=_creator)
|
||||||
|
|
||||||
|
# Creates a Domain and DomainInformation object
|
||||||
|
_domain_request.approve()
|
||||||
|
|
||||||
|
domain_information = DomainInformation.objects.filter(domain_request=_domain_request).get()
|
||||||
|
domain_information.organization_name = "MonkeySeeMonkeyDo"
|
||||||
|
domain_information.save()
|
||||||
|
|
||||||
|
# We use filter here rather than just domain_information.domain just to get the latest data.
|
||||||
|
domain = Domain.objects.filter(domain_info=domain_information).get()
|
||||||
|
|
||||||
|
p = "adminpass"
|
||||||
|
self.client.login(username="superuser", password=p)
|
||||||
|
response = self.client.get(
|
||||||
|
"/admin/registrar/domain/{}/change/".format(domain.pk),
|
||||||
|
follow=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure the page loaded, and that we're on the right page
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(response, domain.name)
|
||||||
|
|
||||||
|
# Test for data. We only need to test one since its all interconnected.
|
||||||
|
expected_organization_name = "MonkeySeeMonkeyDo"
|
||||||
|
self.assertContains(response, expected_organization_name)
|
||||||
|
|
||||||
@patch("registrar.admin.DomainAdmin._get_current_date", return_value=date(2024, 1, 1))
|
@patch("registrar.admin.DomainAdmin._get_current_date", return_value=date(2024, 1, 1))
|
||||||
def test_extend_expiration_date_button_epp(self, mock_date_today):
|
def test_extend_expiration_date_button_epp(self, mock_date_today):
|
||||||
"""
|
"""
|
||||||
|
@ -2026,8 +2103,8 @@ class TestDomainInformationAdmin(TestCase):
|
||||||
# Get the other contact
|
# Get the other contact
|
||||||
other_contact = domain_info.other_contacts.all().first()
|
other_contact = domain_info.other_contacts.all().first()
|
||||||
|
|
||||||
p = "userpass"
|
p = "adminpass"
|
||||||
self.client.login(username="staffuser", password=p)
|
self.client.login(username="superuser", password=p)
|
||||||
|
|
||||||
response = self.client.get(
|
response = self.client.get(
|
||||||
"/admin/registrar/domaininformation/{}/change/".format(domain_info.pk),
|
"/admin/registrar/domaininformation/{}/change/".format(domain_info.pk),
|
||||||
|
@ -2048,6 +2125,44 @@ class TestDomainInformationAdmin(TestCase):
|
||||||
expected_url = "Testy Tester</a>"
|
expected_url = "Testy Tester</a>"
|
||||||
self.assertContains(response, expected_url)
|
self.assertContains(response, expected_url)
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
def test_analyst_cant_access_domain_information(self):
|
||||||
|
"""Ensures that analysts can't directly access the DomainInformation page through /admin"""
|
||||||
|
# Create fake creator
|
||||||
|
_creator = User.objects.create(
|
||||||
|
username="MrMeoward",
|
||||||
|
first_name="Meoward",
|
||||||
|
last_name="Jones",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a fake domain request
|
||||||
|
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW, user=_creator)
|
||||||
|
domain_request.approve()
|
||||||
|
domain_info = DomainInformation.objects.filter(domain=domain_request.approved_domain).get()
|
||||||
|
|
||||||
|
p = "userpass"
|
||||||
|
self.client.login(username="staffuser", password=p)
|
||||||
|
response = self.client.get(
|
||||||
|
"/admin/registrar/domaininformation/{}/change/".format(domain_info.pk),
|
||||||
|
follow=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure that we're denied access
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
|
# To make sure that its not a fluke, swap to an admin user
|
||||||
|
# and try to access the same page. This should succeed.
|
||||||
|
p = "adminpass"
|
||||||
|
self.client.login(username="superuser", password=p)
|
||||||
|
response = self.client.get(
|
||||||
|
"/admin/registrar/domaininformation/{}/change/".format(domain_info.pk),
|
||||||
|
follow=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure the page loaded, and that we're on the right page
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(response, domain_info.domain.name)
|
||||||
|
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_contact_fields_have_detail_table(self):
|
def test_contact_fields_have_detail_table(self):
|
||||||
"""Tests if the contact fields have the detail table which displays title, email, and phone"""
|
"""Tests if the contact fields have the detail table which displays title, email, and phone"""
|
||||||
|
@ -2071,8 +2186,8 @@ class TestDomainInformationAdmin(TestCase):
|
||||||
domain_request.approve()
|
domain_request.approve()
|
||||||
domain_info = DomainInformation.objects.filter(domain=domain_request.approved_domain).get()
|
domain_info = DomainInformation.objects.filter(domain=domain_request.approved_domain).get()
|
||||||
|
|
||||||
p = "userpass"
|
p = "adminpass"
|
||||||
self.client.login(username="staffuser", password=p)
|
self.client.login(username="superuser", password=p)
|
||||||
response = self.client.get(
|
response = self.client.get(
|
||||||
"/admin/registrar/domaininformation/{}/change/".format(domain_info.pk),
|
"/admin/registrar/domaininformation/{}/change/".format(domain_info.pk),
|
||||||
follow=True,
|
follow=True,
|
||||||
|
|
|
@ -34,7 +34,6 @@ class TestGroups(TestCase):
|
||||||
"view_logentry",
|
"view_logentry",
|
||||||
"change_contact",
|
"change_contact",
|
||||||
"view_domain",
|
"view_domain",
|
||||||
"change_domaininformation",
|
|
||||||
"add_domaininvitation",
|
"add_domaininvitation",
|
||||||
"view_domaininvitation",
|
"view_domaininvitation",
|
||||||
"change_domainrequest",
|
"change_domainrequest",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue