Merge pull request #1420 from cisagov/es/1378-availability-bugfix

#1378 Display error message when availability API fails
This commit is contained in:
Erin Song 2023-12-01 16:20:54 -08:00 committed by GitHub
commit c569db24f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 23 deletions

View file

@ -8,6 +8,7 @@ from django.test import RequestFactory
from ..views import available, check_domain_available
from .common import less_console_noise
from registrar.tests.common import MockEppLib
from registrar.utility.errors import GenericError, GenericErrorCodes
from unittest.mock import call
from epplibwrapper import (
@ -100,16 +101,25 @@ class AvailableViewTest(MockEppLib):
response = available(request, domain="igorville")
self.assertTrue(json.loads(response.content)["available"])
def test_error_handling(self):
"""Calling with bad strings raises an error."""
def test_bad_string_handling(self):
"""Calling with bad strings returns unavailable."""
bad_string = "blah!;"
request = self.factory.get(API_BASE_PATH + bad_string)
request.user = self.user
response = available(request, domain=bad_string)
self.assertFalse(json.loads(response.content)["available"])
# domain set to raise error returns false for availability
error_domain_available = available(request, "errordomain.gov")
self.assertFalse(json.loads(error_domain_available.content)["available"])
def test_error_handling(self):
"""Error thrown while calling availabilityAPI returns error."""
request = self.factory.get(API_BASE_PATH + "errordomain.gov")
request.user = self.user
# domain set to raise error returns false for availability and error message
error_domain_response = available(request, domain="errordomain.gov")
self.assertFalse(json.loads(error_domain_response.content)["available"])
self.assertEqual(
GenericError.get_error_message(GenericErrorCodes.CANNOT_CONTACT_REGISTRY),
json.loads(error_domain_response.content)["message"],
)
class AvailableAPITest(MockEppLib):

View file

@ -5,6 +5,7 @@ from django.http import JsonResponse
from django.utils.safestring import mark_safe
from registrar.templatetags.url_helpers import public_site_url
from registrar.utility.errors import GenericError, GenericErrorCodes
import requests
@ -30,7 +31,7 @@ DOMAIN_API_MESSAGES = {
),
"invalid": "Enter a domain using only letters, numbers, or hyphens (though we don't recommend using hyphens).",
"success": "That domain is available!",
"error": "Error finding domain availability.",
"error": GenericError.get_error_message(GenericErrorCodes.CANNOT_CONTACT_REGISTRY),
}
@ -63,17 +64,14 @@ def check_domain_available(domain):
The given domain is lowercased to match against the domains list. If the
given domain doesn't end with .gov, ".gov" is added when looking for
a match.
a match. If check fails, throws a RegistryError.
"""
Domain = apps.get_model("registrar.Domain")
try:
if domain.endswith(".gov"):
return Domain.available(domain)
else:
# domain search string doesn't end with .gov, add it on here
return Domain.available(domain + ".gov")
except Exception:
return False
if domain.endswith(".gov"):
return Domain.available(domain)
else:
# domain search string doesn't end with .gov, add it on here
return Domain.available(domain + ".gov")
@require_http_methods(["GET"])

View file

@ -399,6 +399,8 @@ class AlternativeDomainForm(RegistrarForm):
raise forms.ValidationError(DOMAIN_API_MESSAGES["extra_dots"], code="extra_dots")
except errors.DomainUnavailableError:
raise forms.ValidationError(DOMAIN_API_MESSAGES["unavailable"], code="unavailable")
except errors.RegistrySystemError:
raise forms.ValidationError(DOMAIN_API_MESSAGES["error"], code="error")
except ValueError:
raise forms.ValidationError(DOMAIN_API_MESSAGES["invalid"], code="invalid")
return validated
@ -484,6 +486,8 @@ class DotGovDomainForm(RegistrarForm):
raise forms.ValidationError(DOMAIN_API_MESSAGES["extra_dots"], code="extra_dots")
except errors.DomainUnavailableError:
raise forms.ValidationError(DOMAIN_API_MESSAGES["unavailable"], code="unavailable")
except errors.RegistrySystemError:
raise forms.ValidationError(DOMAIN_API_MESSAGES["error"], code="error")
except ValueError:
raise forms.ValidationError(DOMAIN_API_MESSAGES["invalid"], code="invalid")
return validated

View file

@ -2,6 +2,7 @@ import re
from api.views import check_domain_available
from registrar.utility import errors
from epplibwrapper.errors import RegistryError
class DomainHelper:
@ -29,19 +30,19 @@ class DomainHelper:
if not isinstance(domain, str):
raise ValueError("Domain name must be a string")
domain = domain.lower().strip()
if domain == "":
if blank_ok:
return domain
else:
raise errors.BlankValueError()
if domain == "" and not blank_ok:
raise errors.BlankValueError()
if domain.endswith(".gov"):
domain = domain[:-4]
if "." in domain:
raise errors.ExtraDotsError()
if not DomainHelper.string_could_be_domain(domain + ".gov"):
raise ValueError()
if not check_domain_available(domain):
raise errors.DomainUnavailableError()
try:
if not check_domain_available(domain):
raise errors.DomainUnavailableError()
except RegistryError as err:
raise errors.RegistrySystemError() from err
return domain
@classmethod

View file

@ -13,6 +13,10 @@ class DomainUnavailableError(ValueError):
pass
class RegistrySystemError(ValueError):
pass
class ActionNotAllowed(Exception):
"""User accessed an action that is not
allowed by the current state"""
@ -42,7 +46,7 @@ class GenericError(Exception):
GenericErrorCodes.CANNOT_CONTACT_REGISTRY: """
Were experiencing a system connection error. Please wait a few minutes
and try again. If you continue to receive this error after a few tries,
contact help@get.gov
contact help@get.gov.
""",
GenericErrorCodes.GENERIC_ERROR: ("Value entered was wrong."),
}
@ -56,6 +60,10 @@ contact help@get.gov
def __str__(self):
return f"{self.message}"
@classmethod
def get_error_message(self, code=None):
return self._error_mapping.get(code)
class NameserverErrorCodes(IntEnum):
"""Used in the NameserverError class for