Skip to content

Commit

Permalink
Merge pull request #1169 from cisagov/dk/1123-epp-cache
Browse files Browse the repository at this point in the history
Issue 1123: EPP cache not working
  • Loading branch information
dave-kennedy-ecs authored Oct 18, 2023
2 parents e80a328 + 12cbe3f commit 02b8f82
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 158 deletions.
3 changes: 3 additions & 0 deletions src/registrar/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,9 @@
# instruct browser to only send cookie via HTTPS
SESSION_COOKIE_SECURE = True

# session engine to cache session information
SESSION_ENGINE = "django.contrib.sessions.backends.cache"

# ~ Set by django.middleware.clickjacking.XFrameOptionsMiddleware
# prevent clickjacking by instructing the browser not to load
# our site within an iframe
Expand Down
110 changes: 59 additions & 51 deletions src/registrar/models/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ def _create_host(self, host, addrs):
"""Creates the host object in the registry
doesn't add the created host to the domain
returns ErrorCode (int)"""
logger.info("Creating host")
if addrs is not None:
addresses = [epp.Ip(addr=addr) for addr in addrs]
request = commands.CreateHost(name=host, addrs=addresses)
Expand Down Expand Up @@ -1245,7 +1244,6 @@ def _get_or_create_domain(self):
count = 0
while not exitEarly and count < 3:
try:
logger.info("Getting domain info from epp")
req = commands.InfoDomain(name=self.name)
domainInfoResponse = registry.send(req, cleaned=True)
exitEarly = True
Expand Down Expand Up @@ -1684,74 +1682,84 @@ def _fetch_cache(self, fetch_hosts=False, fetch_contacts=False):
"""Contact registry for info about a domain."""
try:
# get info from registry
dataResponse = self._get_or_create_domain()
data = dataResponse.res_data[0]
# extract properties from response
# (Ellipsis is used to mean "null")
cache = {
"auth_info": getattr(data, "auth_info", ...),
"_contacts": getattr(data, "contacts", ...),
"cr_date": getattr(data, "cr_date", ...),
"ex_date": getattr(data, "ex_date", ...),
"_hosts": getattr(data, "hosts", ...),
"name": getattr(data, "name", ...),
"registrant": getattr(data, "registrant", ...),
"statuses": getattr(data, "statuses", ...),
"tr_date": getattr(data, "tr_date", ...),
"up_date": getattr(data, "up_date", ...),
}
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 = {k: v for k, v in cache.items() if v is not ...}
cleaned = self._remove_null_properties(cache)

# statuses can just be a list no need to keep the epp object
if "statuses" in cleaned:
cleaned["statuses"] = [status.state for status in cleaned["statuses"]]

# get extensions info, if there is any
# DNSSECExtension is one possible extension, make sure to handle
# only DNSSECExtension and not other type extensions
returned_extensions = dataResponse.extensions
cleaned["dnssecdata"] = None
for extension in returned_extensions:
if isinstance(extension, extensions.DNSSECExtension):
cleaned["dnssecdata"] = extension
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")

# get contact info, if there are any
if (
fetch_contacts
and "_contacts" in cleaned
and isinstance(cleaned["_contacts"], list)
and len(cleaned["_contacts"]) > 0
):
cleaned["contacts"] = self._fetch_contacts(cleaned["_contacts"])
# We're only getting contacts, so retain the old
# hosts that existed in cache (if they existed)
# and pass them along.
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

# get nameserver info, if there are any
if (
fetch_hosts
and "_hosts" in cleaned
and isinstance(cleaned["_hosts"], list)
and len(cleaned["_hosts"])
):
cleaned["hosts"] = self._fetch_hosts(cleaned["_hosts"])
# We're only getting hosts, so retain the old
# contacts that existed in cache (if they existed)
# and pass them along.
if fetch_hosts:
cleaned["hosts"] = self._get_hosts(cleaned.get("_hosts", []))
if old_cache_contacts is not None:
cleaned["contacts"] = old_cache_contacts
# replace the prior cache with new data

self._cache = cleaned

except RegistryError as e:
logger.error(e)

def _extract_data_from_response(self, data_response):
data = data_response.res_data[0]
return {
"auth_info": getattr(data, "auth_info", ...),
"_contacts": getattr(data, "contacts", ...),
"cr_date": getattr(data, "cr_date", ...),
"ex_date": getattr(data, "ex_date", ...),
"_hosts": getattr(data, "hosts", ...),
"name": getattr(data, "name", ...),
"registrant": getattr(data, "registrant", ...),
"statuses": getattr(data, "statuses", ...),
"tr_date": getattr(data, "tr_date", ...),
"up_date": getattr(data, "up_date", ...),
}

def _remove_null_properties(self, cache):
return {k: v for k, v in cache.items() if v is not ...}

def _get_dnssec_data(self, response_extensions):
# get extensions info, if there is any
# DNSSECExtension is one possible extension, make sure to handle
# only DNSSECExtension and not other type extensions
dnssec_data = None
for extension in response_extensions:
if isinstance(extension, extensions.DNSSECExtension):
dnssec_data = extension
return dnssec_data

def _get_contacts(self, contacts):
choices = PublicContact.ContactTypeChoices
# We expect that all these fields get populated,
# so we can create these early, rather than waiting.
cleaned_contacts = {
choices.ADMINISTRATIVE: None,
choices.SECURITY: None,
choices.TECHNICAL: None,
}
if contacts and isinstance(contacts, list) and len(contacts) > 0:
cleaned_contacts = self._fetch_contacts(contacts)
return cleaned_contacts

def _get_hosts(self, hosts):
cleaned_hosts = []
if hosts and isinstance(hosts, list):
cleaned_hosts = self._fetch_hosts(hosts)
return cleaned_hosts

def _get_or_create_public_contact(self, public_contact: PublicContact):
"""Tries to find a PublicContact object in our DB.
If it can't, it'll create it. Returns PublicContact"""
Expand Down
Loading

0 comments on commit 02b8f82

Please sign in to comment.