From d920c890df802ad94fc994888516b1bc033b3b7d Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Fri, 15 Mar 2024 12:29:07 -0700 Subject: [PATCH 01/20] Starting point for adding federal agency table --- src/registrar/models/federal_agency.py | 231 +++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 src/registrar/models/federal_agency.py diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py new file mode 100644 index 000000000..b6e72f58d --- /dev/null +++ b/src/registrar/models/federal_agency.py @@ -0,0 +1,231 @@ +from django.contrib.auth.models import Group +import logging + +logger = logging.getLogger(__name__) + + +# TODO: Update param model +class FederalAgency(Group): + class Meta: + verbose_name = "Federal agency" + verbose_name_plural = "Federal agencies" + + # TODO: Update parameters to put in + def create_federal_agencies(apps, schema_editor): + """This method gets run from a data migration.""" + + # Hard to pass self to these methods as the calls from migrations + # are only expecting apps and schema_editor, so we'll just define + # apps, schema_editor in the local scope instead + AGENCIES = [ + "Administrative Conference of the United States", + "Advisory Council on Historic Preservation", + "American Battle Monuments Commission", + "AMTRAK", + "Appalachian Regional Commission", + ("Appraisal Subcommittee of the Federal Financial " "Institutions Examination Council"), + "Architect of the Capitol", + "Armed Forces Retirement Home", + "Barry Goldwater Scholarship and Excellence in Education Foundation", + "Central Intelligence Agency", + "Christopher Columbus Fellowship Foundation", + "Civil Rights Cold Case Records Review Board", + "Commission for the Preservation of America's Heritage Abroad", + "Commission of Fine Arts", + "Committee for Purchase From People Who Are Blind or Severely Disabled", + "Commodity Futures Trading Commission", + "Congressional Budget Office", + "Consumer Financial Protection Bureau", + "Consumer Product Safety Commission", + "Corporation for National and Community Service", + "Council of Inspectors General on Integrity and Efficiency", + "Court Services and Offender Supervision", + "Cyberspace Solarium Commission", + "DC Court Services and Offender Supervision Agency", + "DC Pre-trial Services", + "Defense Nuclear Facilities Safety Board", + "Delta Regional Authority", + "Denali Commission", + "Department of Agriculture", + "Department of Commerce", + "Department of Defense", + "Department of Education", + "Department of Energy", + "Department of Health and Human Services", + "Department of Homeland Security", + "Department of Housing and Urban Development", + "Department of Justice", + "Department of Labor", + "Department of State", + "Department of the Interior", + "Department of the Treasury", + "Department of Transportation", + "Department of Veterans Affairs", + "Director of National Intelligence", + "Dwight D. Eisenhower Memorial Commission", + "Election Assistance Commission", + "Environmental Protection Agency", + "Equal Employment Opportunity Commission", + "Executive Office of the President", + "Export-Import Bank of the United States", + "Farm Credit Administration", + "Farm Credit System Insurance Corporation", + "Federal Communications Commission", + "Federal Deposit Insurance Corporation", + "Federal Election Commission", + "Federal Energy Regulatory Commission", + "Federal Financial Institutions Examination Council", + "Federal Housing Finance Agency", + "Federal Judiciary", + "Federal Labor Relations Authority", + "Federal Maritime Commission", + "Federal Mediation and Conciliation Service", + "Federal Mine Safety and Health Review Commission", + "Federal Permitting Improvement Steering Council", + "Federal Reserve Board of Governors", + "Federal Trade Commission", + "General Services Administration", + "gov Administration", + "Government Accountability Office", + "Government Publishing Office", + "Gulf Coast Ecosystem Restoration Council", + "Harry S. Truman Scholarship Foundation", + "Institute of Museum and Library Services", + "Institute of Peace", + "Inter-American Foundation", + "International Boundary and Water Commission: United States and Mexico", + "International Boundary Commission: United States and Canada", + "International Joint Commission: United States and Canada", + "James Madison Memorial Fellowship Foundation", + "Japan-U.S. Friendship Commission", + "John F. Kennedy Center for the Performing Arts", + "Legal Services Corporation", + "Legislative Branch", + "Library of Congress", + "Marine Mammal Commission", + "Medicaid and CHIP Payment and Access Commission", + "Medicare Payment Advisory Commission", + "Merit Systems Protection Board", + "Millennium Challenge Corporation", + "Morris K. Udall and Stewart L. Udall Foundation", + "National Aeronautics and Space Administration", + "National Archives and Records Administration", + "National Capital Planning Commission", + "National Council on Disability", + "National Credit Union Administration", + "National Endowment for the Arts", + "National Endowment for the Humanities", + "National Foundation on the Arts and the Humanities", + "National Gallery of Art", + "National Indian Gaming Commission", + "National Labor Relations Board", + "National Mediation Board", + "National Science Foundation", + "National Security Commission on Artificial Intelligence", + "National Transportation Safety Board", + "Networking Information Technology Research and Development", + "Non-Federal Agency", + "Northern Border Regional Commission", + "Nuclear Regulatory Commission", + "Nuclear Safety Oversight Committee", + "Occupational Safety and Health Review Commission", + "Office of Compliance", + "Office of Congressional Workplace Rights", + "Office of Government Ethics", + "Office of Navajo and Hopi Indian Relocation", + "Office of Personnel Management", + "Open World Leadership Center", + "Overseas Private Investment Corporation", + "Peace Corps", + "Pension Benefit Guaranty Corporation", + "Postal Regulatory Commission", + "Presidio Trust", + "Privacy and Civil Liberties Oversight Board", + "Public Buildings Reform Board", + "Public Defender Service for the District of Columbia", + "Railroad Retirement Board", + "Securities and Exchange Commission", + "Selective Service System", + "Small Business Administration", + "Smithsonian Institution", + "Social Security Administration", + "Social Security Advisory Board", + "Southeast Crescent Regional Commission", + "Southwest Border Regional Commission", + "State Justice Institute", + "Stennis Center for Public Service", + "Surface Transportation Board", + "Tennessee Valley Authority", + "The Executive Office of the President", + "The Intelligence Community", + "The Legislative Branch", + "The Supreme Court", + "The United States World War One Centennial Commission", + "U.S. Access Board", + "U.S. Agency for Global Media", + "U.S. Agency for International Development", + "U.S. Capitol Police", + "U.S. Chemical Safety Board", + "U.S. China Economic and Security Review Commission", + "U.S. Commission for the Preservation of Americas Heritage Abroad", + "U.S. Commission of Fine Arts", + "U.S. Commission on Civil Rights", + "U.S. Commission on International Religious Freedom", + "U.S. Courts", + "U.S. Department of Agriculture", + "U.S. Interagency Council on Homelessness", + "U.S. International Trade Commission", + "U.S. Nuclear Waste Technical Review Board", + "U.S. Office of Special Counsel", + "U.S. Postal Service", + "U.S. Semiquincentennial Commission", + "U.S. Trade and Development Agency", + "U.S.-China Economic and Security Review Commission", + "Udall Foundation", + "United States AbilityOne", + "United States Access Board", + "United States African Development Foundation", + "United States Agency for Global Media", + "United States Arctic Research Commission", + "United States Global Change Research Program", + "United States Holocaust Memorial Museum", + "United States Institute of Peace", + "United States Interagency Council on Homelessness", + "United States International Development Finance Corporation", + "United States International Trade Commission", + "United States Postal Service", + "United States Senate", + "United States Trade and Development Agency", + "Utah Reclamation Mitigation and Conservation Commission", + "Vietnam Education Foundation", + "Western Hemisphere Drug Policy Commission", + "Woodrow Wilson International Center for Scholars", + "World War I Centennial Commission", + ] + + # TODO: Get apps back here + FederalAgency = apps.get_model("registrar", "FederalAgency") + + try: + federal_agencies_list, _ = FederalAgency.objects.get_or_create( + name="cisa_analysts_group", + ) + + federal_agencies_list.federal_agency.clear() + + # TODO: Why is AGENCIES not loading here? + for agency in AGENCIES: + + # Assign the permissions to the group + federal_agencies_list.agency.add(*agency) + + # TODO: Maybe remove? + # Convert the permissions QuerySet to a list of codenames + agency_list = list(agency.values_list("codename", flat=True)) + + logger.debug(agency + " added to group " + federal_agencies_list.name) + + federal_agencies_list.save() + logger.debug("Federal agency added to table " + federal_agencies_list.name) + except Exception as e: + logger.error(f"Error creating fedearl agency: {e}") From 7b5beba813b40a6994cd671d0aaa7d69d10b70d2 Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Tue, 19 Mar 2024 10:36:14 -0700 Subject: [PATCH 02/20] Add initial federal agency model migration --- src/registrar/admin.py | 3 +- .../migrations/0077_federalagency.py | 26 +++++++++ src/registrar/models/__init__.py | 3 + src/registrar/models/federal_agency.py | 55 +++++++++---------- 4 files changed, 56 insertions(+), 31 deletions(-) create mode 100644 src/registrar/migrations/0077_federalagency.py diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 4968da527..82f010692 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -15,7 +15,7 @@ from django.contrib.contenttypes.models import ContentType from django.urls import reverse from dateutil.relativedelta import relativedelta # type: ignore from epplibwrapper.errors import ErrorCode, RegistryError -from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website +from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website, FederalAgency from registrar.utility import csv_export from registrar.utility.errors import FSMApplicationError, FSMErrorCodes from registrar.views.utility.mixins import OrderableFieldsMixin @@ -1839,6 +1839,7 @@ admin.site.register(models.DomainInvitation, DomainInvitationAdmin) admin.site.register(models.DomainInformation, DomainInformationAdmin) admin.site.register(models.Domain, DomainAdmin) admin.site.register(models.DraftDomain, DraftDomainAdmin) +admin.site.register(FederalAgency) # Host and HostIP removed from django admin because changes in admin # do not propagate to registry and logic not applied admin.site.register(models.Host, MyHostAdmin) diff --git a/src/registrar/migrations/0077_federalagency.py b/src/registrar/migrations/0077_federalagency.py new file mode 100644 index 000000000..3913fbde3 --- /dev/null +++ b/src/registrar/migrations/0077_federalagency.py @@ -0,0 +1,26 @@ +# Generated by Django 4.2.10 on 2024-03-19 05:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("registrar", "0076_alter_domainrequest_current_websites_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="FederalAgency", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("agency", models.CharField(blank=True, help_text="Federal agency", null=True)), + ], + options={ + "verbose_name": "Federal agency", + "verbose_name_plural": "Federal agencies", + }, + ), + ] diff --git a/src/registrar/models/__init__.py b/src/registrar/models/__init__.py index d203421ac..d3bbb3ae5 100644 --- a/src/registrar/models/__init__.py +++ b/src/registrar/models/__init__.py @@ -4,6 +4,7 @@ from .domain_request import DomainRequest from .domain_information import DomainInformation from .domain import Domain from .draft_domain import DraftDomain +from .federal_agency import FederalAgency from .host_ip import HostIP from .host import Host from .domain_invitation import DomainInvitation @@ -22,6 +23,7 @@ __all__ = [ "Domain", "DraftDomain", "DomainInvitation", + "FederalAgency", "HostIP", "Host", "UserDomainRole", @@ -39,6 +41,7 @@ auditlog.register(Domain) auditlog.register(DraftDomain) auditlog.register(DomainInvitation) auditlog.register(DomainInformation) +auditlog.register(FederalAgency) auditlog.register(HostIP) auditlog.register(Host) auditlog.register(UserDomainRole) diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py index b6e72f58d..544f00a9b 100644 --- a/src/registrar/models/federal_agency.py +++ b/src/registrar/models/federal_agency.py @@ -1,22 +1,30 @@ -from django.contrib.auth.models import Group +from .utility.time_stamped_model import TimeStampedModel +from django.db import models import logging logger = logging.getLogger(__name__) # TODO: Update param model -class FederalAgency(Group): +class FederalAgency(TimeStampedModel): class Meta: verbose_name = "Federal agency" verbose_name_plural = "Federal agencies" + + agency = models.CharField( + null=True, + blank=True, + help_text="Federal agency", + ) # TODO: Update parameters to put in def create_federal_agencies(apps, schema_editor): """This method gets run from a data migration.""" - + # Hard to pass self to these methods as the calls from migrations # are only expecting apps and schema_editor, so we'll just define # apps, schema_editor in the local scope instead + AGENCIES = [ "Administrative Conference of the United States", "Advisory Council on Historic Preservation", @@ -202,30 +210,17 @@ class FederalAgency(Group): "Woodrow Wilson International Center for Scholars", "World War I Centennial Commission", ] - - # TODO: Get apps back here - FederalAgency = apps.get_model("registrar", "FederalAgency") - - try: - federal_agencies_list, _ = FederalAgency.objects.get_or_create( - name="cisa_analysts_group", - ) - - federal_agencies_list.federal_agency.clear() - - # TODO: Why is AGENCIES not loading here? - for agency in AGENCIES: - - # Assign the permissions to the group - federal_agencies_list.agency.add(*agency) - - # TODO: Maybe remove? - # Convert the permissions QuerySet to a list of codenames - agency_list = list(agency.values_list("codename", flat=True)) - - logger.debug(agency + " added to group " + federal_agencies_list.name) - - federal_agencies_list.save() - logger.debug("Federal agency added to table " + federal_agencies_list.name) - except Exception as e: - logger.error(f"Error creating fedearl agency: {e}") + + FederalAgency = apps.get_model("registrar", "FederalAgency") + logger.info("Creating federal agency table.") + + try: + for agency in AGENCIES: + federal_agencies_list, _ = FederalAgency.objects.get_or_create( + agency=agency, + ) + logger.debug(agency + " added to record " + federal_agencies_list.agency) + federal_agencies_list.save() + logger.debug("Federal agency added to table " + federal_agencies_list.agency) + except Exception as e: + logger.error(f"Error creating federal agency: {e}") From d62e95fd10f8769a4a5546079ee4700c66a95df0 Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Tue, 19 Mar 2024 14:40:36 -0700 Subject: [PATCH 03/20] Populate fed agency seed data --- src/registrar/migrations/0077_federalagency.py | 12 ++++++++++++ src/registrar/models/federal_agency.py | 3 +++ 2 files changed, 15 insertions(+) diff --git a/src/registrar/migrations/0077_federalagency.py b/src/registrar/migrations/0077_federalagency.py index 3913fbde3..06c4e932d 100644 --- a/src/registrar/migrations/0077_federalagency.py +++ b/src/registrar/migrations/0077_federalagency.py @@ -1,7 +1,14 @@ # Generated by Django 4.2.10 on 2024-03-19 05:42 +# This migration seeds the federal agency table with initial data and manually calls +# FederalAgency.create_federal_agencies to populate initial table values. from django.db import migrations, models +from registrar.models import FederalAgency +from typing import Any +# For linting: RunPython expects a function reference. +def create_federal_agencies(apps, schema_editor) -> Any: + FederalAgency.create_federal_agencies(apps, schema_editor) class Migration(migrations.Migration): @@ -23,4 +30,9 @@ class Migration(migrations.Migration): "verbose_name_plural": "Federal agencies", }, ), + migrations.RunPython( + create_federal_agencies, + reverse_code=migrations.RunPython.noop, + atomic=True, + ), ] diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py index 544f00a9b..fc20a0c29 100644 --- a/src/registrar/models/federal_agency.py +++ b/src/registrar/models/federal_agency.py @@ -17,6 +17,9 @@ class FederalAgency(TimeStampedModel): help_text="Federal agency", ) + def __str__(self) -> str: + return self.agency + # TODO: Update parameters to put in def create_federal_agencies(apps, schema_editor): """This method gets run from a data migration.""" From 712bb26d03df5693277de892a1177bafe023959b Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Tue, 19 Mar 2024 14:48:25 -0700 Subject: [PATCH 04/20] Add search --- src/registrar/admin.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 82f010692..bfd432c85 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1825,6 +1825,11 @@ class VerifiedByStaffAdmin(ListHeaderAdmin): obj.requestor = request.user if request.user.is_authenticated else None super().save_model(request, obj, form, change) +class FederalAgencyAdmin(ListHeaderAdmin): + search_fields = ["agency"] + search_help_text = "Search by agency name." + ordering = ["agency"] + admin.site.unregister(LogEntry) # Unregister the default registration admin.site.register(LogEntry, CustomLogEntryAdmin) @@ -1839,7 +1844,7 @@ admin.site.register(models.DomainInvitation, DomainInvitationAdmin) admin.site.register(models.DomainInformation, DomainInformationAdmin) admin.site.register(models.Domain, DomainAdmin) admin.site.register(models.DraftDomain, DraftDomainAdmin) -admin.site.register(FederalAgency) +admin.site.register(models.FederalAgency, FederalAgencyAdmin) # Host and HostIP removed from django admin because changes in admin # do not propagate to registry and logic not applied admin.site.register(models.Host, MyHostAdmin) From 664b3eb895e1a4124f649ad35236ba5af6c9e584 Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Tue, 19 Mar 2024 14:51:48 -0700 Subject: [PATCH 05/20] Add sorting to federal agency table --- src/registrar/admin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index bfd432c85..43a416d0f 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1826,6 +1826,7 @@ class VerifiedByStaffAdmin(ListHeaderAdmin): super().save_model(request, obj, form, change) class FederalAgencyAdmin(ListHeaderAdmin): + list_display = ["agency"] search_fields = ["agency"] search_help_text = "Search by agency name." ordering = ["agency"] From 5a5faecb2a6c905e140b7b43f5ebb0f8997d8314 Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Tue, 19 Mar 2024 15:02:49 -0700 Subject: [PATCH 06/20] Update test_migrations with federal agency permissions --- src/registrar/models/user_group.py | 5 +++++ src/registrar/tests/test_migrations.py | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/registrar/models/user_group.py b/src/registrar/models/user_group.py index a84da798a..2aa2f642e 100644 --- a/src/registrar/models/user_group.py +++ b/src/registrar/models/user_group.py @@ -71,6 +71,11 @@ class UserGroup(Group): "model": "verifiedbystaff", "permissions": ["add_verifiedbystaff", "change_verifiedbystaff", "delete_verifiedbystaff"], }, + { + "app_label": "registrar", + "model": "federalagency", + "permissions": ["add_federalagency", "change_federalagency", "delete_federalagency"], + }, ] # Avoid error: You can't execute queries until the end diff --git a/src/registrar/tests/test_migrations.py b/src/registrar/tests/test_migrations.py index 50861d97f..bf3b09d0d 100644 --- a/src/registrar/tests/test_migrations.py +++ b/src/registrar/tests/test_migrations.py @@ -39,6 +39,9 @@ class TestGroups(TestCase): "view_domaininvitation", "change_domainrequest", "change_draftdomain", + "add_federalagency", + "change_federalagency", + "delete_federalagency", "analyst_access_permission", "change_user", "delete_userdomainrole", From 601ded68ac4f4497025a35ec456f68dc4ba31146 Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Tue, 19 Mar 2024 15:19:44 -0700 Subject: [PATCH 07/20] Fix lint errors --- src/registrar/admin.py | 4 ++-- src/registrar/migrations/0077_federalagency.py | 2 ++ src/registrar/models/federal_agency.py | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index ac1591584..9916027e6 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -15,8 +15,7 @@ from django.contrib.contenttypes.models import ContentType from django.urls import reverse from dateutil.relativedelta import relativedelta # type: ignore from epplibwrapper.errors import ErrorCode, RegistryError -from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website, FederalAgency -from registrar.utility import csv_export +from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website from registrar.utility.errors import FSMApplicationError, FSMErrorCodes from registrar.views.utility.mixins import OrderableFieldsMixin from django.contrib.admin.views.main import ORDER_VAR @@ -1789,6 +1788,7 @@ class VerifiedByStaffAdmin(ListHeaderAdmin): obj.requestor = request.user if request.user.is_authenticated else None super().save_model(request, obj, form, change) + class FederalAgencyAdmin(ListHeaderAdmin): list_display = ["agency"] search_fields = ["agency"] diff --git a/src/registrar/migrations/0077_federalagency.py b/src/registrar/migrations/0077_federalagency.py index 06c4e932d..0b3be0f70 100644 --- a/src/registrar/migrations/0077_federalagency.py +++ b/src/registrar/migrations/0077_federalagency.py @@ -6,10 +6,12 @@ from django.db import migrations, models from registrar.models import FederalAgency from typing import Any + # For linting: RunPython expects a function reference. def create_federal_agencies(apps, schema_editor) -> Any: FederalAgency.create_federal_agencies(apps, schema_editor) + class Migration(migrations.Migration): dependencies = [ diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py index fc20a0c29..5ccd69b50 100644 --- a/src/registrar/models/federal_agency.py +++ b/src/registrar/models/federal_agency.py @@ -10,7 +10,7 @@ class FederalAgency(TimeStampedModel): class Meta: verbose_name = "Federal agency" verbose_name_plural = "Federal agencies" - + agency = models.CharField( null=True, blank=True, @@ -18,12 +18,12 @@ class FederalAgency(TimeStampedModel): ) def __str__(self) -> str: - return self.agency + return f"{self.agency}" # TODO: Update parameters to put in def create_federal_agencies(apps, schema_editor): """This method gets run from a data migration.""" - + # Hard to pass self to these methods as the calls from migrations # are only expecting apps and schema_editor, so we'll just define # apps, schema_editor in the local scope instead @@ -213,10 +213,10 @@ class FederalAgency(TimeStampedModel): "Woodrow Wilson International Center for Scholars", "World War I Centennial Commission", ] - + FederalAgency = apps.get_model("registrar", "FederalAgency") logger.info("Creating federal agency table.") - + try: for agency in AGENCIES: federal_agencies_list, _ = FederalAgency.objects.get_or_create( From d0826fe8473601a6d01fa33c1405cc4e23b299d9 Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Tue, 19 Mar 2024 15:21:11 -0700 Subject: [PATCH 08/20] Update tests to reflect federal agency text occurrences --- src/registrar/tests/test_admin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index 9666633e9..af9d9aca3 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -284,7 +284,7 @@ class TestDomainAdmin(MockEppLib, WebTest): # There are 4 template references to Federal (4) plus four references in the table # for our actual domain_request - self.assertContains(response, "Federal", count=8) + self.assertContains(response, "Federal", count=36) # This may be a bit more robust self.assertContains(response, 'Federal', count=1) # Now let's make sure the long description does not exist @@ -690,7 +690,7 @@ class TestDomainRequestAdmin(MockEppLib): response = self.client.get("/admin/registrar/domainrequest/") # There are 4 template references to Federal (4) plus two references in the table # for our actual domain request - self.assertContains(response, "Federal", count=6) + self.assertContains(response, "Federal", count=34) # This may be a bit more robust self.assertContains(response, 'Federal', count=1) # Now let's make sure the long description does not exist From c4c1fd602c5e6909228fee30634c79b0c9949652 Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Tue, 19 Mar 2024 15:34:30 -0700 Subject: [PATCH 09/20] Remove todos --- src/registrar/models/federal_agency.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py index 5ccd69b50..c99843b31 100644 --- a/src/registrar/models/federal_agency.py +++ b/src/registrar/models/federal_agency.py @@ -5,7 +5,6 @@ import logging logger = logging.getLogger(__name__) -# TODO: Update param model class FederalAgency(TimeStampedModel): class Meta: verbose_name = "Federal agency" @@ -20,7 +19,6 @@ class FederalAgency(TimeStampedModel): def __str__(self) -> str: return f"{self.agency}" - # TODO: Update parameters to put in def create_federal_agencies(apps, schema_editor): """This method gets run from a data migration.""" From 62b405959aba0c4daafab4a5696ea6f844270bbe Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Wed, 20 Mar 2024 09:33:11 -0700 Subject: [PATCH 10/20] Add in permissions migration for federal agency --- .../migrations/0078_create_groups_v09.py | 37 +++++++++++++++++++ src/registrar/models/federal_agency.py | 2 + 2 files changed, 39 insertions(+) create mode 100644 src/registrar/migrations/0078_create_groups_v09.py diff --git a/src/registrar/migrations/0078_create_groups_v09.py b/src/registrar/migrations/0078_create_groups_v09.py new file mode 100644 index 000000000..6f89e0cb6 --- /dev/null +++ b/src/registrar/migrations/0078_create_groups_v09.py @@ -0,0 +1,37 @@ +# This migration creates the create_full_access_group and create_cisa_analyst_group groups +# It is dependent on 0035 (which populates ContentType and Permissions) +# 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", "0077_federalagency"), + ] + + operations = [ + migrations.RunPython( + create_groups, + reverse_code=migrations.RunPython.noop, + atomic=True, + ), + ] diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py index c99843b31..0a68beb57 100644 --- a/src/registrar/models/federal_agency.py +++ b/src/registrar/models/federal_agency.py @@ -213,6 +213,8 @@ class FederalAgency(TimeStampedModel): ] FederalAgency = apps.get_model("registrar", "FederalAgency") + ContentType = apps.get_model("contenttypes", "ContentType") + logger.info("Creating federal agency table.") try: From e55c0c72e77cd442c899380552bd7968261b405a Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Wed, 20 Mar 2024 09:37:10 -0700 Subject: [PATCH 11/20] Remove contenttype --- src/registrar/models/federal_agency.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py index 0a68beb57..f1f19e845 100644 --- a/src/registrar/models/federal_agency.py +++ b/src/registrar/models/federal_agency.py @@ -213,7 +213,6 @@ class FederalAgency(TimeStampedModel): ] FederalAgency = apps.get_model("registrar", "FederalAgency") - ContentType = apps.get_model("contenttypes", "ContentType") logger.info("Creating federal agency table.") From 14fb918719690d61e34680e52342a2aac97f6243 Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Thu, 21 Mar 2024 16:12:34 -0700 Subject: [PATCH 12/20] Update function description, and remove unecessary save and logger --- src/registrar/models/federal_agency.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py index f1f19e845..a65a5b148 100644 --- a/src/registrar/models/federal_agency.py +++ b/src/registrar/models/federal_agency.py @@ -20,7 +20,8 @@ class FederalAgency(TimeStampedModel): return f"{self.agency}" def create_federal_agencies(apps, schema_editor): - """This method gets run from a data migration.""" + """This method gets run from a data migration to prepopulate data + regarding federal agencies.""" # Hard to pass self to these methods as the calls from migrations # are only expecting apps and schema_editor, so we'll just define @@ -222,7 +223,5 @@ class FederalAgency(TimeStampedModel): agency=agency, ) logger.debug(agency + " added to record " + federal_agencies_list.agency) - federal_agencies_list.save() - logger.debug("Federal agency added to table " + federal_agencies_list.agency) except Exception as e: logger.error(f"Error creating federal agency: {e}") From be1f6558d0fb676187f267dd7e6c7318f8ad875a Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Thu, 21 Mar 2024 16:47:23 -0700 Subject: [PATCH 13/20] Remove our migrations to fix main --- .../migrations/0077_federalagency.py | 40 ------------------- .../migrations/0078_create_groups_v09.py | 37 ----------------- 2 files changed, 77 deletions(-) delete mode 100644 src/registrar/migrations/0077_federalagency.py delete mode 100644 src/registrar/migrations/0078_create_groups_v09.py diff --git a/src/registrar/migrations/0077_federalagency.py b/src/registrar/migrations/0077_federalagency.py deleted file mode 100644 index 0b3be0f70..000000000 --- a/src/registrar/migrations/0077_federalagency.py +++ /dev/null @@ -1,40 +0,0 @@ -# Generated by Django 4.2.10 on 2024-03-19 05:42 -# This migration seeds the federal agency table with initial data and manually calls -# FederalAgency.create_federal_agencies to populate initial table values. - -from django.db import migrations, models -from registrar.models import FederalAgency -from typing import Any - - -# For linting: RunPython expects a function reference. -def create_federal_agencies(apps, schema_editor) -> Any: - FederalAgency.create_federal_agencies(apps, schema_editor) - - -class Migration(migrations.Migration): - - dependencies = [ - ("registrar", "0076_alter_domainrequest_current_websites_and_more"), - ] - - operations = [ - migrations.CreateModel( - name="FederalAgency", - fields=[ - ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), - ("created_at", models.DateTimeField(auto_now_add=True)), - ("updated_at", models.DateTimeField(auto_now=True)), - ("agency", models.CharField(blank=True, help_text="Federal agency", null=True)), - ], - options={ - "verbose_name": "Federal agency", - "verbose_name_plural": "Federal agencies", - }, - ), - migrations.RunPython( - create_federal_agencies, - reverse_code=migrations.RunPython.noop, - atomic=True, - ), - ] diff --git a/src/registrar/migrations/0078_create_groups_v09.py b/src/registrar/migrations/0078_create_groups_v09.py deleted file mode 100644 index 6f89e0cb6..000000000 --- a/src/registrar/migrations/0078_create_groups_v09.py +++ /dev/null @@ -1,37 +0,0 @@ -# This migration creates the create_full_access_group and create_cisa_analyst_group groups -# It is dependent on 0035 (which populates ContentType and Permissions) -# 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", "0077_federalagency"), - ] - - operations = [ - migrations.RunPython( - create_groups, - reverse_code=migrations.RunPython.noop, - atomic=True, - ), - ] From 690cfafc99063f2d616792aa9fc70518220ff080 Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Thu, 21 Mar 2024 17:09:14 -0700 Subject: [PATCH 14/20] Update migrations to main --- .../migrations/0078_federalagency.py | 37 +++++++++++++++++++ .../migrations/0079_create_groups_v08.py | 37 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/registrar/migrations/0078_federalagency.py create mode 100644 src/registrar/migrations/0079_create_groups_v08.py diff --git a/src/registrar/migrations/0078_federalagency.py b/src/registrar/migrations/0078_federalagency.py new file mode 100644 index 000000000..37d2298ec --- /dev/null +++ b/src/registrar/migrations/0078_federalagency.py @@ -0,0 +1,37 @@ +# Generated by Django 4.2.10 on 2024-03-22 00:05 + +from django.db import migrations, models +from registrar.models import FederalAgency +from typing import Any + + +# For linting: RunPython expects a function reference. +def create_federal_agencies(apps, schema_editor) -> Any: + FederalAgency.create_federal_agencies(apps, schema_editor) + +class Migration(migrations.Migration): + + dependencies = [ + ("registrar", "0077_alter_publiccontact_fax_alter_publiccontact_org_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="FederalAgency", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("agency", models.CharField(blank=True, help_text="Federal agency", null=True)), + ], + options={ + "verbose_name": "Federal agency", + "verbose_name_plural": "Federal agencies", + }, + ), + migrations.RunPython( + create_federal_agencies, + reverse_code=migrations.RunPython.noop, + atomic=True, + ), + ] \ No newline at end of file diff --git a/src/registrar/migrations/0079_create_groups_v08.py b/src/registrar/migrations/0079_create_groups_v08.py new file mode 100644 index 000000000..307dda358 --- /dev/null +++ b/src/registrar/migrations/0079_create_groups_v08.py @@ -0,0 +1,37 @@ +# This migration creates the create_full_access_group and create_cisa_analyst_group groups +# It is dependent on 0035 (which populates ContentType and Permissions) +# 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", "0078_federalagency"), + ] + + operations = [ + migrations.RunPython( + create_groups, + reverse_code=migrations.RunPython.noop, + atomic=True, + ), + ] \ No newline at end of file From 969909895c6a03eefc1122eb4ff05e223f95f1c4 Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Thu, 21 Mar 2024 17:13:51 -0700 Subject: [PATCH 15/20] Linter --- src/registrar/migrations/0078_federalagency.py | 3 ++- .../{0079_create_groups_v08.py => 0079_create_groups_v09.py} | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) rename src/registrar/migrations/{0079_create_groups_v08.py => 0079_create_groups_v09.py} (99%) diff --git a/src/registrar/migrations/0078_federalagency.py b/src/registrar/migrations/0078_federalagency.py index 37d2298ec..14b1e9f1a 100644 --- a/src/registrar/migrations/0078_federalagency.py +++ b/src/registrar/migrations/0078_federalagency.py @@ -9,6 +9,7 @@ from typing import Any def create_federal_agencies(apps, schema_editor) -> Any: FederalAgency.create_federal_agencies(apps, schema_editor) + class Migration(migrations.Migration): dependencies = [ @@ -34,4 +35,4 @@ class Migration(migrations.Migration): reverse_code=migrations.RunPython.noop, atomic=True, ), - ] \ No newline at end of file + ] diff --git a/src/registrar/migrations/0079_create_groups_v08.py b/src/registrar/migrations/0079_create_groups_v09.py similarity index 99% rename from src/registrar/migrations/0079_create_groups_v08.py rename to src/registrar/migrations/0079_create_groups_v09.py index 307dda358..dd09a2a41 100644 --- a/src/registrar/migrations/0079_create_groups_v08.py +++ b/src/registrar/migrations/0079_create_groups_v09.py @@ -34,4 +34,4 @@ class Migration(migrations.Migration): reverse_code=migrations.RunPython.noop, atomic=True, ), - ] \ No newline at end of file + ] From b74dbcbcd4db1065fe987735824a3446f91850dd Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Fri, 22 Mar 2024 14:33:26 -0700 Subject: [PATCH 16/20] Add bulk_create to add federal agencies --- src/registrar/models/federal_agency.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py index a65a5b148..7bde05574 100644 --- a/src/registrar/models/federal_agency.py +++ b/src/registrar/models/federal_agency.py @@ -214,14 +214,10 @@ class FederalAgency(TimeStampedModel): ] FederalAgency = apps.get_model("registrar", "FederalAgency") - logger.info("Creating federal agency table.") try: - for agency in AGENCIES: - federal_agencies_list, _ = FederalAgency.objects.get_or_create( - agency=agency, - ) - logger.debug(agency + " added to record " + federal_agencies_list.agency) + agencies = [FederalAgency(agency=agency) for agency in AGENCIES] + FederalAgency.objects.bulk_create(agencies) except Exception as e: logger.error(f"Error creating federal agency: {e}") From 69bb18a6a620bd2ddd8114c501b21ddfac54140b Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Fri, 22 Mar 2024 15:23:14 -0700 Subject: [PATCH 17/20] Update migrations to most recent --- .../{0078_federalagency.py => 0079_federalagency.py} | 4 ++-- .../{0079_create_groups_v09.py => 0080_create_groups_v09.py} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/registrar/migrations/{0078_federalagency.py => 0079_federalagency.py} (88%) rename src/registrar/migrations/{0079_create_groups_v09.py => 0080_create_groups_v09.py} (91%) diff --git a/src/registrar/migrations/0078_federalagency.py b/src/registrar/migrations/0079_federalagency.py similarity index 88% rename from src/registrar/migrations/0078_federalagency.py rename to src/registrar/migrations/0079_federalagency.py index 14b1e9f1a..2f42e3382 100644 --- a/src/registrar/migrations/0078_federalagency.py +++ b/src/registrar/migrations/0079_federalagency.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.10 on 2024-03-22 00:05 +# Generated by Django 4.2.10 on 2024-03-22 22:18 from django.db import migrations, models from registrar.models import FederalAgency @@ -13,7 +13,7 @@ def create_federal_agencies(apps, schema_editor) -> Any: class Migration(migrations.Migration): dependencies = [ - ("registrar", "0077_alter_publiccontact_fax_alter_publiccontact_org_and_more"), + ("registrar", "0078_rename_organization_type_domaininformation_generic_org_type_and_more"), ] operations = [ diff --git a/src/registrar/migrations/0079_create_groups_v09.py b/src/registrar/migrations/0080_create_groups_v09.py similarity index 91% rename from src/registrar/migrations/0079_create_groups_v09.py rename to src/registrar/migrations/0080_create_groups_v09.py index dd09a2a41..e2e44ecc8 100644 --- a/src/registrar/migrations/0079_create_groups_v09.py +++ b/src/registrar/migrations/0080_create_groups_v09.py @@ -1,5 +1,5 @@ # This migration creates the create_full_access_group and create_cisa_analyst_group groups -# It is dependent on 0035 (which populates ContentType and Permissions) +# It is dependent on 0079 (which populates ContentType and Permissions) # If permissions on the groups need changing, edit CISA_ANALYST_GROUP_PERMISSIONS # in the user_group model then: # [NOT RECOMMENDED] @@ -25,7 +25,7 @@ def create_groups(apps, schema_editor) -> Any: class Migration(migrations.Migration): dependencies = [ - ("registrar", "0078_federalagency"), + ("registrar", "0079_federalagency"), ] operations = [ From 8b2beba87950e8ef5a13f57effcc3551732efe34 Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Mon, 25 Mar 2024 12:15:19 -0700 Subject: [PATCH 18/20] Update naming of migrations --- .../{0079_federalagency.py => 0079_federalagency_v01.py} | 0 src/registrar/migrations/0080_create_groups_v09.py | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/registrar/migrations/{0079_federalagency.py => 0079_federalagency_v01.py} (100%) diff --git a/src/registrar/migrations/0079_federalagency.py b/src/registrar/migrations/0079_federalagency_v01.py similarity index 100% rename from src/registrar/migrations/0079_federalagency.py rename to src/registrar/migrations/0079_federalagency_v01.py diff --git a/src/registrar/migrations/0080_create_groups_v09.py b/src/registrar/migrations/0080_create_groups_v09.py index e2e44ecc8..58ca4e813 100644 --- a/src/registrar/migrations/0080_create_groups_v09.py +++ b/src/registrar/migrations/0080_create_groups_v09.py @@ -1,5 +1,5 @@ # This migration creates the create_full_access_group and create_cisa_analyst_group groups -# It is dependent on 0079 (which populates ContentType and Permissions) +# 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] @@ -25,7 +25,7 @@ def create_groups(apps, schema_editor) -> Any: class Migration(migrations.Migration): dependencies = [ - ("registrar", "0079_federalagency"), + ("registrar", "0079_federalagency_v01"), ] operations = [ From 562ad3c20d55b32ff9589d6c1b1d96b0e18af94a Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Mon, 25 Mar 2024 12:23:12 -0700 Subject: [PATCH 19/20] Update migration file name with create --- ...federalagency_v01.py => 0079_create_federal_agencies_v01.py} | 0 src/registrar/migrations/0080_create_groups_v09.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/registrar/migrations/{0079_federalagency_v01.py => 0079_create_federal_agencies_v01.py} (100%) diff --git a/src/registrar/migrations/0079_federalagency_v01.py b/src/registrar/migrations/0079_create_federal_agencies_v01.py similarity index 100% rename from src/registrar/migrations/0079_federalagency_v01.py rename to src/registrar/migrations/0079_create_federal_agencies_v01.py diff --git a/src/registrar/migrations/0080_create_groups_v09.py b/src/registrar/migrations/0080_create_groups_v09.py index 58ca4e813..342404aa1 100644 --- a/src/registrar/migrations/0080_create_groups_v09.py +++ b/src/registrar/migrations/0080_create_groups_v09.py @@ -25,7 +25,7 @@ def create_groups(apps, schema_editor) -> Any: class Migration(migrations.Migration): dependencies = [ - ("registrar", "0079_federalagency_v01"), + ("registrar", "0079_create_federal_agencies_v01"), ] operations = [ From af81357d68dbd9bf8df369c7c32182640c3fd5ca Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:59:51 -0700 Subject: [PATCH 20/20] Fix content of error message --- src/registrar/models/federal_agency.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/models/federal_agency.py b/src/registrar/models/federal_agency.py index 7bde05574..89b15ab56 100644 --- a/src/registrar/models/federal_agency.py +++ b/src/registrar/models/federal_agency.py @@ -220,4 +220,4 @@ class FederalAgency(TimeStampedModel): agencies = [FederalAgency(agency=agency) for agency in AGENCIES] FederalAgency.objects.bulk_create(agencies) except Exception as e: - logger.error(f"Error creating federal agency: {e}") + logger.error(f"Error creating federal agencies: {e}")