From 569ec088f031d650a9244a4e27b6896f2c294078 Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Fri, 17 Jan 2025 10:47:54 -0800 Subject: [PATCH 01/18] Link and text changes --- src/registrar/templates/domain_renewal.html | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/registrar/templates/domain_renewal.html b/src/registrar/templates/domain_renewal.html index 32e535ed5..7c01f6718 100644 --- a/src/registrar/templates/domain_renewal.html +++ b/src/registrar/templates/domain_renewal.html @@ -38,11 +38,11 @@ {{ block.super }}

Confirm the following information for accuracy

-

Review these details below. We +

Review the details below. We require that you maintain accurate information for the domain. The details you provide will only be used to support the administration of .gov and won't be made public.

-

If you would like to retire your domain instead, please +

If you would like to retire your domain instead, please contact us.

Required fields are marked with an asterisk (*).

@@ -119,9 +119,8 @@ >
From cb462c1ab2fb8293f9f60ecf2542b0a41780a9f7 Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Fri, 17 Jan 2025 10:58:36 -0800 Subject: [PATCH 02/18] Fix tool tip text and adjust the banner for expiring soon --- src/registrar/models/domain.py | 2 +- src/registrar/templates/includes/domains_table.html | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index 6bd8278a1..d4c48f6bc 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -1586,7 +1586,7 @@ class Domain(TimeStampedModel, DomainHelper): "This domain has expired, but it is still online. " "To renew this domain, contact help@get.gov." ) elif flag_is_active(request, "domain_renewal") and self.is_expiring(): - help_text = "This domain will expire soon. Contact one of the listed domain managers to renew the domain." + help_text = "This domain will expire soon. Go to “Manage” to renew the domain." else: help_text = Domain.State.get_help_text(self.state) diff --git a/src/registrar/templates/includes/domains_table.html b/src/registrar/templates/includes/domains_table.html index f7e36d330..9b95e840a 100644 --- a/src/registrar/templates/includes/domains_table.html +++ b/src/registrar/templates/includes/domains_table.html @@ -10,9 +10,9 @@ {% if has_domain_renewal_flag and num_expiring_domains > 0 and has_any_domains_portfolio_permission %} -
+
-
+

{% if num_expiring_domains == 1%} One domain will expire soon. Go to "Manage" to renew the domain. Show expiring domain. @@ -76,9 +76,9 @@ {% if has_domain_renewal_flag and num_expiring_domains > 0 and not portfolio %} -

+
-
+

{% if num_expiring_domains == 1%} One domain will expire soon. Go to "Manage" to renew the domain. Show expiring domain. From 61450053639b8b3bd2805f5907f9d61018233737 Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Tue, 21 Jan 2025 13:37:51 -0800 Subject: [PATCH 03/18] Only if expired or expiring and domain manager can see /renewal otherwise 403 --- src/registrar/tests/test_views_domain.py | 1 - src/registrar/views/domain.py | 31 +++++++++++++++++++++++- src/registrar/views/utility/mixins.py | 3 ++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/registrar/tests/test_views_domain.py b/src/registrar/tests/test_views_domain.py index f13490312..2be9e21fa 100644 --- a/src/registrar/tests/test_views_domain.py +++ b/src/registrar/tests/test_views_domain.py @@ -583,7 +583,6 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): reverse("domain", kwargs={"pk": self.domaintorenew.id}), ) - print("puglesss", self.domaintorenew.is_expired) # Make sure we see the link as a domain manager self.assertContains(detail_page, "Renew to maintain access") diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index f82d7005d..d0dd62210 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -311,11 +311,40 @@ class DomainView(DomainBaseView): self._update_session_with_domain() -class DomainRenewalView(DomainView): +class DomainRenewalView(DomainBaseView): """Domain detail overview page.""" template_name = "domain_renewal.html" + def get_context_data(self, **kwargs): + """Grabbing security email information for the renewal form""" + + context = super().get_context_data(**kwargs) + + default_emails = [DefaultEmail.PUBLIC_CONTACT_DEFAULT.value, DefaultEmail.LEGACY_DEFAULT.value] + + context["hidden_security_emails"] = default_emails + + security_email = self.object.get_security_email() + if security_email is None or security_email in default_emails: + context["security_email"] = None + return context + context["security_email"] = security_email + return context + + def in_editable_state(self, pk): + """Override in_editable_state from DomainPermission + Allow renewal form to be accessed""" + + requested_domain = None + if Domain.objects.filter(id=pk).exists(): + requested_domain = Domain.objects.get(id=pk) + + if requested_domain and (requested_domain.is_expiring() or requested_domain.is_expired()): + return True + + return False + def post(self, request, pk): domain = get_object_or_404(Domain, id=pk) diff --git a/src/registrar/views/utility/mixins.py b/src/registrar/views/utility/mixins.py index 11384ca09..954f18b88 100644 --- a/src/registrar/views/utility/mixins.py +++ b/src/registrar/views/utility/mixins.py @@ -192,7 +192,8 @@ class DomainPermission(PermissionsLoginMixin): def can_access_domain_via_portfolio(self, pk): """Most views should not allow permission to portfolio users. If particular views allow access to the domain pages, they will need to override - this function.""" + this function. + """ return False def in_editable_state(self, pk): From 85503160f2d27bbdcb36795d0614bf2d263cc71e Mon Sep 17 00:00:00 2001 From: asaki222 Date: Wed, 22 Jan 2025 09:46:13 -0500 Subject: [PATCH 04/18] added test --- src/registrar/tests/test_views_domain.py | 25 ++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/registrar/tests/test_views_domain.py b/src/registrar/tests/test_views_domain.py index 2be9e21fa..cdc6995d2 100644 --- a/src/registrar/tests/test_views_domain.py +++ b/src/registrar/tests/test_views_domain.py @@ -443,6 +443,15 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): name="domainrenewal.gov", ) + self.domainnotexpiring, _ = Domain.objects.get_or_create( + name="domainnotexpiring.gov", + expiration_date=timezone.now().date() + timedelta(days=65) + ) + + self.domainnodomainmanager, _ = Domain.objects.get_or_create( + name="domainnodomainmanager" + ) + UserDomainRole.objects.get_or_create( user=self.user, domain=self.domaintorenew, role=UserDomainRole.Roles.MANAGER ) @@ -655,7 +664,23 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): edit_page = renewal_page.click(href=edit_button_url, index=1) self.assertEqual(edit_page.status_code, 200) self.assertContains(edit_page, "Domain managers can update all information related to a domain") + + @override_flag("domain_renewal", active=True) + def test_domain_renewal_form_not_expired_or_expiring(self): + with less_console_noise(): + # Start on the Renewal page for the domain + renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domainnotexpiring.id})) + self.assertEqual(renewal_page.status_code, 403) + @override_flag("domain_renewal", active=True) + def test_domain_renewal_form_does_not_appear_if_not_domain_manager(self): + with patch.object(Domain, "is_expired", self.custom_is_expired_true), patch.object( + Domain, "is_expired", self.custom_is_expired_true + ): + renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domainnodomainmanager.id})) + self.assertEqual(renewal_page.status_code, 403) + + @override_flag("domain_renewal", active=True) def test_ack_checkbox_not_checked(self): From d2323aa9ab900b9fa4e3d4455d244549017399de Mon Sep 17 00:00:00 2001 From: asaki222 Date: Wed, 22 Jan 2025 10:00:59 -0500 Subject: [PATCH 05/18] ran linter --- src/registrar/tests/test_views_domain.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/registrar/tests/test_views_domain.py b/src/registrar/tests/test_views_domain.py index cdc6995d2..58edea32d 100644 --- a/src/registrar/tests/test_views_domain.py +++ b/src/registrar/tests/test_views_domain.py @@ -444,13 +444,10 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): ) self.domainnotexpiring, _ = Domain.objects.get_or_create( - name="domainnotexpiring.gov", - expiration_date=timezone.now().date() + timedelta(days=65) + name="domainnotexpiring.gov", expiration_date=timezone.now().date() + timedelta(days=65) ) - self.domainnodomainmanager, _ = Domain.objects.get_or_create( - name="domainnodomainmanager" - ) + self.domainnodomainmanager, _ = Domain.objects.get_or_create(name="domainnodomainmanager") UserDomainRole.objects.get_or_create( user=self.user, domain=self.domaintorenew, role=UserDomainRole.Roles.MANAGER @@ -664,12 +661,12 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): edit_page = renewal_page.click(href=edit_button_url, index=1) self.assertEqual(edit_page.status_code, 200) self.assertContains(edit_page, "Domain managers can update all information related to a domain") - + @override_flag("domain_renewal", active=True) def test_domain_renewal_form_not_expired_or_expiring(self): with less_console_noise(): - # Start on the Renewal page for the domain - renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domainnotexpiring.id})) + # Start on the Renewal page for the domain + renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domainnotexpiring.id})) self.assertEqual(renewal_page.status_code, 403) @override_flag("domain_renewal", active=True) @@ -677,10 +674,9 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): with patch.object(Domain, "is_expired", self.custom_is_expired_true), patch.object( Domain, "is_expired", self.custom_is_expired_true ): - renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domainnodomainmanager.id})) + renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domainnodomainmanager.id})) self.assertEqual(renewal_page.status_code, 403) - @override_flag("domain_renewal", active=True) def test_ack_checkbox_not_checked(self): From 0bf017f6501281850f3b9de2212c55a2b60186f9 Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Wed, 22 Jan 2025 15:45:18 -0800 Subject: [PATCH 06/18] Fix link colour for renew and submit button text --- src/registrar/templates/domain_detail.html | 4 ++-- src/registrar/templates/domain_renewal.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/registrar/templates/domain_detail.html b/src/registrar/templates/domain_detail.html index 2cd3e5a5c..89685e074 100644 --- a/src/registrar/templates/domain_detail.html +++ b/src/registrar/templates/domain_detail.html @@ -52,11 +52,11 @@ {% if has_domain_renewal_flag and domain.is_expired and is_domain_manager %} This domain has expired, but it is still online. {% url 'domain-renewal' pk=domain.id as url %} - Renew to maintain access. + Renew to maintain access. {% elif has_domain_renewal_flag and domain.is_expiring and is_domain_manager %} This domain will expire soon. {% url 'domain-renewal' pk=domain.id as url %} - Renew to maintain access. + Renew to maintain access. {% elif has_domain_renewal_flag and domain.is_expiring and is_portfolio_user %} This domain will expire soon. Contact one of the listed domain managers to renew the domain. {% elif has_domain_renewal_flag and domain.is_expired and is_portfolio_user %} diff --git a/src/registrar/templates/domain_renewal.html b/src/registrar/templates/domain_renewal.html index 7c01f6718..fa833592c 100644 --- a/src/registrar/templates/domain_renewal.html +++ b/src/registrar/templates/domain_renewal.html @@ -130,7 +130,7 @@ name="submit_button" value="next" class="usa-button margin-top-3" - > Submit + > Submit and renew From d36ba58f77da7803b62e4d28ea8a5ac67f935b35 Mon Sep 17 00:00:00 2001 From: asaki222 Date: Mon, 27 Jan 2025 10:19:29 -0500 Subject: [PATCH 07/18] script thus far --- .../reset-db-without-sb-takedown.yaml | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 .github/workflows/reset-db-without-sb-takedown.yaml diff --git a/.github/workflows/reset-db-without-sb-takedown.yaml b/.github/workflows/reset-db-without-sb-takedown.yaml new file mode 100644 index 000000000..53e371cdb --- /dev/null +++ b/.github/workflows/reset-db-without-sb-takedown.yaml @@ -0,0 +1,88 @@ +# This workflow can be run from the CLI +# gh workflow run reset-db.yaml -f environment=ENVIRONMENT +# OR +# cf run-task getgov-ENVIRONMENT --command 'python manage.py flush' --name flush +# cf run-task getgov-ENVIRONMENT --command 'python manage.py load' --name loaddata + +name: Reset database +run-name: Reset database for ${{ github.event.inputs.environment }} without taking down the sandbox + +on: + workflow_dispatch: + inputs: + environment: + type: choice + description: Which environment should we flush and re-load data for? + options: + - staging + - development + - el + - ad + - ms + - ag + - litterbox + - hotgov + - cb + - bob + - meoward + - backup + - ky + - es + - nl + - rh + - za + - gd + - rb + - ko + - ab + - rjm + - dk + +jobs: + reset-db: + runs-on: ubuntu-latest + env: + CF_USERNAME: CF_${{ github.event.inputs.environment }}_USERNAME + CF_PASSWORD: CF_${{ github.event.inputs.environment }}_PASSWORD + steps: + - name: Unbind the database service + uses: cloud-gov/cg-cli-tools@main + with: + cf_username: ${{ secrets[env.CF_USERNAME] }} + cf_password: ${{ secrets[env.CF_PASSWORD] }} + cf_org: cisa-dotgov + cf_space: ${{ github.event.inputs.environment }} + cf_command: "cf unbind-service getgov-${{ github.event.inputs.environment }} getgov-${{ github.event.inputs.environment }}-database" + - name: Delete the service + uses: cloud-gov/cg-cli-tools@main + with: + cf_username: ${{ secrets[env.CF_USERNAME] }} + cf_password: ${{ secrets[env.CF_PASSWORD] }} + cf_org: cisa-dotgov + cf_space: ${{ github.event.inputs.environment }} + cf_command: "cf unbind-service getgov-${{ github.event.inputs.environment }} getgov-${{ github.event.inputs.environment }}-database" + -name: Recreate the service + uses: cloud-gov/cg-cli-tools@main + with: + cf_username: ${{ secrets[env.CF_USERNAME] }} + cf_password: ${{ secrets[env.CF_PASSWORD] }} + cf_org: cisa-dotgov + cf_space: ${{ github.event.inputs.environment }} + cf_command: "cf create-service aws-rds micro-psql getgov-${{ github.event.inputs.environment }} getgov-${{ github.event.inputs.environment }}-database" + -name: Recreate the service + uses: cloud-gov/cg-cli-tools@main + with: + cf_username: ${{ secrets[env.CF_USERNAME] }} + cf_password: ${{ secrets[env.CF_PASSWORD] }} + cf_org: cisa-dotgov + cf_space: ${{ github.event.inputs.environment }} + cf_command: "cf create-service aws-rds micro-psql getgov-${{ github.event.inputs.environment }} getgov-${{ github.event.inputs.environment }}-database" + -name: Rebind the service + uses: cloud-gov/cg-cli-tools@main + with: + cf_username: ${{ secrets[env.CF_USERNAME] }} + cf_password: ${{ secrets[env.CF_PASSWORD] }} + cf_org: cisa-dotgov + cf_space: ${{ github.event.inputs.environment }} + cf_command: "cf bind-service getgov-env getgov-${{ github.event.inputs.environment }}" + \ No newline at end of file From 78afb9524e7e5b306c16e84f16d0a469ed9041b1 Mon Sep 17 00:00:00 2001 From: asaki222 Date: Mon, 27 Jan 2025 10:40:13 -0500 Subject: [PATCH 08/18] removed the .gov, and converted variables to snake case --- src/registrar/tests/test_views_domain.py | 52 ++++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/registrar/tests/test_views_domain.py b/src/registrar/tests/test_views_domain.py index 58edea32d..76e2a5402 100644 --- a/src/registrar/tests/test_views_domain.py +++ b/src/registrar/tests/test_views_domain.py @@ -439,21 +439,21 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): username="usertest", ) - self.domaintorenew, _ = Domain.objects.get_or_create( + self.domain_to_renew, _ = Domain.objects.get_or_create( name="domainrenewal.gov", ) - self.domainnotexpiring, _ = Domain.objects.get_or_create( + self.domain_not_expiring, _ = Domain.objects.get_or_create( name="domainnotexpiring.gov", expiration_date=timezone.now().date() + timedelta(days=65) ) - self.domainnodomainmanager, _ = Domain.objects.get_or_create(name="domainnodomainmanager") + self.domain_no_domain_manager, _ = Domain.objects.get_or_create(name="domainnodomainmanager.gov") UserDomainRole.objects.get_or_create( - user=self.user, domain=self.domaintorenew, role=UserDomainRole.Roles.MANAGER + user=self.user, domain=self.domain_to_renew, role=UserDomainRole.Roles.MANAGER ) - DomainInformation.objects.get_or_create(creator=self.user, domain=self.domaintorenew) + DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_to_renew) self.portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org", creator=self.user) @@ -483,9 +483,9 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): with patch.object(Domain, "is_expiring", self.custom_is_expiring), patch.object( Domain, "is_expired", self.custom_is_expired_false ): - self.assertEquals(self.domaintorenew.state, Domain.State.UNKNOWN) + self.assertEquals(self.domain_to_renew.state, Domain.State.UNKNOWN) detail_page = self.client.get( - reverse("domain", kwargs={"pk": self.domaintorenew.id}), + reverse("domain", kwargs={"pk": self.domain_to_renew.id}), ) self.assertContains(detail_page, "Expiring soon") @@ -516,9 +516,9 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS, ], ) - domaintorenew2, _ = Domain.objects.get_or_create(name="bogusdomain2.gov") + domain_to_renew2, _ = Domain.objects.get_or_create(name="bogusdomain2.gov") DomainInformation.objects.get_or_create( - creator=non_dom_manage_user, domain=domaintorenew2, portfolio=self.portfolio + creator=non_dom_manage_user, domain=domain_to_renew2, portfolio=self.portfolio ) non_dom_manage_user.refresh_from_db() self.client.force_login(non_dom_manage_user) @@ -526,7 +526,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): Domain, "is_expired", self.custom_is_expired_false ): detail_page = self.client.get( - reverse("domain", kwargs={"pk": domaintorenew2.id}), + reverse("domain", kwargs={"pk": domain_to_renew2.id}), ) self.assertContains(detail_page, "Contact one of the listed domain managers to renew the domain.") @@ -535,17 +535,17 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): def test_expiring_domain_on_detail_page_in_org_model_as_a_domain_manager(self): portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org2", creator=self.user) - domaintorenew3, _ = Domain.objects.get_or_create(name="bogusdomain3.gov") + domain_to_renew3, _ = Domain.objects.get_or_create(name="bogusdomain3.gov") - UserDomainRole.objects.get_or_create(user=self.user, domain=domaintorenew3, role=UserDomainRole.Roles.MANAGER) - DomainInformation.objects.get_or_create(creator=self.user, domain=domaintorenew3, portfolio=portfolio) + UserDomainRole.objects.get_or_create(user=self.user, domain=domain_to_renew3, role=UserDomainRole.Roles.MANAGER) + DomainInformation.objects.get_or_create(creator=self.user, domain=domain_to_renew3, portfolio=portfolio) self.user.refresh_from_db() self.client.force_login(self.user) with patch.object(Domain, "is_expiring", self.custom_is_expiring), patch.object( Domain, "is_expired", self.custom_is_expired_false ): detail_page = self.client.get( - reverse("domain", kwargs={"pk": domaintorenew3.id}), + reverse("domain", kwargs={"pk": domain_to_renew3.id}), ) self.assertContains(detail_page, "Renew to maintain access") @@ -557,7 +557,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): ): # Grab the detail page detail_page = self.client.get( - reverse("domain", kwargs={"pk": self.domaintorenew.id}), + reverse("domain", kwargs={"pk": self.domain_to_renew.id}), ) # Make sure we see the link as a domain manager @@ -567,14 +567,14 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): self.assertContains(detail_page, "Renewal form") # Grab link to the renewal page - renewal_form_url = reverse("domain-renewal", kwargs={"pk": self.domaintorenew.id}) + renewal_form_url = reverse("domain-renewal", kwargs={"pk": self.domain_to_renew.id}) self.assertContains(detail_page, f'href="{renewal_form_url}"') # Simulate clicking the link response = self.client.get(renewal_form_url) self.assertEqual(response.status_code, 200) - self.assertContains(response, f"Renew {self.domaintorenew.name}") + self.assertContains(response, f"Renew {self.domain_to_renew.name}") @override_flag("domain_renewal", active=True) def test_domain_renewal_form_and_sidebar_expired(self): @@ -586,7 +586,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): ): # Grab the detail page detail_page = self.client.get( - reverse("domain", kwargs={"pk": self.domaintorenew.id}), + reverse("domain", kwargs={"pk": self.domain_to_renew.id}), ) # Make sure we see the link as a domain manager @@ -596,14 +596,14 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): self.assertContains(detail_page, "Renewal form") # Grab link to the renewal page - renewal_form_url = reverse("domain-renewal", kwargs={"pk": self.domaintorenew.id}) + renewal_form_url = reverse("domain-renewal", kwargs={"pk": self.domain_to_renew.id}) self.assertContains(detail_page, f'href="{renewal_form_url}"') # Simulate clicking the link response = self.client.get(renewal_form_url) self.assertEqual(response.status_code, 200) - self.assertContains(response, f"Renew {self.domaintorenew.name}") + self.assertContains(response, f"Renew {self.domain_to_renew.name}") @override_flag("domain_renewal", active=True) def test_domain_renewal_form_your_contact_info_edit(self): @@ -666,7 +666,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): def test_domain_renewal_form_not_expired_or_expiring(self): with less_console_noise(): # Start on the Renewal page for the domain - renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domainnotexpiring.id})) + renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domain_not_expiring.id})) self.assertEqual(renewal_page.status_code, 403) @override_flag("domain_renewal", active=True) @@ -674,7 +674,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): with patch.object(Domain, "is_expired", self.custom_is_expired_true), patch.object( Domain, "is_expired", self.custom_is_expired_true ): - renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domainnodomainmanager.id})) + renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domain_no_domain_manager.id})) self.assertEqual(renewal_page.status_code, 403) @override_flag("domain_renewal", active=True) @@ -2825,11 +2825,11 @@ class TestDomainRenewal(TestWithUser): name="igorville.gov", expiration_date=expiring_date ) self.domain_with_expired_date, _ = Domain.objects.get_or_create( - name="domainwithexpireddate.com", expiration_date=expired_date + name="domainwithexpireddate.gov", expiration_date=expired_date ) self.domain_with_current_date, _ = Domain.objects.get_or_create( - name="domainwithfarexpireddate.com", expiration_date=expiring_date_current + name="domainwithfarexpireddate.gov", expiration_date=expiring_date_current ) UserDomainRole.objects.get_or_create( @@ -2875,7 +2875,7 @@ class TestDomainRenewal(TestWithUser): today = datetime.now() expiring_date = (today + timedelta(days=30)).strftime("%Y-%m-%d") self.domain_with_another_expiring, _ = Domain.objects.get_or_create( - name="domainwithanotherexpiringdate.com", expiration_date=expiring_date + name="domainwithanotherexpiringdate.gov", expiration_date=expiring_date ) UserDomainRole.objects.get_or_create( @@ -2911,7 +2911,7 @@ class TestDomainRenewal(TestWithUser): today = datetime.now() expiring_date = (today + timedelta(days=31)).strftime("%Y-%m-%d") self.domain_with_another_expiring_org_model, _ = Domain.objects.get_or_create( - name="domainwithanotherexpiringdate_orgmodel.com", expiration_date=expiring_date + name="domainwithanotherexpiringdate_orgmodel.gov", expiration_date=expiring_date ) UserDomainRole.objects.get_or_create( From 3dab617ff1b869f96b142c5ce52ec290d4cc5c16 Mon Sep 17 00:00:00 2001 From: asaki222 Date: Mon, 27 Jan 2025 12:15:14 -0500 Subject: [PATCH 09/18] updated changes --- src/registrar/views/domain.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index d0dd62210..b9f6675ad 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -317,7 +317,8 @@ class DomainRenewalView(DomainBaseView): template_name = "domain_renewal.html" def get_context_data(self, **kwargs): - """Grabbing security email information for the renewal form""" + """Grabs the security email information and adds security_email to the renewal form context + sets it to None if it uses a default email""" context = super().get_context_data(**kwargs) @@ -334,16 +335,13 @@ class DomainRenewalView(DomainBaseView): def in_editable_state(self, pk): """Override in_editable_state from DomainPermission - Allow renewal form to be accessed""" - + Allow renewal form to be accessed + returns boolean""" requested_domain = None if Domain.objects.filter(id=pk).exists(): requested_domain = Domain.objects.get(id=pk) - if requested_domain and (requested_domain.is_expiring() or requested_domain.is_expired()): - return True - - return False + return requested_domain and requested_domain.is_editable() and (requested_domain.is_expiring() or requested_domain.is_expired()) def post(self, request, pk): From 33c4f6497f667a5411578a423a5be329769b8361 Mon Sep 17 00:00:00 2001 From: asaki222 Date: Mon, 27 Jan 2025 13:00:16 -0500 Subject: [PATCH 10/18] ran linter --- src/registrar/views/domain.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index b9f6675ad..2d7d88cd6 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -341,7 +341,11 @@ class DomainRenewalView(DomainBaseView): if Domain.objects.filter(id=pk).exists(): requested_domain = Domain.objects.get(id=pk) - return requested_domain and requested_domain.is_editable() and (requested_domain.is_expiring() or requested_domain.is_expired()) + return ( + requested_domain + and requested_domain.is_editable() + and (requested_domain.is_expiring() or requested_domain.is_expired()) + ) def post(self, request, pk): From 94c63215292d6a5a600254e557d12890062e96b7 Mon Sep 17 00:00:00 2001 From: asaki222 Date: Mon, 27 Jan 2025 13:29:34 -0500 Subject: [PATCH 11/18] delete yaml script --- .../reset-db-without-sb-takedown.yaml | 88 ------------------- 1 file changed, 88 deletions(-) delete mode 100644 .github/workflows/reset-db-without-sb-takedown.yaml diff --git a/.github/workflows/reset-db-without-sb-takedown.yaml b/.github/workflows/reset-db-without-sb-takedown.yaml deleted file mode 100644 index 53e371cdb..000000000 --- a/.github/workflows/reset-db-without-sb-takedown.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# This workflow can be run from the CLI -# gh workflow run reset-db.yaml -f environment=ENVIRONMENT -# OR -# cf run-task getgov-ENVIRONMENT --command 'python manage.py flush' --name flush -# cf run-task getgov-ENVIRONMENT --command 'python manage.py load' --name loaddata - -name: Reset database -run-name: Reset database for ${{ github.event.inputs.environment }} without taking down the sandbox - -on: - workflow_dispatch: - inputs: - environment: - type: choice - description: Which environment should we flush and re-load data for? - options: - - staging - - development - - el - - ad - - ms - - ag - - litterbox - - hotgov - - cb - - bob - - meoward - - backup - - ky - - es - - nl - - rh - - za - - gd - - rb - - ko - - ab - - rjm - - dk - -jobs: - reset-db: - runs-on: ubuntu-latest - env: - CF_USERNAME: CF_${{ github.event.inputs.environment }}_USERNAME - CF_PASSWORD: CF_${{ github.event.inputs.environment }}_PASSWORD - steps: - - name: Unbind the database service - uses: cloud-gov/cg-cli-tools@main - with: - cf_username: ${{ secrets[env.CF_USERNAME] }} - cf_password: ${{ secrets[env.CF_PASSWORD] }} - cf_org: cisa-dotgov - cf_space: ${{ github.event.inputs.environment }} - cf_command: "cf unbind-service getgov-${{ github.event.inputs.environment }} getgov-${{ github.event.inputs.environment }}-database" - - name: Delete the service - uses: cloud-gov/cg-cli-tools@main - with: - cf_username: ${{ secrets[env.CF_USERNAME] }} - cf_password: ${{ secrets[env.CF_PASSWORD] }} - cf_org: cisa-dotgov - cf_space: ${{ github.event.inputs.environment }} - cf_command: "cf unbind-service getgov-${{ github.event.inputs.environment }} getgov-${{ github.event.inputs.environment }}-database" - -name: Recreate the service - uses: cloud-gov/cg-cli-tools@main - with: - cf_username: ${{ secrets[env.CF_USERNAME] }} - cf_password: ${{ secrets[env.CF_PASSWORD] }} - cf_org: cisa-dotgov - cf_space: ${{ github.event.inputs.environment }} - cf_command: "cf create-service aws-rds micro-psql getgov-${{ github.event.inputs.environment }} getgov-${{ github.event.inputs.environment }}-database" - -name: Recreate the service - uses: cloud-gov/cg-cli-tools@main - with: - cf_username: ${{ secrets[env.CF_USERNAME] }} - cf_password: ${{ secrets[env.CF_PASSWORD] }} - cf_org: cisa-dotgov - cf_space: ${{ github.event.inputs.environment }} - cf_command: "cf create-service aws-rds micro-psql getgov-${{ github.event.inputs.environment }} getgov-${{ github.event.inputs.environment }}-database" - -name: Rebind the service - uses: cloud-gov/cg-cli-tools@main - with: - cf_username: ${{ secrets[env.CF_USERNAME] }} - cf_password: ${{ secrets[env.CF_PASSWORD] }} - cf_org: cisa-dotgov - cf_space: ${{ github.event.inputs.environment }} - cf_command: "cf bind-service getgov-env getgov-${{ github.event.inputs.environment }}" - \ No newline at end of file From 08616b3dd5a531a225742f89dda1b7a0417779c3 Mon Sep 17 00:00:00 2001 From: asaki222 Date: Tue, 28 Jan 2025 12:51:14 -0500 Subject: [PATCH 12/18] updated the num_of_domains --- src/registrar/models/user.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/registrar/models/user.py b/src/registrar/models/user.py index 2b5b56a78..1d508f88f 100644 --- a/src/registrar/models/user.py +++ b/src/registrar/models/user.py @@ -171,11 +171,14 @@ class User(AbstractUser): now = timezone.now().date() expiration_window = 60 threshold_date = now + timedelta(days=expiration_window) + acceptable_statuses = [Domain.State.UNKNOWN, Domain.State.DNS_NEEDED, Domain.State.READY] + num_of_expiring_domains = Domain.objects.filter( id__in=domain_ids, expiration_date__isnull=False, expiration_date__lte=threshold_date, expiration_date__gt=now, + state__in=acceptable_statuses, ).count() return num_of_expiring_domains From a3d454194425d9b92dabb30fbb9ea63c92a2178a Mon Sep 17 00:00:00 2001 From: asaki222 Date: Tue, 28 Jan 2025 13:51:46 -0500 Subject: [PATCH 13/18] pr changes --- src/registrar/views/domain.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 2d7d88cd6..aff32e825 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -327,9 +327,6 @@ class DomainRenewalView(DomainBaseView): context["hidden_security_emails"] = default_emails security_email = self.object.get_security_email() - if security_email is None or security_email in default_emails: - context["security_email"] = None - return context context["security_email"] = security_email return context From 218c1ba2e188b6ae2ffc5c03a4abb9274959871c Mon Sep 17 00:00:00 2001 From: Rebecca Hsieh Date: Tue, 28 Jan 2025 16:52:06 -0800 Subject: [PATCH 14/18] Accessibility fixes --- src/registrar/templates/domain_renewal.html | 2 +- src/registrar/templates/includes/domains_table.html | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/registrar/templates/domain_renewal.html b/src/registrar/templates/domain_renewal.html index 11e8615a4..6848bf32e 100644 --- a/src/registrar/templates/domain_renewal.html +++ b/src/registrar/templates/domain_renewal.html @@ -98,7 +98,7 @@ {% if form.is_policy_acknowledged.errors %} {% for error in form.is_policy_acknowledged.errors %}

diff --git a/src/registrar/tests/test_views_domain.py b/src/registrar/tests/test_views_domain.py index f2e3e1f5b..7d1e69783 100644 --- a/src/registrar/tests/test_views_domain.py +++ b/src/registrar/tests/test_views_domain.py @@ -479,6 +479,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_expiring_domain_on_detail_page_as_domain_manager(self): + """If a user is a domain manager and their domain is expiring soon, + user should be able to see the "Renew to maintain access" link domain overview detail box.""" self.client.force_login(self.user) with patch.object(Domain, "is_expiring", self.custom_is_expiring), patch.object( Domain, "is_expired", self.custom_is_expired_false @@ -497,6 +499,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) @override_flag("organization_feature", active=True) def test_expiring_domain_on_detail_page_in_org_model_as_a_non_domain_manager(self): + """In org model: If a user is NOT a domain manager and their domain is expiring soon, + user be notified to contact a domain manager in the domain overview detail box.""" portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org", creator=self.user) non_dom_manage_user = get_user_model().objects.create( first_name="Non Domain", @@ -533,6 +537,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) @override_flag("organization_feature", active=True) def test_expiring_domain_on_detail_page_in_org_model_as_a_domain_manager(self): + """Inorg model: If a user is a domain manager and their domain is expiring soon, + user should be able to see the "Renew to maintain access" link domain overview detail box.""" portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org2", creator=self.user) domain_to_renew3, _ = Domain.objects.get_or_create(name="bogusdomain3.gov") @@ -551,6 +557,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_domain_renewal_form_and_sidebar_expiring(self): + """If a user is a domain manager and their domain is expiring soon, + user should be able to see Renewal Form on the sidebar.""" self.client.force_login(self.user) with patch.object(Domain, "is_expiring", self.custom_is_expiring), patch.object( Domain, "is_expiring", self.custom_is_expiring @@ -578,7 +586,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_domain_renewal_form_and_sidebar_expired(self): - + """If a user is a domain manager and their domain is expired, + user should be able to see Renewal Form on the sidebar.""" self.client.force_login(self.user) with patch.object(Domain, "is_expired", self.custom_is_expired_true), patch.object( @@ -607,6 +616,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_domain_renewal_form_your_contact_info_edit(self): + """Checking that if a user is a domain manager they can edit the + Your Profile portion of the Renewal Form.""" with less_console_noise(): # Start on the Renewal page for the domain renewal_page = self.app.get(reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id})) @@ -625,6 +636,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_domain_renewal_form_security_email_edit(self): + """Checking that if a user is a domain manager they can edit the + Security Email portion of the Renewal Form.""" with less_console_noise(): # Start on the Renewal page for the domain renewal_page = self.app.get(reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id})) @@ -646,6 +659,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_domain_renewal_form_domain_manager_edit(self): + """Checking that if a user is a domain manager they can edit the + Domain Manager portion of the Renewal Form.""" with less_console_noise(): # Start on the Renewal page for the domain renewal_page = self.app.get(reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id})) @@ -664,6 +679,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_domain_renewal_form_not_expired_or_expiring(self): + """Checking that if the user's domain is not expired or expiring that user should not be able + to access /renewal and that it should receive a 403.""" with less_console_noise(): # Start on the Renewal page for the domain renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domain_not_expiring.id})) @@ -671,6 +688,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_domain_renewal_form_does_not_appear_if_not_domain_manager(self): + """If user is not a domain manager and tries to access /renewal, user should receive a 403.""" with patch.object(Domain, "is_expired", self.custom_is_expired_true), patch.object( Domain, "is_expired", self.custom_is_expired_true ): @@ -679,7 +697,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_ack_checkbox_not_checked(self): - + """If user don't check the checkbox, user should receive an error message.""" # Grab the renewal URL renewal_url = reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id}) @@ -691,7 +709,8 @@ class TestDomainDetailDomainRenewal(TestDomainOverview): @override_flag("domain_renewal", active=True) def test_ack_checkbox_checked(self): - + """If user check the checkbox and submits the form, + user should be redirected Domain Over page with an updated by 1 year expiration date""" # Grab the renewal URL with patch.object(Domain, "renew_domain", self.custom_renew_domain): renewal_url = reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id})