From d84f7fbb0e8a88efa0b85930cc5e4daad07a8e4b Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Mon, 11 Dec 2023 17:26:00 -0500 Subject: [PATCH 01/12] wip --- src/registrar/templates/domain_detail.html | 6 +++++ .../templates/includes/domain_dates.html | 5 ++++ src/registrar/views/domain.py | 23 +++++++++++++------ 3 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 src/registrar/templates/includes/domain_dates.html diff --git a/src/registrar/templates/domain_detail.html b/src/registrar/templates/domain_detail.html index 81a350f82..7522d0892 100644 --- a/src/registrar/templates/domain_detail.html +++ b/src/registrar/templates/domain_detail.html @@ -27,6 +27,12 @@
+ +
+ Expires: {{ expiration_date }} + Date created: {{ creation_date }} +
+ {% url 'domain-dns-nameservers' pk=domain.id as url %} {% if domain.nameservers|length > 0 %} {% include "includes/summary_item.html" with title='DNS name servers' domains='true' value=domain.nameservers list='true' edit_link=url editable=domain.is_editable %} diff --git a/src/registrar/templates/includes/domain_dates.html b/src/registrar/templates/includes/domain_dates.html new file mode 100644 index 000000000..0949ea3f4 --- /dev/null +++ b/src/registrar/templates/includes/domain_dates.html @@ -0,0 +1,5 @@ + +
+ Expires: {{ expiration_date }} + Date created: {{ creation_date }} +
diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 81f1d0bb7..daf10bf90 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -142,14 +142,23 @@ class DomainView(DomainBaseView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - default_email = self.object.get_default_security_contact().email - context["default_security_email"] = default_email + try: + default_email = self.object.get_default_security_contact().email + context["default_security_email"] = default_email + + security_email = self.object.get_security_email() + if security_email is None or security_email == default_email: + context["security_email"] = None + return context + context["security_email"] = security_email + + context["expiration_date"] = self.object.registry_expiration_date + context["creation_date"] = self.object.creation_date + except: + log.warning(err) + context["expiration_date"] = datetime.strptime("2019-01-01", "%Y-%m-%d") + context["creation_date"] = datetime.strptime("2015-01-01", "%Y-%m-%d") - security_email = self.object.get_security_email() - if security_email is None or security_email == default_email: - context["security_email"] = None - return context - context["security_email"] = security_email return context def in_editable_state(self, pk): From c3b7bdb431e0ba9caf72e570d0a1b587e4a9c425 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 12 Dec 2023 08:22:34 -0500 Subject: [PATCH 02/12] expiration date and creation date added to template, no formatting --- src/registrar/templates/domain_detail.html | 6 +---- .../templates/includes/domain_dates.html | 11 ++++++--- src/registrar/views/domain.py | 23 ++++++------------- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/registrar/templates/domain_detail.html b/src/registrar/templates/domain_detail.html index 4e9eea70b..2aa4f3c19 100644 --- a/src/registrar/templates/domain_detail.html +++ b/src/registrar/templates/domain_detail.html @@ -27,11 +27,7 @@
- -
- Expires: {{ expiration_date }} - Date created: {{ creation_date }} -
+ {% include "includes/domain_dates.html" %} {% url 'domain-dns-nameservers' pk=domain.id as url %} {% if domain.nameservers|length > 0 %} diff --git a/src/registrar/templates/includes/domain_dates.html b/src/registrar/templates/includes/domain_dates.html index 0949ea3f4..3a4fbdfff 100644 --- a/src/registrar/templates/includes/domain_dates.html +++ b/src/registrar/templates/includes/domain_dates.html @@ -1,5 +1,10 @@ - +{% if domain.expiration_date or domain.created_at %}
- Expires: {{ expiration_date }} - Date created: {{ creation_date }} +{% if domain.expiration_date %}Expires: + {{ domain.expiration_date|date:"Y-m-d" }} + {% if domain.is_expired %} (expired){% endif %} +
+ {% endif %} + {% if domain.created_at %}Date created: {{ domain.created_at|date:"Y-m-d" }}{% endif %}
+{% endif %} diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 933094562..5ec4433f7 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -142,23 +142,14 @@ class DomainView(DomainBaseView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - try: - default_email = self.object.get_default_security_contact().email - context["default_security_email"] = default_email - - security_email = self.object.get_security_email() - if security_email is None or security_email == default_email: - context["security_email"] = None - return context - context["security_email"] = security_email - - context["expiration_date"] = self.object.registry_expiration_date - context["creation_date"] = self.object.creation_date - except: - log.warning(err) - context["expiration_date"] = datetime.strptime("2019-01-01", "%Y-%m-%d") - context["creation_date"] = datetime.strptime("2015-01-01", "%Y-%m-%d") + default_email = self.object.get_default_security_contact().email + context["default_security_email"] = default_email + security_email = self.object.get_security_email() + if security_email is None or security_email == default_email: + context["security_email"] = None + return context + context["security_email"] = security_email return context def in_editable_state(self, pk): From 48c7a792b5adc5eff3cab55f10eadfe5582badc9 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 12 Dec 2023 08:23:59 -0500 Subject: [PATCH 03/12] is_expired added to domain model --- src/registrar/models/domain.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index c92f540f1..6c94bd8d7 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -8,6 +8,7 @@ from typing import Optional from django_fsm import FSMField, transition, TransitionNotAllowed # type: ignore from django.db import models +from django.utils import timezone from typing import Any @@ -963,6 +964,16 @@ class Domain(TimeStampedModel, DomainHelper): def isActive(self): return self.state == Domain.State.CREATED + def is_expired(self): + """ + Check if the domain's expiration date is in the past. + Returns True if expired, False otherwise. + """ + if not self.expiration_date: + return True + now = timezone.now().date() + return self.expiration_date < now + def map_epp_contact_to_public_contact(self, contact: eppInfo.InfoContactResultData, contact_id, contact_type): """Maps the Epp contact representation to a PublicContact object. From 225a03dd48535c042658c9df08c52ed704d932b3 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 12 Dec 2023 11:56:08 -0500 Subject: [PATCH 04/12] defined unit tests for expiration date (is_expired) and creation date --- src/registrar/models/domain.py | 24 ++++++++++- src/registrar/tests/test_models_domain.py | 50 +++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index 6c94bd8d7..7feeb820d 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -201,6 +201,14 @@ class Domain(TimeStampedModel, DomainHelper): """Get the `cr_date` element from the registry.""" return self._get_property("cr_date") + @creation_date.setter # type: ignore + def creation_date(self, ex_date: date): + """ + Direct setting of the creation date in the registry is not implemented. + + Creation date can only be set by registry.""" + raise NotImplementedError() + @Cache def last_transferred_date(self) -> date: """Get the `tr_date` element from the registry.""" @@ -969,11 +977,11 @@ class Domain(TimeStampedModel, DomainHelper): Check if the domain's expiration date is in the past. Returns True if expired, False otherwise. """ - if not self.expiration_date: + if self.expiration_date is None: return True now = timezone.now().date() return self.expiration_date < now - + def map_epp_contact_to_public_contact(self, contact: eppInfo.InfoContactResultData, contact_id, contact_type): """Maps the Epp contact representation to a PublicContact object. @@ -1620,10 +1628,22 @@ class Domain(TimeStampedModel, DomainHelper): if old_cache_contacts is not None: cleaned["contacts"] = old_cache_contacts + requires_save = False + # if expiration date from registry does not match what is in db, # update the db if "ex_date" in cleaned and cleaned["ex_date"] != self.expiration_date: self.expiration_date = cleaned["ex_date"] + requires_save = True + + # if creation_date from registry does not match what is in db, + # update the db + if "cr_date" in cleaned and cleaned["cr_date"] != self.created_at: + self.created_at = cleaned["cr_date"] + requires_save = True + + # if either registration date or creation date need updating + if requires_save: self.save() self._cache = cleaned diff --git a/src/registrar/tests/test_models_domain.py b/src/registrar/tests/test_models_domain.py index 39f63c942..2f54d7794 100644 --- a/src/registrar/tests/test_models_domain.py +++ b/src/registrar/tests/test_models_domain.py @@ -1962,6 +1962,9 @@ class TestExpirationDate(MockEppLib): """ super().setUp() # for the tests, need a domain in the ready state + # mock data for self.domain includes the following dates: + # cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35) + # ex_date=datetime.date(2023, 5, 25) self.domain, _ = Domain.objects.get_or_create(name="fake.gov", state=Domain.State.READY) # for the test, need a domain that will raise an exception self.domain_w_error, _ = Domain.objects.get_or_create(name="fake-error.gov", state=Domain.State.READY) @@ -1987,6 +1990,23 @@ class TestExpirationDate(MockEppLib): with self.assertRaises(RegistryError): self.domain_w_error.renew_domain() + def test_is_expired(self): + """assert that is_expired returns true for expiration_date in past""" + # force fetch_cache to be called + self.domain.statuses + self.assertTrue(self.domain.is_expired) + + def test_is_not_expired(self): + """assert that is_expired returns false for expiration in future""" + # to do this, need to mock value returned from timezone.now + # set now to 2023-01-01 + mocked_datetime = datetime.datetime(2023, 1, 1, 12, 0, 0) + # force fetch_cache which sets the expiration date to 2023-05-25 + self.domain.statuses + + with patch("registrar.models.domain.timezone.now", return_value=mocked_datetime): + self.assertFalse(self.domain.is_expired()) + def test_expiration_date_updated_on_info_domain_call(self): """assert that expiration date in db is updated on info domain call""" # force fetch_cache to be called @@ -1995,6 +2015,36 @@ class TestExpirationDate(MockEppLib): self.assertEquals(self.domain.expiration_date, test_date) +class TestCreationDate(MockEppLib): + """Created_at in domain model is updated from EPP""" + + def setUp(self): + """ + Domain exists in registry + """ + super().setUp() + # for the tests, need a domain with a creation date + self.domain, _ = Domain.objects.get_or_create(name="fake.gov", state=Domain.State.READY) + # creation_date returned from mockDataInfoDomain with creation date: + # cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35) + self.creation_date = datetime.datetime(2023, 5, 25, 19, 45, 35) + + def tearDown(self): + Domain.objects.all().delete() + super().tearDown() + + def test_creation_date_setter_not_implemented(self): + """assert that the setter for creation date is not implemented and will raise error""" + with self.assertRaises(NotImplementedError): + self.domain.creation_date = datetime.date.today() + + def test_creation_date_updated_on_info_domain_call(self): + """assert that creation date in db is updated on info domain call""" + # force fetch_cache to be called + self.domain.statuses + self.assertEquals(self.domain.created_at, self.creation_date) + + class TestAnalystClientHold(MockEppLib): """Rule: Analysts may suspend or restore a domain by using client hold""" From eb61199d85f62bcaa56a0acdf6f63c774ebfcdb5 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 12 Dec 2023 16:03:04 -0500 Subject: [PATCH 05/12] formatting of expiration date and creation date in domain management --- src/registrar/templates/domain_detail.html | 2 +- .../templates/includes/domain_dates.html | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/registrar/templates/domain_detail.html b/src/registrar/templates/domain_detail.html index 2aa4f3c19..08eebfda1 100644 --- a/src/registrar/templates/domain_detail.html +++ b/src/registrar/templates/domain_detail.html @@ -34,7 +34,7 @@ {% include "includes/summary_item.html" with title='DNS name servers' domains='true' value=domain.nameservers list='true' edit_link=url editable=domain.is_editable %} {% else %} {% if domain.is_editable %} -

DNS name servers

+

DNS name servers

No DNS name servers have been added yet. Before your domain can be used we’ll need information about your domain name servers.

Add DNS name servers {% else %} diff --git a/src/registrar/templates/includes/domain_dates.html b/src/registrar/templates/includes/domain_dates.html index 3a4fbdfff..525de1fb9 100644 --- a/src/registrar/templates/includes/domain_dates.html +++ b/src/registrar/templates/includes/domain_dates.html @@ -1,10 +1,12 @@ {% if domain.expiration_date or domain.created_at %} -
-{% if domain.expiration_date %}Expires: - {{ domain.expiration_date|date:"Y-m-d" }} - {% if domain.is_expired %} (expired){% endif %} -
- {% endif %} - {% if domain.created_at %}Date created: {{ domain.created_at|date:"Y-m-d" }}{% endif %} -
+

+ {% if domain.expiration_date %} + Expires: + {{ domain.expiration_date|date }} + {% if domain.is_expired %} (expired){% endif %} +
+ {% endif %} + {% if domain.created_at %} + Date created: {{ domain.created_at|date }}{% endif %} +

{% endif %} From 2c28863a1c3ec88caa3f171fd820e82777af5da0 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 13 Dec 2023 10:14:46 -0500 Subject: [PATCH 06/12] submission date added to home page for domain requests --- .../0056_domainapplication_submission_date.py | 17 +++++++++++++++++ src/registrar/models/domain_application.py | 8 ++++++++ src/registrar/templates/home.html | 14 ++++++++++---- 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 src/registrar/migrations/0056_domainapplication_submission_date.py diff --git a/src/registrar/migrations/0056_domainapplication_submission_date.py b/src/registrar/migrations/0056_domainapplication_submission_date.py new file mode 100644 index 000000000..6cfdfbd4a --- /dev/null +++ b/src/registrar/migrations/0056_domainapplication_submission_date.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.7 on 2023-12-13 15:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("registrar", "0055_alter_domain_state_alter_domainapplication_status_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="domainapplication", + name="submission_date", + field=models.DateField(blank=True, default=None, help_text="Date submitted", null=True), + ), + ] diff --git a/src/registrar/models/domain_application.py b/src/registrar/models/domain_application.py index 12eda4caf..25d6dfe9e 100644 --- a/src/registrar/models/domain_application.py +++ b/src/registrar/models/domain_application.py @@ -547,6 +547,14 @@ class DomainApplication(TimeStampedModel): help_text="Acknowledged .gov acceptable use policy", ) + # submission date records when application is submitted + submission_date = models.DateField( + null=True, + blank=True, + default=None, + help_text="Date submitted", + ) + def __str__(self): try: if self.requested_domain and self.requested_domain.name: diff --git a/src/registrar/templates/home.html b/src/registrar/templates/home.html index 756ed4378..1c31acf47 100644 --- a/src/registrar/templates/home.html +++ b/src/registrar/templates/home.html @@ -39,7 +39,7 @@ Domain name - Date created + Expires Status Action @@ -50,7 +50,7 @@ {{ domain.name }} - {{ domain.created_time|date }} + {{ domain.expiration_date|date }} {% if domain.state == "unknown" or domain.state == "dns needed"%} DNS needed @@ -99,7 +99,7 @@ Domain name - Date created + Date submitted Status Action @@ -110,7 +110,13 @@ {{ application.requested_domain.name|default:"New domain request" }} - {{ application.created_at|date }} + + {% if application.submission_date %} + {{ application.submission_date|date }} + {% else %} + Not submitted + {% endif %} + {{ application.get_status_display }} {% if application.status == "started" or application.status == "action needed" or application.status == "withdrawn" %} From acc853da6848472440da63e407be68dccc425dfd Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 13 Dec 2023 16:14:44 -0500 Subject: [PATCH 07/12] submission_date set on application submit; refactored index.py; display of expired in both home page and domain detail page --- src/registrar/models/domain_application.py | 5 +++++ src/registrar/templates/domain_detail.html | 8 ++++++-- src/registrar/templates/home.html | 6 ++++-- src/registrar/views/index.py | 14 ++++++-------- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/registrar/models/domain_application.py b/src/registrar/models/domain_application.py index 25d6dfe9e..6dabd80ea 100644 --- a/src/registrar/models/domain_application.py +++ b/src/registrar/models/domain_application.py @@ -6,6 +6,7 @@ import logging from django.apps import apps from django.db import models from django_fsm import FSMField, transition # type: ignore +from django.utils import timezone from registrar.models.domain import Domain from .utility.time_stamped_model import TimeStampedModel @@ -615,6 +616,10 @@ class DomainApplication(TimeStampedModel): if not DraftDomain.string_could_be_domain(self.requested_domain.name): raise ValueError("Requested domain is not a valid domain name.") + # Update submission_date to today + self.submission_date = timezone.now().date() + self.save() + self._send_status_update_email( "submission confirmation", "emails/submission_confirmation.txt", diff --git a/src/registrar/templates/domain_detail.html b/src/registrar/templates/domain_detail.html index 08eebfda1..6a5542d89 100644 --- a/src/registrar/templates/domain_detail.html +++ b/src/registrar/templates/domain_detail.html @@ -5,8 +5,9 @@ {{ block.super }}
+
@@ -17,7 +18,9 @@ Status: - {% if domain.state == domain.State.UNKNOWN or domain.state == domain.State.DNS_NEEDED%} + {% if domain.is_expired %} + Expired + {% elif domain.state == domain.State.UNKNOWN or domain.state == domain.State.DNS_NEEDED%} DNS needed {% else %} {{ domain.state|title }} @@ -26,6 +29,7 @@

+ {% include "includes/domain_dates.html" %} diff --git a/src/registrar/templates/home.html b/src/registrar/templates/home.html index 1c31acf47..cedf611f3 100644 --- a/src/registrar/templates/home.html +++ b/src/registrar/templates/home.html @@ -52,7 +52,9 @@ {{ domain.expiration_date|date }} - {% if domain.state == "unknown" or domain.state == "dns needed"%} + {% if domain.is_expired %} + Expired + {% elif domain.state == "unknown" or domain.state == "dns needed"%} DNS needed {% else %} {{ domain.state|title }} @@ -114,7 +116,7 @@ {% if application.submission_date %} {{ application.submission_date|date }} {% else %} - Not submitted + Not submitted {% endif %} {{ application.get_status_display }} diff --git a/src/registrar/views/index.py b/src/registrar/views/index.py index b203694ff..ce5f8b07d 100644 --- a/src/registrar/views/index.py +++ b/src/registrar/views/index.py @@ -1,7 +1,8 @@ from django.db.models import F from django.shortcuts import render +from django.utils import timezone -from registrar.models import DomainApplication +from registrar.models import DomainApplication, Domain, UserDomainRole def index(request): @@ -14,12 +15,9 @@ def index(request): # the active applications table context["domain_applications"] = applications.exclude(status="approved") - domains = request.user.permissions.values( - "role", - pk=F("domain__id"), - name=F("domain__name"), - created_time=F("domain__created_at"), - state=F("domain__state"), - ) + user_domain_roles = UserDomainRole.objects.filter(user=request.user) + domain_ids = user_domain_roles.values_list('domain_id', flat=True) + domains = Domain.objects.filter(id__in=domain_ids) + context["domains"] = domains return render(request, "home.html", context) From 9a53e92f8bff9e88e5abdad9abcb986d2a7025ec Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 13 Dec 2023 16:41:46 -0500 Subject: [PATCH 08/12] some fixes to unit tests; accounting for submission date in django admin and on submission of application --- src/registrar/models/domain_information.py | 1 + src/registrar/tests/test_admin.py | 1 + src/registrar/tests/test_views.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/registrar/models/domain_information.py b/src/registrar/models/domain_information.py index 1d934f659..e6c323128 100644 --- a/src/registrar/models/domain_information.py +++ b/src/registrar/models/domain_information.py @@ -229,6 +229,7 @@ class DomainInformation(TimeStampedModel): da_dict.pop("alternative_domains", None) da_dict.pop("requested_domain", None) da_dict.pop("approved_domain", None) + da_dict.pop("submission_date", None) other_contacts = da_dict.pop("other_contacts", []) domain_info = cls(**da_dict) domain_info.domain_application = domain_application diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index 8a67fc191..9a1e87362 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -623,6 +623,7 @@ class TestDomainApplicationAdmin(MockEppLib): "no_other_contacts_rationale", "anything_else", "is_policy_acknowledged", + "submission_date", "current_websites", "other_contacts", "alternative_domains", diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py index 3c98c5fe7..a34f268ce 100644 --- a/src/registrar/tests/test_views.py +++ b/src/registrar/tests/test_views.py @@ -100,7 +100,7 @@ class LoggedInTests(TestWithUser): response = self.client.get("/") # count = 2 because it is also in screenreader content self.assertContains(response, "igorville.gov", count=2) - self.assertContains(response, "DNS needed") + self.assertContains(response, "Expired") # clean up role.delete() From 74e2f7117b16ba6034e2ca3a71c60bd9c6032ac9 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 13 Dec 2023 17:10:04 -0500 Subject: [PATCH 09/12] formatted code for linter; reformatted _fetch_cache for readability --- src/registrar/models/domain.py | 91 ++++++++++++++++++---------------- src/registrar/views/index.py | 4 +- 2 files changed, 50 insertions(+), 45 deletions(-) diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index 7feeb820d..b0b7306b5 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -1601,50 +1601,11 @@ class Domain(TimeStampedModel, DomainHelper): def _fetch_cache(self, fetch_hosts=False, fetch_contacts=False): """Contact registry for info about a domain.""" try: - # get info from registry data_response = self._get_or_create_domain() cache = self._extract_data_from_response(data_response) - - # remove null properties (to distinguish between "a value of None" and null) - cleaned = self._remove_null_properties(cache) - - if "statuses" in cleaned: - cleaned["statuses"] = [status.state for status in cleaned["statuses"]] - - cleaned["dnssecdata"] = self._get_dnssec_data(data_response.extensions) - - # Capture and store old hosts and contacts from cache if they exist - old_cache_hosts = self._cache.get("hosts") - old_cache_contacts = self._cache.get("contacts") - - if fetch_contacts: - cleaned["contacts"] = self._get_contacts(cleaned.get("_contacts", [])) - if old_cache_hosts is not None: - logger.debug("resetting cleaned['hosts'] to old_cache_hosts") - cleaned["hosts"] = old_cache_hosts - - if fetch_hosts: - cleaned["hosts"] = self._get_hosts(cleaned.get("_hosts", [])) - if old_cache_contacts is not None: - cleaned["contacts"] = old_cache_contacts - - requires_save = False - - # if expiration date from registry does not match what is in db, - # update the db - if "ex_date" in cleaned and cleaned["ex_date"] != self.expiration_date: - self.expiration_date = cleaned["ex_date"] - requires_save = True - - # if creation_date from registry does not match what is in db, - # update the db - if "cr_date" in cleaned and cleaned["cr_date"] != self.created_at: - self.created_at = cleaned["cr_date"] - requires_save = True - - # if either registration date or creation date need updating - if requires_save: - self.save() + cleaned = self._clean_cache(cache, data_response) + self._update_hosts_and_contacts(cleaned, fetch_hosts, fetch_contacts) + self._update_dates(cleaned) self._cache = cleaned @@ -1652,6 +1613,7 @@ class Domain(TimeStampedModel, DomainHelper): logger.error(e) def _extract_data_from_response(self, data_response): + """extract datea from response from registry""" data = data_response.res_data[0] return { "auth_info": getattr(data, "auth_info", ...), @@ -1666,6 +1628,15 @@ class Domain(TimeStampedModel, DomainHelper): "up_date": getattr(data, "up_date", ...), } + def _clean_cache(self, cache, data_response): + """clean up the cache""" + # remove null properties (to distinguish between "a value of None" and null) + cleaned = self._remove_null_properties(cache) + if "statuses" in cleaned: + cleaned["statuses"] = [status.state for status in cleaned["statuses"]] + cleaned["dnssecdata"] = self._get_dnssec_data(data_response.extensions) + return cleaned + def _remove_null_properties(self, cache): return {k: v for k, v in cache.items() if v is not ...} @@ -1679,6 +1650,42 @@ class Domain(TimeStampedModel, DomainHelper): dnssec_data = extension return dnssec_data + def _update_hosts_and_contacts(self, cleaned, fetch_hosts, fetch_contacts): + """Capture and store old hosts and contacts from cache if the don't exist""" + old_cache_hosts = self._cache.get("hosts") + old_cache_contacts = self._cache.get("contacts") + + if fetch_contacts: + cleaned["contacts"] = self._get_contacts(cleaned.get("_contacts", [])) + if old_cache_hosts is not None: + logger.debug("resetting cleaned['hosts'] to old_cache_hosts") + cleaned["hosts"] = old_cache_hosts + + if fetch_hosts: + cleaned["hosts"] = self._get_hosts(cleaned.get("_hosts", [])) + if old_cache_contacts is not None: + cleaned["contacts"] = old_cache_contacts + + def _update_dates(self, cleaned): + """Update dates (expiration and creation) from cleaned""" + requires_save = False + + # if expiration date from registry does not match what is in db, + # update the db + if "ex_date" in cleaned and cleaned["ex_date"] != self.expiration_date: + self.expiration_date = cleaned["ex_date"] + requires_save = True + + # if creation_date from registry does not match what is in db, + # update the db + if "cr_date" in cleaned and cleaned["cr_date"] != self.created_at: + self.created_at = cleaned["cr_date"] + requires_save = True + + # if either registration date or creation date need updating + if requires_save: + self.save() + def _get_contacts(self, contacts): choices = PublicContact.ContactTypeChoices # We expect that all these fields get populated, diff --git a/src/registrar/views/index.py b/src/registrar/views/index.py index ce5f8b07d..9605c723d 100644 --- a/src/registrar/views/index.py +++ b/src/registrar/views/index.py @@ -1,6 +1,4 @@ -from django.db.models import F from django.shortcuts import render -from django.utils import timezone from registrar.models import DomainApplication, Domain, UserDomainRole @@ -16,7 +14,7 @@ def index(request): context["domain_applications"] = applications.exclude(status="approved") user_domain_roles = UserDomainRole.objects.filter(user=request.user) - domain_ids = user_domain_roles.values_list('domain_id', flat=True) + domain_ids = user_domain_roles.values_list("domain_id", flat=True) domains = Domain.objects.filter(id__in=domain_ids) context["domains"] = domains From 0dbe1c4757b323947631bb023c0fab3d8841a92c Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 14 Dec 2023 04:30:38 -0500 Subject: [PATCH 10/12] merged and fixed migrations --- ...ission_date.py => 0057_domainapplication_submission_date.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/registrar/migrations/{0056_domainapplication_submission_date.py => 0057_domainapplication_submission_date.py} (87%) diff --git a/src/registrar/migrations/0056_domainapplication_submission_date.py b/src/registrar/migrations/0057_domainapplication_submission_date.py similarity index 87% rename from src/registrar/migrations/0056_domainapplication_submission_date.py rename to src/registrar/migrations/0057_domainapplication_submission_date.py index 6cfdfbd4a..a2a170888 100644 --- a/src/registrar/migrations/0056_domainapplication_submission_date.py +++ b/src/registrar/migrations/0057_domainapplication_submission_date.py @@ -5,7 +5,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ("registrar", "0055_alter_domain_state_alter_domainapplication_status_and_more"), + ("registrar", "0056_alter_domain_state_alter_domainapplication_status_and_more"), ] operations = [ From 2fc3d4f1c80f905fb6539d01801d8fc206206003 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 14 Dec 2023 04:46:37 -0500 Subject: [PATCH 11/12] clean up typos --- src/registrar/models/domain.py | 2 +- src/registrar/templates/domain_detail.html | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index b0b7306b5..c31a090b7 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -1613,7 +1613,7 @@ class Domain(TimeStampedModel, DomainHelper): logger.error(e) def _extract_data_from_response(self, data_response): - """extract datea from response from registry""" + """extract data from response from registry""" data = data_response.res_data[0] return { "auth_info": getattr(data, "auth_info", ...), diff --git a/src/registrar/templates/domain_detail.html b/src/registrar/templates/domain_detail.html index 6a5542d89..6d67925bc 100644 --- a/src/registrar/templates/domain_detail.html +++ b/src/registrar/templates/domain_detail.html @@ -5,7 +5,6 @@ {{ block.super }}
-
Date: Thu, 14 Dec 2023 15:29:34 -0500 Subject: [PATCH 12/12] style change to display of expired text --- src/registrar/templates/includes/domain_dates.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/templates/includes/domain_dates.html b/src/registrar/templates/includes/domain_dates.html index 525de1fb9..c05e202e1 100644 --- a/src/registrar/templates/includes/domain_dates.html +++ b/src/registrar/templates/includes/domain_dates.html @@ -3,7 +3,7 @@ {% if domain.expiration_date %} Expires: {{ domain.expiration_date|date }} - {% if domain.is_expired %} (expired){% endif %} + {% if domain.is_expired %} (expired){% endif %}
{% endif %} {% if domain.created_at %}