mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-15 09:07:02 +02:00
updated linter length; linter reformatted several files
This commit is contained in:
parent
f0636013e0
commit
c760417e6a
65 changed files with 550 additions and 1727 deletions
|
@ -1,5 +1,5 @@
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 120
|
||||||
max-complexity = 10
|
max-complexity = 10
|
||||||
extend-ignore = E203
|
extend-ignore = E203
|
||||||
per-file-ignores = __init__.py:F401,F403,E402
|
per-file-ignores = __init__.py:F401,F403,E402
|
||||||
|
|
|
@ -10,9 +10,7 @@ from login_required import login_not_required
|
||||||
from cachetools.func import ttl_cache
|
from cachetools.func import ttl_cache
|
||||||
|
|
||||||
|
|
||||||
DOMAIN_FILE_URL = (
|
DOMAIN_FILE_URL = "https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv"
|
||||||
"https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
DOMAIN_API_MESSAGES = {
|
DOMAIN_API_MESSAGES = {
|
||||||
|
@ -22,8 +20,7 @@ DOMAIN_API_MESSAGES = {
|
||||||
"extra_dots": "Enter the .gov domain you want without any periods.",
|
"extra_dots": "Enter the .gov domain you want without any periods.",
|
||||||
"unavailable": "That domain isn’t available. Try entering another one."
|
"unavailable": "That domain isn’t available. Try entering another one."
|
||||||
" Contact us if you need help coming up with a domain.",
|
" Contact us if you need help coming up with a domain.",
|
||||||
"invalid": "Enter a domain using only letters,"
|
"invalid": "Enter a domain using only letters, numbers, or hyphens (though we don't recommend using hyphens).",
|
||||||
" numbers, or hyphens (though we don't recommend using hyphens).",
|
|
||||||
"success": "That domain is available!",
|
"success": "That domain is available!",
|
||||||
"error": "Error finding domain availability.",
|
"error": "Error finding domain availability.",
|
||||||
}
|
}
|
||||||
|
@ -82,24 +79,13 @@ def available(request, domain=""):
|
||||||
DraftDomain = apps.get_model("registrar.DraftDomain")
|
DraftDomain = apps.get_model("registrar.DraftDomain")
|
||||||
# validate that the given domain could be a domain name and fail early if
|
# validate that the given domain could be a domain name and fail early if
|
||||||
# not.
|
# not.
|
||||||
if not (
|
if not (DraftDomain.string_could_be_domain(domain) or DraftDomain.string_could_be_domain(domain + ".gov")):
|
||||||
DraftDomain.string_could_be_domain(domain)
|
return JsonResponse({"available": False, "message": DOMAIN_API_MESSAGES["invalid"]})
|
||||||
or DraftDomain.string_could_be_domain(domain + ".gov")
|
|
||||||
):
|
|
||||||
return JsonResponse(
|
|
||||||
{"available": False, "message": DOMAIN_API_MESSAGES["invalid"]}
|
|
||||||
)
|
|
||||||
# a domain is available if it is NOT in the list of current domains
|
# a domain is available if it is NOT in the list of current domains
|
||||||
try:
|
try:
|
||||||
if check_domain_available(domain):
|
if check_domain_available(domain):
|
||||||
return JsonResponse(
|
return JsonResponse({"available": True, "message": DOMAIN_API_MESSAGES["success"]})
|
||||||
{"available": True, "message": DOMAIN_API_MESSAGES["success"]}
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return JsonResponse(
|
return JsonResponse({"available": False, "message": DOMAIN_API_MESSAGES["unavailable"]})
|
||||||
{"available": False, "message": DOMAIN_API_MESSAGES["unavailable"]}
|
|
||||||
)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return JsonResponse(
|
return JsonResponse({"available": False, "message": DOMAIN_API_MESSAGES["error"]})
|
||||||
{"available": False, "message": DOMAIN_API_MESSAGES["error"]}
|
|
||||||
)
|
|
||||||
|
|
|
@ -72,9 +72,7 @@ class Client(oic.Client):
|
||||||
try:
|
try:
|
||||||
# discover and store the provider (OP) urls, etc
|
# discover and store the provider (OP) urls, etc
|
||||||
self.provider_config(provider["srv_discovery_url"])
|
self.provider_config(provider["srv_discovery_url"])
|
||||||
self.store_registration_info(
|
self.store_registration_info(RegistrationResponse(**provider["client_registration"]))
|
||||||
RegistrationResponse(**provider["client_registration"])
|
|
||||||
)
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
logger.error(
|
logger.error(
|
||||||
|
@ -169,9 +167,7 @@ class Client(oic.Client):
|
||||||
if isinstance(authn_response, ErrorResponse):
|
if isinstance(authn_response, ErrorResponse):
|
||||||
error = authn_response.get("error", "")
|
error = authn_response.get("error", "")
|
||||||
if error == "login_required":
|
if error == "login_required":
|
||||||
logger.warning(
|
logger.warning("User was not logged in (%s), trying again for %s" % (error, state))
|
||||||
"User was not logged in (%s), trying again for %s" % (error, state)
|
|
||||||
)
|
|
||||||
return self.create_authn_request(session)
|
return self.create_authn_request(session)
|
||||||
else:
|
else:
|
||||||
logger.error("Unable to process response %s for %s" % (error, state))
|
logger.error("Unable to process response %s for %s" % (error, state))
|
||||||
|
@ -190,9 +186,7 @@ class Client(oic.Client):
|
||||||
|
|
||||||
if self.behaviour.get("response_type") == "code":
|
if self.behaviour.get("response_type") == "code":
|
||||||
# need an access token to get user info (and to log the user out later)
|
# need an access token to get user info (and to log the user out later)
|
||||||
self._request_token(
|
self._request_token(authn_response["state"], authn_response["code"], session)
|
||||||
authn_response["state"], authn_response["code"], session
|
|
||||||
)
|
|
||||||
|
|
||||||
user_info = self._get_user_info(state, session)
|
user_info = self._get_user_info(state, session)
|
||||||
|
|
||||||
|
@ -216,10 +210,7 @@ class Client(oic.Client):
|
||||||
|
|
||||||
# ErrorResponse is not raised, it is passed back...
|
# ErrorResponse is not raised, it is passed back...
|
||||||
if isinstance(info_response, ErrorResponse):
|
if isinstance(info_response, ErrorResponse):
|
||||||
logger.error(
|
logger.error("Unable to get user info (%s) for %s" % (info_response.get("error", ""), state))
|
||||||
"Unable to get user info (%s) for %s"
|
|
||||||
% (info_response.get("error", ""), state)
|
|
||||||
)
|
|
||||||
raise o_e.AuthenticationFailed(locator=state)
|
raise o_e.AuthenticationFailed(locator=state)
|
||||||
|
|
||||||
logger.debug("user info: %s" % info_response)
|
logger.debug("user info: %s" % info_response)
|
||||||
|
@ -249,10 +240,7 @@ class Client(oic.Client):
|
||||||
|
|
||||||
# ErrorResponse is not raised, it is passed back...
|
# ErrorResponse is not raised, it is passed back...
|
||||||
if isinstance(token_response, ErrorResponse):
|
if isinstance(token_response, ErrorResponse):
|
||||||
logger.error(
|
logger.error("Unable to get token (%s) for %s" % (token_response.get("error", ""), state))
|
||||||
"Unable to get token (%s) for %s"
|
|
||||||
% (token_response.get("error", ""), state)
|
|
||||||
)
|
|
||||||
raise o_e.AuthenticationFailed(locator=state)
|
raise o_e.AuthenticationFailed(locator=state)
|
||||||
|
|
||||||
logger.debug("token response %s" % token_response)
|
logger.debug("token response %s" % token_response)
|
||||||
|
|
|
@ -85,12 +85,8 @@ class ViewsTest(TestCase):
|
||||||
session.save()
|
session.save()
|
||||||
# mock
|
# mock
|
||||||
mock_client.callback.side_effect = self.user_info
|
mock_client.callback.side_effect = self.user_info
|
||||||
mock_client.registration_response = {
|
mock_client.registration_response = {"post_logout_redirect_uris": ["http://example.com/back"]}
|
||||||
"post_logout_redirect_uris": ["http://example.com/back"]
|
mock_client.provider_info = {"end_session_endpoint": "http://example.com/log_me_out"}
|
||||||
}
|
|
||||||
mock_client.provider_info = {
|
|
||||||
"end_session_endpoint": "http://example.com/log_me_out"
|
|
||||||
}
|
|
||||||
mock_client.client_id = "TEST"
|
mock_client.client_id = "TEST"
|
||||||
# test
|
# test
|
||||||
with less_console_noise():
|
with less_console_noise():
|
||||||
|
|
|
@ -92,11 +92,7 @@ def logout(request, next_page=None):
|
||||||
and len(CLIENT.registration_response["post_logout_redirect_uris"]) > 0
|
and len(CLIENT.registration_response["post_logout_redirect_uris"]) > 0
|
||||||
):
|
):
|
||||||
request_args.update(
|
request_args.update(
|
||||||
{
|
{"post_logout_redirect_uri": CLIENT.registration_response["post_logout_redirect_uris"][0]}
|
||||||
"post_logout_redirect_uri": CLIENT.registration_response[
|
|
||||||
"post_logout_redirect_uris"
|
|
||||||
][0]
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
url = CLIENT.provider_info["end_session_endpoint"]
|
url = CLIENT.provider_info["end_session_endpoint"]
|
||||||
|
|
|
@ -95,9 +95,7 @@ class EPPLibWrapper:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not self.pool_status.connection_success:
|
if not self.pool_status.connection_success:
|
||||||
raise LoginError(
|
raise LoginError("Couldn't connect to the registry after three attempts")
|
||||||
"Couldn't connect to the registry after three attempts"
|
|
||||||
)
|
|
||||||
with self._pool.get() as connection:
|
with self._pool.get() as connection:
|
||||||
response = connection.send(command)
|
response = connection.send(command)
|
||||||
except Timeout as t:
|
except Timeout as t:
|
||||||
|
@ -239,6 +237,4 @@ try:
|
||||||
logger.info("registry client initialized")
|
logger.info("registry client initialized")
|
||||||
except Exception:
|
except Exception:
|
||||||
CLIENT = None # type: ignore
|
CLIENT = None # type: ignore
|
||||||
logger.warning(
|
logger.warning("Unable to configure epplib. Registrar cannot contact registry.", exc_info=True)
|
||||||
"Unable to configure epplib. Registrar cannot contact registry.", exc_info=True
|
|
||||||
)
|
|
||||||
|
|
|
@ -103,9 +103,7 @@ class TestConnectionPool(TestCase):
|
||||||
],
|
],
|
||||||
cl_id="gov2023-ote",
|
cl_id="gov2023-ote",
|
||||||
cr_id="gov2023-ote",
|
cr_id="gov2023-ote",
|
||||||
cr_date=datetime.datetime(
|
cr_date=datetime.datetime(2023, 8, 15, 23, 56, 36, tzinfo=tzlocal()),
|
||||||
2023, 8, 15, 23, 56, 36, tzinfo=tzlocal()
|
|
||||||
),
|
|
||||||
up_id="gov2023-ote",
|
up_id="gov2023-ote",
|
||||||
up_date=datetime.datetime(2023, 8, 17, 2, 3, 19, tzinfo=tzlocal()),
|
up_date=datetime.datetime(2023, 8, 17, 2, 3, 19, tzinfo=tzlocal()),
|
||||||
tr_date=None,
|
tr_date=None,
|
||||||
|
@ -129,9 +127,7 @@ class TestConnectionPool(TestCase):
|
||||||
|
|
||||||
# Mock what happens inside the "with"
|
# Mock what happens inside the "with"
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
stack.enter_context(
|
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket))
|
||||||
patch.object(EPPConnectionPool, "_create_socket", self.fake_socket)
|
|
||||||
)
|
|
||||||
stack.enter_context(patch.object(Socket, "connect", self.fake_client))
|
stack.enter_context(patch.object(Socket, "connect", self.fake_client))
|
||||||
stack.enter_context(patch.object(SocketTransport, "send", self.fake_send))
|
stack.enter_context(patch.object(SocketTransport, "send", self.fake_send))
|
||||||
stack.enter_context(patch.object(SocketTransport, "receive", fake_receive))
|
stack.enter_context(patch.object(SocketTransport, "receive", fake_receive))
|
||||||
|
@ -176,9 +172,7 @@ class TestConnectionPool(TestCase):
|
||||||
],
|
],
|
||||||
cl_id="gov2023-ote",
|
cl_id="gov2023-ote",
|
||||||
cr_id="gov2023-ote",
|
cr_id="gov2023-ote",
|
||||||
cr_date=datetime.datetime(
|
cr_date=datetime.datetime(2023, 8, 15, 23, 56, 36, tzinfo=tzlocal()),
|
||||||
2023, 8, 15, 23, 56, 36, tzinfo=tzlocal()
|
|
||||||
),
|
|
||||||
up_id="gov2023-ote",
|
up_id="gov2023-ote",
|
||||||
up_date=datetime.datetime(2023, 8, 17, 2, 3, 19, tzinfo=tzlocal()),
|
up_date=datetime.datetime(2023, 8, 17, 2, 3, 19, tzinfo=tzlocal()),
|
||||||
tr_date=None,
|
tr_date=None,
|
||||||
|
@ -202,9 +196,7 @@ class TestConnectionPool(TestCase):
|
||||||
|
|
||||||
# Mock what happens inside the "with"
|
# Mock what happens inside the "with"
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
stack.enter_context(
|
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket))
|
||||||
patch.object(EPPConnectionPool, "_create_socket", self.fake_socket)
|
|
||||||
)
|
|
||||||
stack.enter_context(patch.object(Socket, "connect", self.fake_client))
|
stack.enter_context(patch.object(Socket, "connect", self.fake_client))
|
||||||
stack.enter_context(patch.object(SocketTransport, "send", self.fake_send))
|
stack.enter_context(patch.object(SocketTransport, "send", self.fake_send))
|
||||||
stack.enter_context(patch.object(SocketTransport, "receive", fake_receive))
|
stack.enter_context(patch.object(SocketTransport, "receive", fake_receive))
|
||||||
|
@ -218,9 +210,7 @@ class TestConnectionPool(TestCase):
|
||||||
# that they cannot connect to EPP
|
# that they cannot connect to EPP
|
||||||
with self.assertRaises(RegistryError):
|
with self.assertRaises(RegistryError):
|
||||||
expected = "InfoDomain failed to execute due to a connection error."
|
expected = "InfoDomain failed to execute due to a connection error."
|
||||||
result = registry.send(
|
result = registry.send(commands.InfoDomain(name="test.gov"), cleaned=True)
|
||||||
commands.InfoDomain(name="test.gov"), cleaned=True
|
|
||||||
)
|
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
# A subsequent command should be successful, as the pool restarts
|
# A subsequent command should be successful, as the pool restarts
|
||||||
|
@ -240,9 +230,7 @@ class TestConnectionPool(TestCase):
|
||||||
right as we send a command."""
|
right as we send a command."""
|
||||||
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
stack.enter_context(
|
stack.enter_context(patch.object(EPPConnectionPool, "_create_socket", self.fake_socket))
|
||||||
patch.object(EPPConnectionPool, "_create_socket", self.fake_socket)
|
|
||||||
)
|
|
||||||
stack.enter_context(patch.object(Socket, "connect", self.fake_client))
|
stack.enter_context(patch.object(Socket, "connect", self.fake_client))
|
||||||
|
|
||||||
# Pool should be running
|
# Pool should be running
|
||||||
|
@ -252,7 +240,5 @@ class TestConnectionPool(TestCase):
|
||||||
# Try to send a command out - should fail
|
# Try to send a command out - should fail
|
||||||
with self.assertRaises(RegistryError):
|
with self.assertRaises(RegistryError):
|
||||||
expected = "InfoDomain failed to execute due to a connection error."
|
expected = "InfoDomain failed to execute due to a connection error."
|
||||||
result = registry.send(
|
result = registry.send(commands.InfoDomain(name="test.gov"), cleaned=True)
|
||||||
commands.InfoDomain(name="test.gov"), cleaned=True
|
|
||||||
)
|
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
|
@ -125,9 +125,7 @@ class EPPConnectionPool(ConnectionPool):
|
||||||
|
|
||||||
# Open multiple connections
|
# Open multiple connections
|
||||||
for i in range(self.size):
|
for i in range(self.size):
|
||||||
self.greenlets.append(
|
self.greenlets.append(gevent.spawn_later(self.spawn_frequency * i, self._addOne))
|
||||||
gevent.spawn_later(self.spawn_frequency * i, self._addOne)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Open a "keepalive" thread if we want to ping open connections
|
# Open a "keepalive" thread if we want to ping open connections
|
||||||
if self.keepalive:
|
if self.keepalive:
|
||||||
|
|
|
@ -28,14 +28,8 @@ class PoolError(Exception):
|
||||||
|
|
||||||
# Used variables due to linter requirements
|
# Used variables due to linter requirements
|
||||||
kill_failed = "Could not kill all connections. Are multiple pools running?"
|
kill_failed = "Could not kill all connections. Are multiple pools running?"
|
||||||
conn_failed = (
|
conn_failed = "Failed to execute due to a registry error. See previous logs to determine the cause of the error."
|
||||||
"Failed to execute due to a registry error."
|
alive_failed = "Failed to keep the connection alive. It is likely that the registry returned a LoginError."
|
||||||
" See previous logs to determine the cause of the error."
|
|
||||||
)
|
|
||||||
alive_failed = (
|
|
||||||
"Failed to keep the connection alive. "
|
|
||||||
"It is likely that the registry returned a LoginError."
|
|
||||||
)
|
|
||||||
_error_mapping = {
|
_error_mapping = {
|
||||||
PoolErrorCodes.KILL_ALL_FAILED: kill_failed,
|
PoolErrorCodes.KILL_ALL_FAILED: kill_failed,
|
||||||
PoolErrorCodes.NEW_CONNECTION_FAILED: conn_failed,
|
PoolErrorCodes.NEW_CONNECTION_FAILED: conn_failed,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length=88
|
line-length=120
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
ignore_missing_imports = true
|
ignore_missing_imports = true
|
||||||
|
|
|
@ -73,9 +73,7 @@ class ListHeaderAdmin(AuditedAdmin):
|
||||||
filters = self.get_filters(request)
|
filters = self.get_filters(request)
|
||||||
# Pass the filtered values to the template context
|
# Pass the filtered values to the template context
|
||||||
extra_context["filters"] = filters
|
extra_context["filters"] = filters
|
||||||
extra_context["search_query"] = request.GET.get(
|
extra_context["search_query"] = request.GET.get("q", "") # Assuming the search query parameter is 'q'
|
||||||
"q", ""
|
|
||||||
) # Assuming the search query parameter is 'q'
|
|
||||||
return super().changelist_view(request, extra_context=extra_context)
|
return super().changelist_view(request, extra_context=extra_context)
|
||||||
|
|
||||||
def get_filters(self, request):
|
def get_filters(self, request):
|
||||||
|
@ -91,11 +89,7 @@ class ListHeaderAdmin(AuditedAdmin):
|
||||||
for param in request.GET.keys():
|
for param in request.GET.keys():
|
||||||
# Exclude the default search parameter 'q'
|
# Exclude the default search parameter 'q'
|
||||||
if param != "q" and param != "o":
|
if param != "q" and param != "o":
|
||||||
parameter_name = (
|
parameter_name = param.replace("__exact", "").replace("_type", "").replace("__id", " id")
|
||||||
param.replace("__exact", "")
|
|
||||||
.replace("_type", "")
|
|
||||||
.replace("__id", " id")
|
|
||||||
)
|
|
||||||
|
|
||||||
if parameter_name == "investigator id":
|
if parameter_name == "investigator id":
|
||||||
# Retrieves the corresponding contact from Users
|
# Retrieves the corresponding contact from Users
|
||||||
|
@ -613,8 +607,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
|
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
"This action is not permitted. The domain "
|
"This action is not permitted. The domain is already active.",
|
||||||
+ "is already active.",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -627,9 +620,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
models.DomainApplication.APPROVED: obj.approve,
|
models.DomainApplication.APPROVED: obj.approve,
|
||||||
models.DomainApplication.WITHDRAWN: obj.withdraw,
|
models.DomainApplication.WITHDRAWN: obj.withdraw,
|
||||||
models.DomainApplication.REJECTED: obj.reject,
|
models.DomainApplication.REJECTED: obj.reject,
|
||||||
models.DomainApplication.INELIGIBLE: (
|
models.DomainApplication.INELIGIBLE: (obj.reject_with_prejudice),
|
||||||
obj.reject_with_prejudice
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
selected_method = status_method_mapping.get(obj.status)
|
selected_method = status_method_mapping.get(obj.status)
|
||||||
if selected_method is None:
|
if selected_method is None:
|
||||||
|
@ -649,8 +640,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
|
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
"This action is not permitted for applications "
|
"This action is not permitted for applications with a restricted creator.",
|
||||||
+ "with a restricted creator.",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_readonly_fields(self, request, obj=None):
|
def get_readonly_fields(self, request, obj=None):
|
||||||
|
@ -669,9 +659,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
readonly_fields.extend([field.name for field in self.model._meta.fields])
|
readonly_fields.extend([field.name for field in self.model._meta.fields])
|
||||||
# Add the multi-select fields to readonly_fields:
|
# Add the multi-select fields to readonly_fields:
|
||||||
# Complex fields like ManyToManyField require special handling
|
# Complex fields like ManyToManyField require special handling
|
||||||
readonly_fields.extend(
|
readonly_fields.extend(["current_websites", "other_contacts", "alternative_domains"])
|
||||||
["current_websites", "other_contacts", "alternative_domains"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if request.user.has_perm("registrar.full_access_permission"):
|
if request.user.has_perm("registrar.full_access_permission"):
|
||||||
return readonly_fields
|
return readonly_fields
|
||||||
|
@ -739,9 +727,7 @@ class DomainAdmin(ListHeaderAdmin):
|
||||||
def organization_type(self, obj):
|
def organization_type(self, obj):
|
||||||
return obj.domain_info.get_organization_type_display()
|
return obj.domain_info.get_organization_type_display()
|
||||||
|
|
||||||
organization_type.admin_order_field = ( # type: ignore
|
organization_type.admin_order_field = "domain_info__organization_type" # type: ignore
|
||||||
"domain_info__organization_type"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Filters
|
# Filters
|
||||||
list_filter = ["domain_info__organization_type", "state"]
|
list_filter = ["domain_info__organization_type", "state"]
|
||||||
|
@ -846,9 +832,7 @@ class DomainAdmin(ListHeaderAdmin):
|
||||||
if not err.is_connection_error():
|
if not err.is_connection_error():
|
||||||
# If nothing is found, will default to returned err
|
# If nothing is found, will default to returned err
|
||||||
message = error_messages.get(err.code, err)
|
message = error_messages.get(err.code, err)
|
||||||
self.message_user(
|
self.message_user(request, f"Error deleting this Domain: {message}", messages.ERROR)
|
||||||
request, f"Error deleting this Domain: {message}", messages.ERROR
|
|
||||||
)
|
|
||||||
except TransitionNotAllowed:
|
except TransitionNotAllowed:
|
||||||
if obj.state == Domain.State.DELETED:
|
if obj.state == Domain.State.DELETED:
|
||||||
self.message_user(
|
self.message_user(
|
||||||
|
@ -886,8 +870,7 @@ class DomainAdmin(ListHeaderAdmin):
|
||||||
else:
|
else:
|
||||||
self.message_user(
|
self.message_user(
|
||||||
request,
|
request,
|
||||||
f"The registry statuses are {statuses}. "
|
f"The registry statuses are {statuses}. These statuses are from the provider of the .gov registry.",
|
||||||
"These statuses are from the provider of the .gov registry.",
|
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(".")
|
return HttpResponseRedirect(".")
|
||||||
|
|
||||||
|
@ -916,11 +899,7 @@ class DomainAdmin(ListHeaderAdmin):
|
||||||
else:
|
else:
|
||||||
self.message_user(
|
self.message_user(
|
||||||
request,
|
request,
|
||||||
(
|
("%s is in client hold. This domain is no longer accessible on the public internet.") % obj.name,
|
||||||
"%s is in client hold. This domain is no longer accessible on"
|
|
||||||
" the public internet."
|
|
||||||
)
|
|
||||||
% obj.name,
|
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(".")
|
return HttpResponseRedirect(".")
|
||||||
|
|
||||||
|
@ -949,8 +928,7 @@ class DomainAdmin(ListHeaderAdmin):
|
||||||
else:
|
else:
|
||||||
self.message_user(
|
self.message_user(
|
||||||
request,
|
request,
|
||||||
("%s is ready. This domain is accessible on the public internet.")
|
("%s is ready. This domain is accessible on the public internet.") % obj.name,
|
||||||
% obj.name,
|
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(".")
|
return HttpResponseRedirect(".")
|
||||||
|
|
||||||
|
@ -973,9 +951,9 @@ class DomainAdmin(ListHeaderAdmin):
|
||||||
# Fixes a bug wherein users which are only is_staff
|
# Fixes a bug wherein users which are only is_staff
|
||||||
# can access 'change' when GET,
|
# can access 'change' when GET,
|
||||||
# but cannot access this page when it is a request of type POST.
|
# but cannot access this page when it is a request of type POST.
|
||||||
if request.user.has_perm(
|
if request.user.has_perm("registrar.full_access_permission") or request.user.has_perm(
|
||||||
"registrar.full_access_permission"
|
"registrar.analyst_access_permission"
|
||||||
) or request.user.has_perm("registrar.analyst_access_permission"):
|
):
|
||||||
return True
|
return True
|
||||||
return super().has_change_permission(request, obj)
|
return super().has_change_permission(request, obj)
|
||||||
|
|
||||||
|
|
|
@ -526,9 +526,7 @@ OIDC_PROVIDERS = {
|
||||||
"acr_value": "http://idmanagement.gov/ns/assurance/ial/2",
|
"acr_value": "http://idmanagement.gov/ns/assurance/ial/2",
|
||||||
},
|
},
|
||||||
"client_registration": {
|
"client_registration": {
|
||||||
"client_id": (
|
"client_id": ("urn:gov:cisa:openidconnect.profiles:sp:sso:cisa:dotgov_registrar"),
|
||||||
"urn:gov:cisa:openidconnect.profiles:sp:sso:cisa:dotgov_registrar"
|
|
||||||
),
|
|
||||||
"redirect_uris": [f"{env_base_url}/openid/callback/login/"],
|
"redirect_uris": [f"{env_base_url}/openid/callback/login/"],
|
||||||
"post_logout_redirect_uris": [f"{env_base_url}/openid/callback/logout/"],
|
"post_logout_redirect_uris": [f"{env_base_url}/openid/callback/logout/"],
|
||||||
"token_endpoint_auth_method": ["private_key_jwt"],
|
"token_endpoint_auth_method": ["private_key_jwt"],
|
||||||
|
|
|
@ -97,9 +97,7 @@ class DomainApplicationFixture:
|
||||||
def _set_non_foreign_key_fields(cls, da: DomainApplication, app: dict):
|
def _set_non_foreign_key_fields(cls, da: DomainApplication, app: dict):
|
||||||
"""Helper method used by `load`."""
|
"""Helper method used by `load`."""
|
||||||
da.status = app["status"] if "status" in app else "started"
|
da.status = app["status"] if "status" in app else "started"
|
||||||
da.organization_type = (
|
da.organization_type = app["organization_type"] if "organization_type" in app else "federal"
|
||||||
app["organization_type"] if "organization_type" in app else "federal"
|
|
||||||
)
|
|
||||||
da.federal_agency = (
|
da.federal_agency = (
|
||||||
app["federal_agency"]
|
app["federal_agency"]
|
||||||
if "federal_agency" in app
|
if "federal_agency" in app
|
||||||
|
@ -112,40 +110,25 @@ class DomainApplicationFixture:
|
||||||
if "federal_type" in app
|
if "federal_type" in app
|
||||||
else random.choice(["executive", "judicial", "legislative"]) # nosec
|
else random.choice(["executive", "judicial", "legislative"]) # nosec
|
||||||
)
|
)
|
||||||
da.address_line1 = (
|
da.address_line1 = app["address_line1"] if "address_line1" in app else fake.street_address()
|
||||||
app["address_line1"] if "address_line1" in app else fake.street_address()
|
|
||||||
)
|
|
||||||
da.address_line2 = app["address_line2"] if "address_line2" in app else None
|
da.address_line2 = app["address_line2"] if "address_line2" in app else None
|
||||||
da.city = app["city"] if "city" in app else fake.city()
|
da.city = app["city"] if "city" in app else fake.city()
|
||||||
da.state_territory = (
|
da.state_territory = app["state_territory"] if "state_territory" in app else fake.state_abbr()
|
||||||
app["state_territory"] if "state_territory" in app else fake.state_abbr()
|
|
||||||
)
|
|
||||||
da.zipcode = app["zipcode"] if "zipcode" in app else fake.postalcode()
|
da.zipcode = app["zipcode"] if "zipcode" in app else fake.postalcode()
|
||||||
da.urbanization = app["urbanization"] if "urbanization" in app else None
|
da.urbanization = app["urbanization"] if "urbanization" in app else None
|
||||||
da.purpose = app["purpose"] if "purpose" in app else fake.paragraph()
|
da.purpose = app["purpose"] if "purpose" in app else fake.paragraph()
|
||||||
da.anything_else = app["anything_else"] if "anything_else" in app else None
|
da.anything_else = app["anything_else"] if "anything_else" in app else None
|
||||||
da.is_policy_acknowledged = (
|
da.is_policy_acknowledged = app["is_policy_acknowledged"] if "is_policy_acknowledged" in app else True
|
||||||
app["is_policy_acknowledged"] if "is_policy_acknowledged" in app else True
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _set_foreign_key_fields(cls, da: DomainApplication, app: dict, user: User):
|
def _set_foreign_key_fields(cls, da: DomainApplication, app: dict, user: User):
|
||||||
"""Helper method used by `load`."""
|
"""Helper method used by `load`."""
|
||||||
if not da.investigator:
|
if not da.investigator:
|
||||||
da.investigator = (
|
da.investigator = User.objects.get(username=user.username) if "investigator" in app else None
|
||||||
User.objects.get(username=user.username)
|
|
||||||
if "investigator" in app
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
|
|
||||||
if not da.authorizing_official:
|
if not da.authorizing_official:
|
||||||
if (
|
if "authorizing_official" in app and app["authorizing_official"] is not None:
|
||||||
"authorizing_official" in app
|
da.authorizing_official, _ = Contact.objects.get_or_create(**app["authorizing_official"])
|
||||||
and app["authorizing_official"] is not None
|
|
||||||
):
|
|
||||||
da.authorizing_official, _ = Contact.objects.get_or_create(
|
|
||||||
**app["authorizing_official"]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
da.authorizing_official = Contact.objects.create(**cls.fake_contact())
|
da.authorizing_official = Contact.objects.create(**cls.fake_contact())
|
||||||
|
|
||||||
|
@ -157,13 +140,9 @@ class DomainApplicationFixture:
|
||||||
|
|
||||||
if not da.requested_domain:
|
if not da.requested_domain:
|
||||||
if "requested_domain" in app and app["requested_domain"] is not None:
|
if "requested_domain" in app and app["requested_domain"] is not None:
|
||||||
da.requested_domain, _ = DraftDomain.objects.get_or_create(
|
da.requested_domain, _ = DraftDomain.objects.get_or_create(name=app["requested_domain"])
|
||||||
name=app["requested_domain"]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
da.requested_domain = DraftDomain.objects.create(
|
da.requested_domain = DraftDomain.objects.create(name=cls.fake_dot_gov())
|
||||||
name=cls.fake_dot_gov()
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _set_many_to_many_relations(cls, da: DomainApplication, app: dict):
|
def _set_many_to_many_relations(cls, da: DomainApplication, app: dict):
|
||||||
|
@ -173,32 +152,25 @@ class DomainApplicationFixture:
|
||||||
da.other_contacts.add(Contact.objects.get_or_create(**contact)[0])
|
da.other_contacts.add(Contact.objects.get_or_create(**contact)[0])
|
||||||
elif not da.other_contacts.exists():
|
elif not da.other_contacts.exists():
|
||||||
other_contacts = [
|
other_contacts = [
|
||||||
Contact.objects.create(**cls.fake_contact())
|
Contact.objects.create(**cls.fake_contact()) for _ in range(random.randint(0, 3)) # nosec
|
||||||
for _ in range(random.randint(0, 3)) # nosec
|
|
||||||
]
|
]
|
||||||
da.other_contacts.add(*other_contacts)
|
da.other_contacts.add(*other_contacts)
|
||||||
|
|
||||||
if "current_websites" in app:
|
if "current_websites" in app:
|
||||||
for website in app["current_websites"]:
|
for website in app["current_websites"]:
|
||||||
da.current_websites.add(
|
da.current_websites.add(Website.objects.get_or_create(website=website)[0])
|
||||||
Website.objects.get_or_create(website=website)[0]
|
|
||||||
)
|
|
||||||
elif not da.current_websites.exists():
|
elif not da.current_websites.exists():
|
||||||
current_websites = [
|
current_websites = [
|
||||||
Website.objects.create(website=fake.uri())
|
Website.objects.create(website=fake.uri()) for _ in range(random.randint(0, 3)) # nosec
|
||||||
for _ in range(random.randint(0, 3)) # nosec
|
|
||||||
]
|
]
|
||||||
da.current_websites.add(*current_websites)
|
da.current_websites.add(*current_websites)
|
||||||
|
|
||||||
if "alternative_domains" in app:
|
if "alternative_domains" in app:
|
||||||
for domain in app["alternative_domains"]:
|
for domain in app["alternative_domains"]:
|
||||||
da.alternative_domains.add(
|
da.alternative_domains.add(Website.objects.get_or_create(website=domain)[0])
|
||||||
Website.objects.get_or_create(website=domain)[0]
|
|
||||||
)
|
|
||||||
elif not da.alternative_domains.exists():
|
elif not da.alternative_domains.exists():
|
||||||
alternative_domains = [
|
alternative_domains = [
|
||||||
Website.objects.create(website=cls.fake_dot_gov())
|
Website.objects.create(website=cls.fake_dot_gov()) for _ in range(random.randint(0, 3)) # nosec
|
||||||
for _ in range(random.randint(0, 3)) # nosec
|
|
||||||
]
|
]
|
||||||
da.alternative_domains.add(*alternative_domains)
|
da.alternative_domains.add(*alternative_domains)
|
||||||
|
|
||||||
|
@ -242,9 +214,7 @@ class DomainFixture(DomainApplicationFixture):
|
||||||
|
|
||||||
for user in users:
|
for user in users:
|
||||||
# approve one of each users in review status domains
|
# approve one of each users in review status domains
|
||||||
application = DomainApplication.objects.filter(
|
application = DomainApplication.objects.filter(creator=user, status=DomainApplication.IN_REVIEW).last()
|
||||||
creator=user, status=DomainApplication.IN_REVIEW
|
|
||||||
).last()
|
|
||||||
logger.debug(f"Approving {application} for {user}")
|
logger.debug(f"Approving {application} for {user}")
|
||||||
application.approve()
|
application.approve()
|
||||||
application.save()
|
application.save()
|
||||||
|
|
|
@ -50,9 +50,7 @@ class RegistrarForm(forms.Form):
|
||||||
"""Returns a dict of form field values gotten from `obj`."""
|
"""Returns a dict of form field values gotten from `obj`."""
|
||||||
if obj is None:
|
if obj is None:
|
||||||
return {}
|
return {}
|
||||||
return {
|
return {name: getattr(obj, name) for name in cls.declared_fields.keys()} # type: ignore
|
||||||
name: getattr(obj, name) for name in cls.declared_fields.keys()
|
|
||||||
} # type: ignore
|
|
||||||
|
|
||||||
|
|
||||||
class RegistrarFormSet(forms.BaseFormSet):
|
class RegistrarFormSet(forms.BaseFormSet):
|
||||||
|
@ -178,10 +176,7 @@ class TribalGovernmentForm(RegistrarForm):
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
"""Needs to be either state or federally recognized."""
|
"""Needs to be either state or federally recognized."""
|
||||||
if not (
|
if not (self.cleaned_data["federally_recognized_tribe"] or self.cleaned_data["state_recognized_tribe"]):
|
||||||
self.cleaned_data["federally_recognized_tribe"]
|
|
||||||
or self.cleaned_data["state_recognized_tribe"]
|
|
||||||
):
|
|
||||||
raise forms.ValidationError(
|
raise forms.ValidationError(
|
||||||
# no sec because we are using it to include an internal URL
|
# no sec because we are using it to include an internal URL
|
||||||
# into a link. There should be no user-facing input in the
|
# into a link. There should be no user-facing input in the
|
||||||
|
@ -203,11 +198,7 @@ class OrganizationFederalForm(RegistrarForm):
|
||||||
federal_type = forms.ChoiceField(
|
federal_type = forms.ChoiceField(
|
||||||
choices=DomainApplication.BranchChoices.choices,
|
choices=DomainApplication.BranchChoices.choices,
|
||||||
widget=forms.RadioSelect,
|
widget=forms.RadioSelect,
|
||||||
error_messages={
|
error_messages={"required": ("Select the part of the federal government your organization is in.")},
|
||||||
"required": (
|
|
||||||
"Select the part of the federal government your organization is in."
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -227,10 +218,7 @@ class OrganizationElectionForm(RegistrarForm):
|
||||||
is_election_board = self.cleaned_data["is_election_board"]
|
is_election_board = self.cleaned_data["is_election_board"]
|
||||||
if is_election_board is None:
|
if is_election_board is None:
|
||||||
raise forms.ValidationError(
|
raise forms.ValidationError(
|
||||||
(
|
("Select “Yes” if you represent an election office. Select “No” if you don’t."),
|
||||||
"Select “Yes” if you represent an election office. Select “No” if"
|
|
||||||
" you don’t."
|
|
||||||
),
|
|
||||||
code="required",
|
code="required",
|
||||||
)
|
)
|
||||||
return is_election_board
|
return is_election_board
|
||||||
|
@ -260,18 +248,13 @@ class OrganizationContactForm(RegistrarForm):
|
||||||
)
|
)
|
||||||
city = forms.CharField(
|
city = forms.CharField(
|
||||||
label="City",
|
label="City",
|
||||||
error_messages={
|
error_messages={"required": "Enter the city where your organization is located."},
|
||||||
"required": "Enter the city where your organization is located."
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
state_territory = forms.ChoiceField(
|
state_territory = forms.ChoiceField(
|
||||||
label="State, territory, or military post",
|
label="State, territory, or military post",
|
||||||
choices=[("", "--Select--")] + DomainApplication.StateTerritoryChoices.choices,
|
choices=[("", "--Select--")] + DomainApplication.StateTerritoryChoices.choices,
|
||||||
error_messages={
|
error_messages={
|
||||||
"required": (
|
"required": ("Select the state, territory, or military post where your organization is located.")
|
||||||
"Select the state, territory, or military post where your organization"
|
|
||||||
" is located."
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
zipcode = forms.CharField(
|
zipcode = forms.CharField(
|
||||||
|
@ -320,9 +303,7 @@ class AboutYourOrganizationForm(RegistrarForm):
|
||||||
message="Response must be less than 1000 characters.",
|
message="Response must be less than 1000 characters.",
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
error_messages={
|
error_messages={"required": ("Enter more information about your organization.")},
|
||||||
"required": ("Enter more information about your organization.")
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -346,11 +327,7 @@ class AuthorizingOfficialForm(RegistrarForm):
|
||||||
|
|
||||||
first_name = forms.CharField(
|
first_name = forms.CharField(
|
||||||
label="First name / given name",
|
label="First name / given name",
|
||||||
error_messages={
|
error_messages={"required": ("Enter the first name / given name of your authorizing official.")},
|
||||||
"required": (
|
|
||||||
"Enter the first name / given name of your authorizing official."
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
middle_name = forms.CharField(
|
middle_name = forms.CharField(
|
||||||
required=False,
|
required=False,
|
||||||
|
@ -358,11 +335,7 @@ class AuthorizingOfficialForm(RegistrarForm):
|
||||||
)
|
)
|
||||||
last_name = forms.CharField(
|
last_name = forms.CharField(
|
||||||
label="Last name / family name",
|
label="Last name / family name",
|
||||||
error_messages={
|
error_messages={"required": ("Enter the last name / family name of your authorizing official.")},
|
||||||
"required": (
|
|
||||||
"Enter the last name / family name of your authorizing official."
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
title = forms.CharField(
|
title = forms.CharField(
|
||||||
label="Title or role in your organization",
|
label="Title or role in your organization",
|
||||||
|
@ -375,17 +348,11 @@ class AuthorizingOfficialForm(RegistrarForm):
|
||||||
)
|
)
|
||||||
email = forms.EmailField(
|
email = forms.EmailField(
|
||||||
label="Email",
|
label="Email",
|
||||||
error_messages={
|
error_messages={"invalid": ("Enter an email address in the required format, like name@example.com.")},
|
||||||
"invalid": (
|
|
||||||
"Enter an email address in the required format, like name@example.com."
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
phone = PhoneNumberField(
|
phone = PhoneNumberField(
|
||||||
label="Phone",
|
label="Phone",
|
||||||
error_messages={
|
error_messages={"required": "Enter the phone number for your authorizing official."},
|
||||||
"required": "Enter the phone number for your authorizing official."
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -394,10 +361,7 @@ class CurrentSitesForm(RegistrarForm):
|
||||||
required=False,
|
required=False,
|
||||||
label="Public website",
|
label="Public website",
|
||||||
error_messages={
|
error_messages={
|
||||||
"invalid": (
|
"invalid": ("Enter your organization's current website in the required format, like www.city.com.")
|
||||||
"Enter your organization's current website in the required format, like"
|
|
||||||
" www.city.com."
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -410,9 +374,7 @@ class BaseCurrentSitesFormSet(RegistrarFormSet):
|
||||||
return website.strip() == ""
|
return website.strip() == ""
|
||||||
|
|
||||||
def to_database(self, obj: DomainApplication):
|
def to_database(self, obj: DomainApplication):
|
||||||
self._to_database(
|
self._to_database(obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create)
|
||||||
obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_database(cls, obj):
|
def from_database(cls, obj):
|
||||||
|
@ -434,13 +396,9 @@ class AlternativeDomainForm(RegistrarForm):
|
||||||
requested = self.cleaned_data.get("alternative_domain", None)
|
requested = self.cleaned_data.get("alternative_domain", None)
|
||||||
validated = DraftDomain.validate(requested, blank_ok=True)
|
validated = DraftDomain.validate(requested, blank_ok=True)
|
||||||
except errors.ExtraDotsError:
|
except errors.ExtraDotsError:
|
||||||
raise forms.ValidationError(
|
raise forms.ValidationError(DOMAIN_API_MESSAGES["extra_dots"], code="extra_dots")
|
||||||
DOMAIN_API_MESSAGES["extra_dots"], code="extra_dots"
|
|
||||||
)
|
|
||||||
except errors.DomainUnavailableError:
|
except errors.DomainUnavailableError:
|
||||||
raise forms.ValidationError(
|
raise forms.ValidationError(DOMAIN_API_MESSAGES["unavailable"], code="unavailable")
|
||||||
DOMAIN_API_MESSAGES["unavailable"], code="unavailable"
|
|
||||||
)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise forms.ValidationError(DOMAIN_API_MESSAGES["invalid"], code="invalid")
|
raise forms.ValidationError(DOMAIN_API_MESSAGES["invalid"], code="invalid")
|
||||||
return validated
|
return validated
|
||||||
|
@ -471,9 +429,7 @@ class BaseAlternativeDomainFormSet(RegistrarFormSet):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def to_database(self, obj: DomainApplication):
|
def to_database(self, obj: DomainApplication):
|
||||||
self._to_database(
|
self._to_database(obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create)
|
||||||
obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def on_fetch(cls, query):
|
def on_fetch(cls, query):
|
||||||
|
@ -523,17 +479,11 @@ class DotGovDomainForm(RegistrarForm):
|
||||||
requested = self.cleaned_data.get("requested_domain", None)
|
requested = self.cleaned_data.get("requested_domain", None)
|
||||||
validated = DraftDomain.validate(requested)
|
validated = DraftDomain.validate(requested)
|
||||||
except errors.BlankValueError:
|
except errors.BlankValueError:
|
||||||
raise forms.ValidationError(
|
raise forms.ValidationError(DOMAIN_API_MESSAGES["required"], code="required")
|
||||||
DOMAIN_API_MESSAGES["required"], code="required"
|
|
||||||
)
|
|
||||||
except errors.ExtraDotsError:
|
except errors.ExtraDotsError:
|
||||||
raise forms.ValidationError(
|
raise forms.ValidationError(DOMAIN_API_MESSAGES["extra_dots"], code="extra_dots")
|
||||||
DOMAIN_API_MESSAGES["extra_dots"], code="extra_dots"
|
|
||||||
)
|
|
||||||
except errors.DomainUnavailableError:
|
except errors.DomainUnavailableError:
|
||||||
raise forms.ValidationError(
|
raise forms.ValidationError(DOMAIN_API_MESSAGES["unavailable"], code="unavailable")
|
||||||
DOMAIN_API_MESSAGES["unavailable"], code="unavailable"
|
|
||||||
)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise forms.ValidationError(DOMAIN_API_MESSAGES["invalid"], code="invalid")
|
raise forms.ValidationError(DOMAIN_API_MESSAGES["invalid"], code="invalid")
|
||||||
return validated
|
return validated
|
||||||
|
@ -551,9 +501,7 @@ class PurposeForm(RegistrarForm):
|
||||||
message="Response must be less than 1000 characters.",
|
message="Response must be less than 1000 characters.",
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
error_messages={
|
error_messages={"required": "Describe how you'll use the .gov domain you’re requesting."},
|
||||||
"required": "Describe how you'll use the .gov domain you’re requesting."
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -590,20 +538,12 @@ class YourContactForm(RegistrarForm):
|
||||||
title = forms.CharField(
|
title = forms.CharField(
|
||||||
label="Title or role in your organization",
|
label="Title or role in your organization",
|
||||||
error_messages={
|
error_messages={
|
||||||
"required": (
|
"required": ("Enter your title or role in your organization (e.g., Chief Information Officer).")
|
||||||
"Enter your title or role in your organization (e.g., Chief Information"
|
|
||||||
" Officer)."
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
email = forms.EmailField(
|
email = forms.EmailField(
|
||||||
label="Email",
|
label="Email",
|
||||||
error_messages={
|
error_messages={"invalid": ("Enter your email address in the required format, like name@example.com.")},
|
||||||
"invalid": (
|
|
||||||
"Enter your email address in the required format, like"
|
|
||||||
" name@example.com."
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
phone = PhoneNumberField(
|
phone = PhoneNumberField(
|
||||||
label="Phone",
|
label="Phone",
|
||||||
|
@ -614,9 +554,7 @@ class YourContactForm(RegistrarForm):
|
||||||
class OtherContactsForm(RegistrarForm):
|
class OtherContactsForm(RegistrarForm):
|
||||||
first_name = forms.CharField(
|
first_name = forms.CharField(
|
||||||
label="First name / given name",
|
label="First name / given name",
|
||||||
error_messages={
|
error_messages={"required": "Enter the first name / given name of this contact."},
|
||||||
"required": "Enter the first name / given name of this contact."
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
middle_name = forms.CharField(
|
middle_name = forms.CharField(
|
||||||
required=False,
|
required=False,
|
||||||
|
@ -624,26 +562,19 @@ class OtherContactsForm(RegistrarForm):
|
||||||
)
|
)
|
||||||
last_name = forms.CharField(
|
last_name = forms.CharField(
|
||||||
label="Last name / family name",
|
label="Last name / family name",
|
||||||
error_messages={
|
error_messages={"required": "Enter the last name / family name of this contact."},
|
||||||
"required": "Enter the last name / family name of this contact."
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
title = forms.CharField(
|
title = forms.CharField(
|
||||||
label="Title or role in your organization",
|
label="Title or role in your organization",
|
||||||
error_messages={
|
error_messages={
|
||||||
"required": (
|
"required": (
|
||||||
"Enter the title or role in your organization of this contact (e.g.,"
|
"Enter the title or role in your organization of this contact (e.g., Chief Information Officer)."
|
||||||
" Chief Information Officer)."
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
email = forms.EmailField(
|
email = forms.EmailField(
|
||||||
label="Email",
|
label="Email",
|
||||||
error_messages={
|
error_messages={"invalid": ("Enter an email address in the required format, like name@example.com.")},
|
||||||
"invalid": (
|
|
||||||
"Enter an email address in the required format, like name@example.com."
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
phone = PhoneNumberField(
|
phone = PhoneNumberField(
|
||||||
label="Phone",
|
label="Phone",
|
||||||
|
@ -659,9 +590,7 @@ class BaseOtherContactsFormSet(RegistrarFormSet):
|
||||||
return all(empty)
|
return all(empty)
|
||||||
|
|
||||||
def to_database(self, obj: DomainApplication):
|
def to_database(self, obj: DomainApplication):
|
||||||
self._to_database(
|
self._to_database(obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create)
|
||||||
obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_database(cls, obj):
|
def from_database(cls, obj):
|
||||||
|
@ -706,9 +635,6 @@ class RequirementsForm(RegistrarForm):
|
||||||
is_policy_acknowledged = forms.BooleanField(
|
is_policy_acknowledged = forms.BooleanField(
|
||||||
label="I read and agree to the requirements for operating .gov domains.",
|
label="I read and agree to the requirements for operating .gov domains.",
|
||||||
error_messages={
|
error_messages={
|
||||||
"required": (
|
"required": ("Check the box if you read and agree to the requirements for operating .gov domains.")
|
||||||
"Check the box if you read and agree to the requirements for"
|
|
||||||
" operating .gov domains."
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -95,23 +95,17 @@ class DomainNameserverForm(forms.Form):
|
||||||
elif e.code == nsErrorCodes.MISSING_IP:
|
elif e.code == nsErrorCodes.MISSING_IP:
|
||||||
self.add_error(
|
self.add_error(
|
||||||
"ip",
|
"ip",
|
||||||
NameserverError(
|
NameserverError(code=nsErrorCodes.MISSING_IP, nameserver=domain, ip=ip_list),
|
||||||
code=nsErrorCodes.MISSING_IP, nameserver=domain, ip=ip_list
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
elif e.code == nsErrorCodes.MISSING_HOST:
|
elif e.code == nsErrorCodes.MISSING_HOST:
|
||||||
self.add_error(
|
self.add_error(
|
||||||
"server",
|
"server",
|
||||||
NameserverError(
|
NameserverError(code=nsErrorCodes.MISSING_HOST, nameserver=domain, ip=ip_list),
|
||||||
code=nsErrorCodes.MISSING_HOST, nameserver=domain, ip=ip_list
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
elif e.code == nsErrorCodes.INVALID_HOST:
|
elif e.code == nsErrorCodes.INVALID_HOST:
|
||||||
self.add_error(
|
self.add_error(
|
||||||
"server",
|
"server",
|
||||||
NameserverError(
|
NameserverError(code=nsErrorCodes.INVALID_HOST, nameserver=server, ip=ip_list),
|
||||||
code=nsErrorCodes.INVALID_HOST, nameserver=server, ip=ip_list
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.add_error("ip", str(e))
|
self.add_error("ip", str(e))
|
||||||
|
@ -187,17 +181,12 @@ class DomainOrgNameAddressForm(forms.ModelForm):
|
||||||
"urbanization",
|
"urbanization",
|
||||||
]
|
]
|
||||||
error_messages = {
|
error_messages = {
|
||||||
"federal_agency": {
|
"federal_agency": {"required": "Select the federal agency for your organization."},
|
||||||
"required": "Select the federal agency for your organization."
|
|
||||||
},
|
|
||||||
"organization_name": {"required": "Enter the name of your organization."},
|
"organization_name": {"required": "Enter the name of your organization."},
|
||||||
"address_line1": {
|
"address_line1": {"required": "Enter the street address of your organization."},
|
||||||
"required": "Enter the street address of your organization."
|
|
||||||
},
|
|
||||||
"city": {"required": "Enter the city where your organization is located."},
|
"city": {"required": "Enter the city where your organization is located."},
|
||||||
"state_territory": {
|
"state_territory": {
|
||||||
"required": "Select the state, territory, or military post where your"
|
"required": "Select the state, territory, or military post where your organization is located."
|
||||||
"organization is located."
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
widgets = {
|
widgets = {
|
||||||
|
@ -205,9 +194,7 @@ class DomainOrgNameAddressForm(forms.ModelForm):
|
||||||
# state/territory because for these fields we are creating an individual
|
# state/territory because for these fields we are creating an individual
|
||||||
# instance of the Select. For the other fields we use the for loop to set
|
# instance of the Select. For the other fields we use the for loop to set
|
||||||
# the class's required attribute to true.
|
# the class's required attribute to true.
|
||||||
"federal_agency": forms.Select(
|
"federal_agency": forms.Select(attrs={"required": True}, choices=DomainInformation.AGENCY_CHOICES),
|
||||||
attrs={"required": True}, choices=DomainInformation.AGENCY_CHOICES
|
|
||||||
),
|
|
||||||
"organization_name": forms.TextInput,
|
"organization_name": forms.TextInput,
|
||||||
"address_line1": forms.TextInput,
|
"address_line1": forms.TextInput,
|
||||||
"address_line2": forms.TextInput,
|
"address_line2": forms.TextInput,
|
||||||
|
|
|
@ -23,9 +23,7 @@ class Command(BaseCommand):
|
||||||
default="txt",
|
default="txt",
|
||||||
help="What file extensions to look for, like txt or gz",
|
help="What file extensions to look for, like txt or gz",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument("--directory", default="migrationdata", help="Desired directory")
|
||||||
"--directory", default="migrationdata", help="Desired directory"
|
|
||||||
)
|
|
||||||
|
|
||||||
def handle(self, **options):
|
def handle(self, **options):
|
||||||
file_extension: str = options.get("file_extension").lstrip(".")
|
file_extension: str = options.get("file_extension").lstrip(".")
|
||||||
|
|
|
@ -52,20 +52,15 @@ class Command(BaseCommand):
|
||||||
if result.returncode:
|
if result.returncode:
|
||||||
self.stderr.write(
|
self.stderr.write(
|
||||||
self.style.NOTICE(
|
self.style.NOTICE(
|
||||||
"[manage.py lint] Re-try with: [docker-compose exec app] "
|
"[manage.py lint] Re-try with: [docker-compose exec app] " f"{' '.join(linter['args'])}"
|
||||||
f"{' '.join(linter['args'])}"
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
errors.append(CalledProcessError(result.returncode, linter["args"]))
|
errors.append(CalledProcessError(result.returncode, linter["args"]))
|
||||||
else:
|
else:
|
||||||
self.stdout.write(
|
self.stdout.write(f"[manage.py lint] {linter['purpose']} completed with success!")
|
||||||
f"[manage.py lint] {linter['purpose']} completed with success!"
|
|
||||||
)
|
|
||||||
if errors:
|
if errors:
|
||||||
self.stdout.write(f"[manage.py lint] {len(errors)} linter(s) failed.")
|
self.stdout.write(f"[manage.py lint] {len(errors)} linter(s) failed.")
|
||||||
raise LinterError(errors)
|
raise LinterError(errors)
|
||||||
except (CalledProcessError, LinterError) as e:
|
except (CalledProcessError, LinterError) as e:
|
||||||
raise CommandError(e)
|
raise CommandError(e)
|
||||||
self.stdout.write(
|
self.stdout.write(self.style.SUCCESS("[manage.py lint] All linters ran successfully."))
|
||||||
self.style.SUCCESS("[manage.py lint] All linters ran successfully.")
|
|
||||||
)
|
|
||||||
|
|
|
@ -21,9 +21,7 @@ class Command(BaseCommand):
|
||||||
"domain_contacts_filename",
|
"domain_contacts_filename",
|
||||||
help="Data file with domain contact information",
|
help="Data file with domain contact information",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument("contacts_filename", help="Data file with contact information")
|
||||||
"contacts_filename", help="Data file with contact information"
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument("--sep", default="|", help="Delimiter character")
|
parser.add_argument("--sep", default="|", help="Delimiter character")
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,7 @@ class Command(BaseCommand):
|
||||||
help = "Load domain data from a delimited text file on stdin."
|
help = "Load domain data from a delimited text file on stdin."
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument(
|
parser.add_argument("--sep", default="|", help="Separator character for data file")
|
||||||
"--sep", default="|", help="Separator character for data file"
|
|
||||||
)
|
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
separator_character = options.get("sep")
|
separator_character = options.get("sep")
|
||||||
|
|
|
@ -36,24 +36,18 @@ class Command(BaseCommand):
|
||||||
Use this to trigger a prompt for deleting all table entries. Useful
|
Use this to trigger a prompt for deleting all table entries. Useful
|
||||||
for testing purposes, but USE WITH CAUTION
|
for testing purposes, but USE WITH CAUTION
|
||||||
"""
|
"""
|
||||||
parser.add_argument(
|
parser.add_argument("domain_contacts_filename", help="Data file with domain contact information")
|
||||||
"domain_contacts_filename", help="Data file with domain contact information"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"contacts_filename",
|
"contacts_filename",
|
||||||
help="Data file with contact information",
|
help="Data file with contact information",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument("domain_statuses_filename", help="Data file with domain status information")
|
||||||
"domain_statuses_filename", help="Data file with domain status information"
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument("--sep", default="|", help="Delimiter character")
|
parser.add_argument("--sep", default="|", help="Delimiter character")
|
||||||
|
|
||||||
parser.add_argument("--debug", action=argparse.BooleanOptionalAction)
|
parser.add_argument("--debug", action=argparse.BooleanOptionalAction)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument("--limitParse", default=0, help="Sets max number of entries to load")
|
||||||
"--limitParse", default=0, help="Sets max number of entries to load"
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--resetTable",
|
"--resetTable",
|
||||||
|
@ -61,9 +55,7 @@ class Command(BaseCommand):
|
||||||
action=argparse.BooleanOptionalAction,
|
action=argparse.BooleanOptionalAction,
|
||||||
)
|
)
|
||||||
|
|
||||||
def print_debug_mode_statements(
|
def print_debug_mode_statements(self, debug_on: bool, debug_max_entries_to_parse: int):
|
||||||
self, debug_on: bool, debug_max_entries_to_parse: int
|
|
||||||
):
|
|
||||||
"""Prints additional terminal statements to indicate if --debug
|
"""Prints additional terminal statements to indicate if --debug
|
||||||
or --limitParse are in use"""
|
or --limitParse are in use"""
|
||||||
if debug_on:
|
if debug_on:
|
||||||
|
@ -85,9 +77,7 @@ class Command(BaseCommand):
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_domain_user_dict(
|
def get_domain_user_dict(self, domain_statuses_filename: str, sep: str) -> defaultdict[str, str]:
|
||||||
self, domain_statuses_filename: str, sep: str
|
|
||||||
) -> defaultdict[str, str]:
|
|
||||||
"""Creates a mapping of domain name -> status"""
|
"""Creates a mapping of domain name -> status"""
|
||||||
domain_status_dictionary = defaultdict(str)
|
domain_status_dictionary = defaultdict(str)
|
||||||
logger.info("Reading domain statuses data file %s", domain_statuses_filename)
|
logger.info("Reading domain statuses data file %s", domain_statuses_filename)
|
||||||
|
@ -99,9 +89,7 @@ class Command(BaseCommand):
|
||||||
logger.info("Loaded statuses for %d domains", len(domain_status_dictionary))
|
logger.info("Loaded statuses for %d domains", len(domain_status_dictionary))
|
||||||
return domain_status_dictionary
|
return domain_status_dictionary
|
||||||
|
|
||||||
def get_user_emails_dict(
|
def get_user_emails_dict(self, contacts_filename: str, sep) -> defaultdict[str, str]:
|
||||||
self, contacts_filename: str, sep
|
|
||||||
) -> defaultdict[str, str]:
|
|
||||||
"""Creates mapping of userId -> emails"""
|
"""Creates mapping of userId -> emails"""
|
||||||
user_emails_dictionary = defaultdict(str)
|
user_emails_dictionary = defaultdict(str)
|
||||||
logger.info("Reading contacts data file %s", contacts_filename)
|
logger.info("Reading contacts data file %s", contacts_filename)
|
||||||
|
@ -149,19 +137,13 @@ class Command(BaseCommand):
|
||||||
total_duplicate_domains = len(duplicate_domains)
|
total_duplicate_domains = len(duplicate_domains)
|
||||||
total_users_without_email = len(users_without_email)
|
total_users_without_email = len(users_without_email)
|
||||||
if total_users_without_email > 0:
|
if total_users_without_email > 0:
|
||||||
users_without_email_as_string = "{}".format(
|
users_without_email_as_string = "{}".format(", ".join(map(str, duplicate_domain_user_combos)))
|
||||||
", ".join(map(str, duplicate_domain_user_combos))
|
|
||||||
)
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"{TerminalColors.YELLOW} No e-mails found for users: {users_without_email_as_string}" # noqa
|
f"{TerminalColors.YELLOW} No e-mails found for users: {users_without_email_as_string}" # noqa
|
||||||
)
|
)
|
||||||
if total_duplicate_pairs > 0 or total_duplicate_domains > 0:
|
if total_duplicate_pairs > 0 or total_duplicate_domains > 0:
|
||||||
duplicate_pairs_as_string = "{}".format(
|
duplicate_pairs_as_string = "{}".format(", ".join(map(str, duplicate_domain_user_combos)))
|
||||||
", ".join(map(str, duplicate_domain_user_combos))
|
duplicate_domains_as_string = "{}".format(", ".join(map(str, duplicate_domains)))
|
||||||
)
|
|
||||||
duplicate_domains_as_string = "{}".format(
|
|
||||||
", ".join(map(str, duplicate_domains))
|
|
||||||
)
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"""{TerminalColors.YELLOW}
|
f"""{TerminalColors.YELLOW}
|
||||||
|
|
||||||
|
@ -179,9 +161,7 @@ class Command(BaseCommand):
|
||||||
{TerminalColors.ENDC}"""
|
{TerminalColors.ENDC}"""
|
||||||
)
|
)
|
||||||
|
|
||||||
def print_summary_status_findings(
|
def print_summary_status_findings(self, domains_without_status: list[str], outlier_statuses: list[str]):
|
||||||
self, domains_without_status: list[str], outlier_statuses: list[str]
|
|
||||||
):
|
|
||||||
"""Called at the end of the script execution to print out a summary of
|
"""Called at the end of the script execution to print out a summary of
|
||||||
status anomolies in the imported Verisign data. Currently, we check for:
|
status anomolies in the imported Verisign data. Currently, we check for:
|
||||||
- domains without a status
|
- domains without a status
|
||||||
|
@ -191,9 +171,7 @@ class Command(BaseCommand):
|
||||||
total_domains_without_status = len(domains_without_status)
|
total_domains_without_status = len(domains_without_status)
|
||||||
total_outlier_statuses = len(outlier_statuses)
|
total_outlier_statuses = len(outlier_statuses)
|
||||||
if total_domains_without_status > 0:
|
if total_domains_without_status > 0:
|
||||||
domains_without_status_as_string = "{}".format(
|
domains_without_status_as_string = "{}".format(", ".join(map(str, domains_without_status)))
|
||||||
", ".join(map(str, domains_without_status))
|
|
||||||
)
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"""{TerminalColors.YELLOW}
|
f"""{TerminalColors.YELLOW}
|
||||||
|
|
||||||
|
@ -207,9 +185,7 @@ class Command(BaseCommand):
|
||||||
)
|
)
|
||||||
|
|
||||||
if total_outlier_statuses > 0:
|
if total_outlier_statuses > 0:
|
||||||
domains_without_status_as_string = "{}".format(
|
domains_without_status_as_string = "{}".format(", ".join(map(str, outlier_statuses))) # noqa
|
||||||
", ".join(map(str, outlier_statuses))
|
|
||||||
) # noqa
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"""{TerminalColors.YELLOW}
|
f"""{TerminalColors.YELLOW}
|
||||||
|
|
||||||
|
@ -265,18 +241,14 @@ class Command(BaseCommand):
|
||||||
debug_on = options.get("debug")
|
debug_on = options.get("debug")
|
||||||
|
|
||||||
# Get --LimitParse argument
|
# Get --LimitParse argument
|
||||||
debug_max_entries_to_parse = int(
|
debug_max_entries_to_parse = int(options.get("limitParse")) # set to 0 to parse all entries
|
||||||
options.get("limitParse")
|
|
||||||
) # set to 0 to parse all entries
|
|
||||||
|
|
||||||
# print message to terminal about which args are in use
|
# print message to terminal about which args are in use
|
||||||
self.print_debug_mode_statements(debug_on, debug_max_entries_to_parse)
|
self.print_debug_mode_statements(debug_on, debug_max_entries_to_parse)
|
||||||
|
|
||||||
# STEP 1:
|
# STEP 1:
|
||||||
# Create mapping of domain name -> status
|
# Create mapping of domain name -> status
|
||||||
domain_status_dictionary = self.get_domain_user_dict(
|
domain_status_dictionary = self.get_domain_user_dict(domain_statuses_filename, sep)
|
||||||
domain_statuses_filename, sep
|
|
||||||
)
|
|
||||||
|
|
||||||
# STEP 2:
|
# STEP 2:
|
||||||
# Create mapping of userId -> email
|
# Create mapping of userId -> email
|
||||||
|
@ -367,12 +339,7 @@ class Command(BaseCommand):
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
existing_domain_user_pair = next(
|
existing_domain_user_pair = next(
|
||||||
(
|
(x for x in to_create if x.username == new_entry_email and x.domain_name == new_entry_domain_name),
|
||||||
x
|
|
||||||
for x in to_create
|
|
||||||
if x.username == new_entry_email
|
|
||||||
and x.domain_name == new_entry_domain_name
|
|
||||||
),
|
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
if existing_domain is not None:
|
if existing_domain is not None:
|
||||||
|
@ -443,10 +410,7 @@ class Command(BaseCommand):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check Parse limit and exit loop if needed
|
# Check Parse limit and exit loop if needed
|
||||||
if (
|
if total_rows_parsed >= debug_max_entries_to_parse and debug_max_entries_to_parse != 0:
|
||||||
total_rows_parsed >= debug_max_entries_to_parse
|
|
||||||
and debug_max_entries_to_parse != 0
|
|
||||||
):
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{TerminalColors.YELLOW}"
|
f"{TerminalColors.YELLOW}"
|
||||||
f"----PARSE LIMIT REACHED. HALTING PARSER.----"
|
f"----PARSE LIMIT REACHED. HALTING PARSER.----"
|
||||||
|
@ -467,7 +431,5 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
# Print a summary of findings (duplicate entries,
|
# Print a summary of findings (duplicate entries,
|
||||||
# missing data..etc.)
|
# missing data..etc.)
|
||||||
self.print_summary_duplications(
|
self.print_summary_duplications(duplicate_domain_user_combos, duplicate_domains, users_without_email)
|
||||||
duplicate_domain_user_combos, duplicate_domains, users_without_email
|
|
||||||
)
|
|
||||||
self.print_summary_status_findings(domains_without_status, outlier_statuses)
|
self.print_summary_status_findings(domains_without_status, outlier_statuses)
|
||||||
|
|
|
@ -94,10 +94,7 @@ class Command(BaseCommand):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--migrationDirectory",
|
"--migrationDirectory",
|
||||||
default="migrationdata",
|
default="migrationdata",
|
||||||
help=(
|
help=("The location of the files used for load_transition_domain migration script"),
|
||||||
"The location of the files used for"
|
|
||||||
"load_transition_domain migration script"
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--migrationFilenames",
|
"--migrationFilenames",
|
||||||
|
@ -116,17 +113,13 @@ class Command(BaseCommand):
|
||||||
information""",
|
information""",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument("--sep", default="|", help="Delimiter character for the migration files")
|
||||||
"--sep", default="|", help="Delimiter character for the migration files"
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument("--debug", action=argparse.BooleanOptionalAction)
|
parser.add_argument("--debug", action=argparse.BooleanOptionalAction)
|
||||||
|
|
||||||
parser.add_argument("--prompt", action=argparse.BooleanOptionalAction)
|
parser.add_argument("--prompt", action=argparse.BooleanOptionalAction)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument("--limitParse", default=0, help="Sets max number of entries to load")
|
||||||
"--limitParse", default=0, help="Sets max number of entries to load"
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--resetTable",
|
"--resetTable",
|
||||||
|
@ -173,9 +166,7 @@ class Command(BaseCommand):
|
||||||
# Check Domain table
|
# Check Domain table
|
||||||
matching_domains = Domain.objects.filter(name=transition_domain_name)
|
matching_domains = Domain.objects.filter(name=transition_domain_name)
|
||||||
# Check Domain Information table
|
# Check Domain Information table
|
||||||
matching_domain_informations = DomainInformation.objects.filter(
|
matching_domain_informations = DomainInformation.objects.filter(domain__name=transition_domain_name)
|
||||||
domain__name=transition_domain_name
|
|
||||||
)
|
|
||||||
# Check Domain Invitation table
|
# Check Domain Invitation table
|
||||||
matching_domain_invitations = DomainInvitation.objects.filter(
|
matching_domain_invitations = DomainInvitation.objects.filter(
|
||||||
email=transition_domain_email.lower(),
|
email=transition_domain_email.lower(),
|
||||||
|
@ -215,15 +206,9 @@ class Command(BaseCommand):
|
||||||
total_missing_domain_invitations = len(missing_domain_invites)
|
total_missing_domain_invitations = len(missing_domain_invites)
|
||||||
|
|
||||||
missing_domains_as_string = "{}".format(", ".join(map(str, missing_domains)))
|
missing_domains_as_string = "{}".format(", ".join(map(str, missing_domains)))
|
||||||
duplicate_domains_as_string = "{}".format(
|
duplicate_domains_as_string = "{}".format(", ".join(map(str, duplicate_domains)))
|
||||||
", ".join(map(str, duplicate_domains))
|
missing_domain_informations_as_string = "{}".format(", ".join(map(str, missing_domain_informations)))
|
||||||
)
|
missing_domain_invites_as_string = "{}".format(", ".join(map(str, missing_domain_invites)))
|
||||||
missing_domain_informations_as_string = "{}".format(
|
|
||||||
", ".join(map(str, missing_domain_informations))
|
|
||||||
)
|
|
||||||
missing_domain_invites_as_string = "{}".format(
|
|
||||||
", ".join(map(str, missing_domain_invites))
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"""{TerminalColors.OKGREEN}
|
f"""{TerminalColors.OKGREEN}
|
||||||
|
|
|
@ -83,10 +83,7 @@ class Command(BaseCommand):
|
||||||
# domains_with_errors
|
# domains_with_errors
|
||||||
try:
|
try:
|
||||||
# if prior username does not match current username
|
# if prior username does not match current username
|
||||||
if (
|
if not email_context["email"] or email_context["email"] != transition_domain.username:
|
||||||
not email_context["email"]
|
|
||||||
or email_context["email"] != transition_domain.username
|
|
||||||
):
|
|
||||||
# if not first in list of transition_domains
|
# if not first in list of transition_domains
|
||||||
if email_context["email"]:
|
if email_context["email"]:
|
||||||
# append the email context to the emails_to_send array
|
# append the email context to the emails_to_send array
|
||||||
|
@ -96,12 +93,8 @@ class Command(BaseCommand):
|
||||||
email_context["domains"].append(transition_domain.domain_name)
|
email_context["domains"].append(transition_domain.domain_name)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
# error condition if domain not in database
|
# error condition if domain not in database
|
||||||
self.domains_with_errors.append(
|
self.domains_with_errors.append(copy.deepcopy(transition_domain.domain_name))
|
||||||
copy.deepcopy(transition_domain.domain_name)
|
logger.error(f"error retrieving domain {transition_domain.domain_name}: {err}")
|
||||||
)
|
|
||||||
logger.error(
|
|
||||||
f"error retrieving domain {transition_domain.domain_name}: {err}"
|
|
||||||
)
|
|
||||||
# if there are at least one more transition domains than errors,
|
# if there are at least one more transition domains than errors,
|
||||||
# then append one more item
|
# then append one more item
|
||||||
if len(self.transition_domains) > len(self.domains_with_errors):
|
if len(self.transition_domains) > len(self.domains_with_errors):
|
||||||
|
|
|
@ -33,9 +33,7 @@ class Command(BaseCommand):
|
||||||
help="Sets max number of entries to load, set to 0 to load all entries",
|
help="Sets max number of entries to load, set to 0 to load all entries",
|
||||||
)
|
)
|
||||||
|
|
||||||
def print_debug_mode_statements(
|
def print_debug_mode_statements(self, debug_on: bool, debug_max_entries_to_parse: int):
|
||||||
self, debug_on: bool, debug_max_entries_to_parse: int
|
|
||||||
):
|
|
||||||
"""Prints additional terminal statements to indicate if --debug
|
"""Prints additional terminal statements to indicate if --debug
|
||||||
or --limitParse are in use"""
|
or --limitParse are in use"""
|
||||||
TerminalHelper.print_conditional(
|
TerminalHelper.print_conditional(
|
||||||
|
@ -57,9 +55,7 @@ class Command(BaseCommand):
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_domain_status(
|
def update_domain_status(self, transition_domain: TransitionDomain, target_domain: Domain, debug_on: bool) -> bool:
|
||||||
self, transition_domain: TransitionDomain, target_domain: Domain, debug_on: bool
|
|
||||||
) -> bool:
|
|
||||||
"""Given a transition domain that matches an existing domain,
|
"""Given a transition domain that matches an existing domain,
|
||||||
updates the existing domain object with that status of
|
updates the existing domain object with that status of
|
||||||
the transition domain.
|
the transition domain.
|
||||||
|
@ -153,9 +149,7 @@ class Command(BaseCommand):
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
|
||||||
def try_add_domain_invitation(
|
def try_add_domain_invitation(self, domain_email: str, associated_domain: Domain) -> DomainInvitation | None:
|
||||||
self, domain_email: str, associated_domain: Domain
|
|
||||||
) -> DomainInvitation | None:
|
|
||||||
"""If no domain invitation exists for the given domain and
|
"""If no domain invitation exists for the given domain and
|
||||||
e-mail, create and return a new domain invitation object.
|
e-mail, create and return a new domain invitation object.
|
||||||
If one already exists, or if the email is invalid, return NONE"""
|
If one already exists, or if the email is invalid, return NONE"""
|
||||||
|
@ -187,9 +181,7 @@ class Command(BaseCommand):
|
||||||
).exists()
|
).exists()
|
||||||
if not domain_email_already_in_domain_invites:
|
if not domain_email_already_in_domain_invites:
|
||||||
# Create new domain invitation
|
# Create new domain invitation
|
||||||
new_domain_invitation = DomainInvitation(
|
new_domain_invitation = DomainInvitation(email=domain_email.lower(), domain=associated_domain)
|
||||||
email=domain_email.lower(), domain=associated_domain
|
|
||||||
)
|
|
||||||
return new_domain_invitation
|
return new_domain_invitation
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -203,9 +195,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
# grab command line arguments and store locally...
|
# grab command line arguments and store locally...
|
||||||
debug_on = options.get("debug")
|
debug_on = options.get("debug")
|
||||||
debug_max_entries_to_parse = int(
|
debug_max_entries_to_parse = int(options.get("limitParse")) # set to 0 to parse all entries
|
||||||
options.get("limitParse")
|
|
||||||
) # set to 0 to parse all entries
|
|
||||||
|
|
||||||
self.print_debug_mode_statements(debug_on, debug_max_entries_to_parse)
|
self.print_debug_mode_statements(debug_on, debug_max_entries_to_parse)
|
||||||
|
|
||||||
|
@ -258,18 +248,14 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
# for existing entry, update the status to
|
# for existing entry, update the status to
|
||||||
# the transition domain status
|
# the transition domain status
|
||||||
update_made = self.update_domain_status(
|
update_made = self.update_domain_status(transition_domain, domain_to_update, debug_on)
|
||||||
transition_domain, domain_to_update, debug_on
|
|
||||||
)
|
|
||||||
if update_made:
|
if update_made:
|
||||||
# keep track of updated domains for data analysis purposes
|
# keep track of updated domains for data analysis purposes
|
||||||
updated_domain_entries.append(transition_domain.domain_name)
|
updated_domain_entries.append(transition_domain.domain_name)
|
||||||
|
|
||||||
# check if we need to add a domain invitation
|
# check if we need to add a domain invitation
|
||||||
# (eg. for a new user)
|
# (eg. for a new user)
|
||||||
new_domain_invitation = self.try_add_domain_invitation(
|
new_domain_invitation = self.try_add_domain_invitation(transition_domain_email, domain_to_update)
|
||||||
transition_domain_email, domain_to_update
|
|
||||||
)
|
|
||||||
|
|
||||||
except Domain.MultipleObjectsReturned:
|
except Domain.MultipleObjectsReturned:
|
||||||
# This exception was thrown once before during testing.
|
# This exception was thrown once before during testing.
|
||||||
|
@ -338,18 +324,14 @@ class Command(BaseCommand):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# no matching entry, make one
|
# no matching entry, make one
|
||||||
new_domain = Domain(
|
new_domain = Domain(name=transition_domain_name, state=transition_domain_status)
|
||||||
name=transition_domain_name, state=transition_domain_status
|
|
||||||
)
|
|
||||||
domains_to_create.append(new_domain)
|
domains_to_create.append(new_domain)
|
||||||
# DEBUG:
|
# DEBUG:
|
||||||
TerminalHelper.print_conditional(
|
TerminalHelper.print_conditional(
|
||||||
debug_on,
|
debug_on,
|
||||||
f"{TerminalColors.OKCYAN} Adding domain: {new_domain} {TerminalColors.ENDC}", # noqa
|
f"{TerminalColors.OKCYAN} Adding domain: {new_domain} {TerminalColors.ENDC}", # noqa
|
||||||
)
|
)
|
||||||
new_domain_invitation = self.try_add_domain_invitation(
|
new_domain_invitation = self.try_add_domain_invitation(transition_domain_email, new_domain)
|
||||||
transition_domain_email, new_domain
|
|
||||||
)
|
|
||||||
|
|
||||||
if new_domain_invitation is None:
|
if new_domain_invitation is None:
|
||||||
logger.info(
|
logger.info(
|
||||||
|
@ -365,10 +347,7 @@ class Command(BaseCommand):
|
||||||
domain_invitations_to_create.append(new_domain_invitation)
|
domain_invitations_to_create.append(new_domain_invitation)
|
||||||
|
|
||||||
# Check parse limit and exit loop if parse limit has been reached
|
# Check parse limit and exit loop if parse limit has been reached
|
||||||
if (
|
if debug_max_entries_to_parse > 0 and total_rows_parsed >= debug_max_entries_to_parse:
|
||||||
debug_max_entries_to_parse > 0
|
|
||||||
and total_rows_parsed >= debug_max_entries_to_parse
|
|
||||||
):
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"""{TerminalColors.YELLOW}
|
f"""{TerminalColors.YELLOW}
|
||||||
----PARSE LIMIT REACHED. HALTING PARSER.----
|
----PARSE LIMIT REACHED. HALTING PARSER.----
|
||||||
|
|
|
@ -64,9 +64,7 @@ class TerminalHelper:
|
||||||
logger.info(print_statement)
|
logger.info(print_statement)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def prompt_for_execution(
|
def prompt_for_execution(system_exit_on_terminate: bool, info_to_inspect: str, prompt_title: str) -> bool:
|
||||||
system_exit_on_terminate: bool, info_to_inspect: str, prompt_title: str
|
|
||||||
) -> bool:
|
|
||||||
"""Create to reduce code complexity.
|
"""Create to reduce code complexity.
|
||||||
Prompts the user to inspect the given string
|
Prompts the user to inspect the given string
|
||||||
and asks if they wish to proceed.
|
and asks if they wish to proceed.
|
||||||
|
|
|
@ -32,9 +32,7 @@ class Migration(migrations.Migration):
|
||||||
("password", models.CharField(max_length=128, verbose_name="password")),
|
("password", models.CharField(max_length=128, verbose_name="password")),
|
||||||
(
|
(
|
||||||
"last_login",
|
"last_login",
|
||||||
models.DateTimeField(
|
models.DateTimeField(blank=True, null=True, verbose_name="last login"),
|
||||||
blank=True, null=True, verbose_name="last login"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"is_superuser",
|
"is_superuser",
|
||||||
|
@ -47,35 +45,25 @@ class Migration(migrations.Migration):
|
||||||
(
|
(
|
||||||
"username",
|
"username",
|
||||||
models.CharField(
|
models.CharField(
|
||||||
error_messages={
|
error_messages={"unique": "A user with that username already exists."},
|
||||||
"unique": "A user with that username already exists."
|
|
||||||
},
|
|
||||||
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
||||||
max_length=150,
|
max_length=150,
|
||||||
unique=True,
|
unique=True,
|
||||||
validators=[
|
validators=[django.contrib.auth.validators.UnicodeUsernameValidator()],
|
||||||
django.contrib.auth.validators.UnicodeUsernameValidator()
|
|
||||||
],
|
|
||||||
verbose_name="username",
|
verbose_name="username",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"first_name",
|
"first_name",
|
||||||
models.CharField(
|
models.CharField(blank=True, max_length=150, verbose_name="first name"),
|
||||||
blank=True, max_length=150, verbose_name="first name"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"last_name",
|
"last_name",
|
||||||
models.CharField(
|
models.CharField(blank=True, max_length=150, verbose_name="last name"),
|
||||||
blank=True, max_length=150, verbose_name="last name"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"email",
|
"email",
|
||||||
models.EmailField(
|
models.EmailField(blank=True, max_length=254, verbose_name="email address"),
|
||||||
blank=True, max_length=254, verbose_name="email address"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"is_staff",
|
"is_staff",
|
||||||
|
@ -95,9 +83,7 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"date_joined",
|
"date_joined",
|
||||||
models.DateTimeField(
|
models.DateTimeField(default=django.utils.timezone.now, verbose_name="date joined"),
|
||||||
default=django.utils.timezone.now, verbose_name="date joined"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"groups",
|
"groups",
|
||||||
|
@ -145,9 +131,7 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"first_name",
|
"first_name",
|
||||||
models.TextField(
|
models.TextField(blank=True, db_index=True, help_text="First name", null=True),
|
||||||
blank=True, db_index=True, help_text="First name", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"middle_name",
|
"middle_name",
|
||||||
|
@ -155,22 +139,16 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"last_name",
|
"last_name",
|
||||||
models.TextField(
|
models.TextField(blank=True, db_index=True, help_text="Last name", null=True),
|
||||||
blank=True, db_index=True, help_text="Last name", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
("title", models.TextField(blank=True, help_text="Title", null=True)),
|
("title", models.TextField(blank=True, help_text="Title", null=True)),
|
||||||
(
|
(
|
||||||
"email",
|
"email",
|
||||||
models.TextField(
|
models.TextField(blank=True, db_index=True, help_text="Email", null=True),
|
||||||
blank=True, db_index=True, help_text="Email", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"phone",
|
"phone",
|
||||||
models.TextField(
|
models.TextField(blank=True, db_index=True, help_text="Phone", null=True),
|
||||||
blank=True, db_index=True, help_text="Phone", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -280,21 +258,15 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"unit_type",
|
"unit_type",
|
||||||
models.CharField(
|
models.CharField(blank=True, help_text="Unit type", max_length=15, null=True),
|
||||||
blank=True, help_text="Unit type", max_length=15, null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"unit_number",
|
"unit_number",
|
||||||
models.CharField(
|
models.CharField(blank=True, help_text="Unit number", max_length=255, null=True),
|
||||||
blank=True, help_text="Unit number", max_length=255, null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"state_territory",
|
"state_territory",
|
||||||
models.CharField(
|
models.CharField(blank=True, help_text="State/Territory", max_length=2, null=True),
|
||||||
blank=True, help_text="State/Territory", max_length=2, null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"zip_code",
|
"zip_code",
|
||||||
|
@ -308,9 +280,7 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"purpose",
|
"purpose",
|
||||||
models.TextField(
|
models.TextField(blank=True, help_text="Purpose of the domain", null=True),
|
||||||
blank=True, help_text="Purpose of the domain", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"security_email",
|
"security_email",
|
||||||
|
@ -323,9 +293,7 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"anything_else",
|
"anything_else",
|
||||||
models.TextField(
|
models.TextField(blank=True, help_text="Anything else we should know?", null=True),
|
||||||
blank=True, help_text="Anything else we should know?", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"acknowledged_policy",
|
"acknowledged_policy",
|
||||||
|
@ -337,9 +305,7 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"alternative_domains",
|
"alternative_domains",
|
||||||
models.ManyToManyField(
|
models.ManyToManyField(blank=True, related_name="alternatives+", to="registrar.website"),
|
||||||
blank=True, related_name="alternatives+", to="registrar.website"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"authorizing_official",
|
"authorizing_official",
|
||||||
|
@ -361,9 +327,7 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"current_websites",
|
"current_websites",
|
||||||
models.ManyToManyField(
|
models.ManyToManyField(blank=True, related_name="current+", to="registrar.website"),
|
||||||
blank=True, related_name="current+", to="registrar.website"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"investigator",
|
"investigator",
|
||||||
|
|
|
@ -48,9 +48,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="address_line2",
|
name="address_line2",
|
||||||
field=models.CharField(
|
field=models.CharField(blank=True, help_text="Address line 2", max_length=15, null=True),
|
||||||
blank=True, help_text="Address line 2", max_length=15, null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
|
|
|
@ -22,8 +22,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="federal_agency",
|
name="federal_agency",
|
||||||
field=models.TextField(
|
field=models.TextField(blank=True, help_text="Top level federal agency", null=True),
|
||||||
blank=True, help_text="Top level federal agency", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,9 +21,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="type_of_work",
|
name="type_of_work",
|
||||||
field=models.TextField(
|
field=models.TextField(blank=True, help_text="Type of work of the organization", null=True),
|
||||||
blank=True, help_text="Type of work of the organization", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
|
@ -33,9 +31,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="address_line2",
|
name="address_line2",
|
||||||
field=models.CharField(
|
field=models.CharField(blank=True, help_text="Street address line 2", max_length=15, null=True),
|
||||||
blank=True, help_text="Street address line 2", max_length=15, null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
|
@ -95,9 +91,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="purpose",
|
name="purpose",
|
||||||
field=models.TextField(
|
field=models.TextField(blank=True, help_text="Purpose of your domain", null=True),
|
||||||
blank=True, help_text="Purpose of your domain", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
|
@ -112,9 +106,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="urbanization",
|
name="urbanization",
|
||||||
field=models.TextField(
|
field=models.TextField(blank=True, help_text="Urbanization (Puerto Rico only)", null=True),
|
||||||
blank=True, help_text="Urbanization (Puerto Rico only)", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
|
|
|
@ -21,9 +21,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="contact",
|
model_name="contact",
|
||||||
name="created_at",
|
name="created_at",
|
||||||
field=models.DateTimeField(
|
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||||
auto_now_add=True, default=django.utils.timezone.now
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
preserve_default=False,
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
|
@ -34,9 +32,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="website",
|
model_name="website",
|
||||||
name="created_at",
|
name="created_at",
|
||||||
field=models.DateTimeField(
|
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||||
auto_now_add=True, default=django.utils.timezone.now
|
|
||||||
),
|
|
||||||
preserve_default=False,
|
preserve_default=False,
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
|
|
|
@ -12,16 +12,12 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="federally_recognized_tribe",
|
name="federally_recognized_tribe",
|
||||||
field=models.BooleanField(
|
field=models.BooleanField(help_text="Is the tribe federally recognized", null=True),
|
||||||
help_text="Is the tribe federally recognized", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="state_recognized_tribe",
|
name="state_recognized_tribe",
|
||||||
field=models.BooleanField(
|
field=models.BooleanField(help_text="Is the tribe recognized by a state", null=True),
|
||||||
help_text="Is the tribe recognized by a state", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
|
|
|
@ -59,8 +59,6 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
migrations.AddConstraint(
|
migrations.AddConstraint(
|
||||||
model_name="userdomainrole",
|
model_name="userdomainrole",
|
||||||
constraint=models.UniqueConstraint(
|
constraint=models.UniqueConstraint(fields=("user", "domain"), name="unique_user_domain_role"),
|
||||||
fields=("user", "domain"), name="unique_user_domain_role"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -64,15 +64,11 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"federally_recognized_tribe",
|
"federally_recognized_tribe",
|
||||||
models.BooleanField(
|
models.BooleanField(help_text="Is the tribe federally recognized", null=True),
|
||||||
help_text="Is the tribe federally recognized", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"state_recognized_tribe",
|
"state_recognized_tribe",
|
||||||
models.BooleanField(
|
models.BooleanField(help_text="Is the tribe recognized by a state", null=True),
|
||||||
help_text="Is the tribe recognized by a state", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"tribe_name",
|
"tribe_name",
|
||||||
|
@ -172,9 +168,7 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"purpose",
|
"purpose",
|
||||||
models.TextField(
|
models.TextField(blank=True, help_text="Purpose of your domain", null=True),
|
||||||
blank=True, help_text="Purpose of your domain", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"no_other_contacts_rationale",
|
"no_other_contacts_rationale",
|
||||||
|
@ -186,9 +180,7 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"anything_else",
|
"anything_else",
|
||||||
models.TextField(
|
models.TextField(blank=True, help_text="Anything else we should know?", null=True),
|
||||||
blank=True, help_text="Anything else we should know?", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"is_policy_acknowledged",
|
"is_policy_acknowledged",
|
||||||
|
|
|
@ -76,9 +76,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="publiccontact",
|
model_name="publiccontact",
|
||||||
name="org",
|
name="org",
|
||||||
field=models.TextField(
|
field=models.TextField(help_text="Contact's organization (null ok)", null=True),
|
||||||
help_text="Contact's organization (null ok)", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="publiccontact",
|
model_name="publiccontact",
|
||||||
|
@ -88,9 +86,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="publiccontact",
|
model_name="publiccontact",
|
||||||
name="pw",
|
name="pw",
|
||||||
field=models.TextField(
|
field=models.TextField(help_text="Contact's authorization code. 16 characters minimum."),
|
||||||
help_text="Contact's authorization code. 16 characters minimum."
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="publiccontact",
|
model_name="publiccontact",
|
||||||
|
@ -115,8 +111,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="publiccontact",
|
model_name="publiccontact",
|
||||||
name="voice",
|
name="voice",
|
||||||
field=models.TextField(
|
field=models.TextField(help_text="Contact's phone number. Must be in ITU.E164.2005 format"),
|
||||||
help_text="Contact's phone number. Must be in ITU.E164.2005 format"
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,8 +12,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="contact",
|
model_name="contact",
|
||||||
name="email",
|
name="email",
|
||||||
field=models.EmailField(
|
field=models.EmailField(blank=True, db_index=True, help_text="Email", max_length=254, null=True),
|
||||||
blank=True, db_index=True, help_text="Email", max_length=254, null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,15 +12,11 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="address_line2",
|
name="address_line2",
|
||||||
field=models.TextField(
|
field=models.TextField(blank=True, help_text="Street address line 2", null=True),
|
||||||
blank=True, help_text="Street address line 2", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domaininformation",
|
model_name="domaininformation",
|
||||||
name="address_line2",
|
name="address_line2",
|
||||||
field=models.TextField(
|
field=models.TextField(blank=True, help_text="Street address line 2", null=True),
|
||||||
blank=True, help_text="Street address line 2", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -95,16 +95,12 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
name="about_your_organization",
|
name="about_your_organization",
|
||||||
field=models.TextField(
|
field=models.TextField(blank=True, help_text="Information about your organization", null=True),
|
||||||
blank=True, help_text="Information about your organization", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="domaininformation",
|
model_name="domaininformation",
|
||||||
name="about_your_organization",
|
name="about_your_organization",
|
||||||
field=models.TextField(
|
field=models.TextField(blank=True, help_text="Information about your organization", null=True),
|
||||||
blank=True, help_text="Information about your organization", null=True
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domainapplication",
|
model_name="domainapplication",
|
||||||
|
|
|
@ -262,10 +262,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
doesn't add the created host to the domain
|
doesn't add the created host to the domain
|
||||||
returns ErrorCode (int)"""
|
returns ErrorCode (int)"""
|
||||||
if addrs is not None and addrs != []:
|
if addrs is not None and addrs != []:
|
||||||
addresses = [
|
addresses = [epp.Ip(addr=addr, ip="v6" if self.is_ipv6(addr) else None) for addr in addrs]
|
||||||
epp.Ip(addr=addr, ip="v6" if self.is_ipv6(addr) else None)
|
|
||||||
for addr in addrs
|
|
||||||
]
|
|
||||||
request = commands.CreateHost(name=host, addrs=addresses)
|
request = commands.CreateHost(name=host, addrs=addresses)
|
||||||
else:
|
else:
|
||||||
request = commands.CreateHost(name=host)
|
request = commands.CreateHost(name=host)
|
||||||
|
@ -358,15 +355,11 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
raise NameserverError(code=nsErrorCodes.MISSING_IP, nameserver=nameserver)
|
raise NameserverError(code=nsErrorCodes.MISSING_IP, nameserver=nameserver)
|
||||||
|
|
||||||
elif not cls.isSubdomain(name, nameserver) and (ip is not None and ip != []):
|
elif not cls.isSubdomain(name, nameserver) and (ip is not None and ip != []):
|
||||||
raise NameserverError(
|
raise NameserverError(code=nsErrorCodes.GLUE_RECORD_NOT_ALLOWED, nameserver=nameserver, ip=ip)
|
||||||
code=nsErrorCodes.GLUE_RECORD_NOT_ALLOWED, nameserver=nameserver, ip=ip
|
|
||||||
)
|
|
||||||
elif ip is not None and ip != []:
|
elif ip is not None and ip != []:
|
||||||
for addr in ip:
|
for addr in ip:
|
||||||
if not cls._valid_ip_addr(addr):
|
if not cls._valid_ip_addr(addr):
|
||||||
raise NameserverError(
|
raise NameserverError(code=nsErrorCodes.INVALID_IP, nameserver=nameserver[:40], ip=ip)
|
||||||
code=nsErrorCodes.INVALID_IP, nameserver=nameserver[:40], ip=ip
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -382,9 +375,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getNameserverChanges(
|
def getNameserverChanges(self, hosts: list[tuple[str, list]]) -> tuple[list, list, dict, dict]:
|
||||||
self, hosts: list[tuple[str, list]]
|
|
||||||
) -> tuple[list, list, dict, dict]:
|
|
||||||
"""
|
"""
|
||||||
calls self.nameserver, it should pull from cache but may result
|
calls self.nameserver, it should pull from cache but may result
|
||||||
in an epp call
|
in an epp call
|
||||||
|
@ -420,40 +411,27 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
else:
|
else:
|
||||||
# TODO - host is being updated when previous was None+new is empty list
|
# TODO - host is being updated when previous was None+new is empty list
|
||||||
# add check here
|
# add check here
|
||||||
if newHostDict[prevHost] is not None and set(
|
if newHostDict[prevHost] is not None and set(newHostDict[prevHost]) != set(addrs):
|
||||||
newHostDict[prevHost]
|
self.__class__.checkHostIPCombo(name=self.name, nameserver=prevHost, ip=newHostDict[prevHost])
|
||||||
) != set(addrs):
|
|
||||||
self.__class__.checkHostIPCombo(
|
|
||||||
name=self.name, nameserver=prevHost, ip=newHostDict[prevHost]
|
|
||||||
)
|
|
||||||
updated_values.append((prevHost, newHostDict[prevHost]))
|
updated_values.append((prevHost, newHostDict[prevHost]))
|
||||||
|
|
||||||
new_values = {
|
new_values = {
|
||||||
key: newHostDict.get(key)
|
key: newHostDict.get(key) for key in newHostDict if key not in previousHostDict and key.strip() != ""
|
||||||
for key in newHostDict
|
|
||||||
if key not in previousHostDict and key.strip() != ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for nameserver, ip in new_values.items():
|
for nameserver, ip in new_values.items():
|
||||||
self.__class__.checkHostIPCombo(
|
self.__class__.checkHostIPCombo(name=self.name, nameserver=nameserver, ip=ip)
|
||||||
name=self.name, nameserver=nameserver, ip=ip
|
|
||||||
)
|
|
||||||
|
|
||||||
return (deleted_values, updated_values, new_values, previousHostDict)
|
return (deleted_values, updated_values, new_values, previousHostDict)
|
||||||
|
|
||||||
def _update_host_values(self, updated_values, oldNameservers):
|
def _update_host_values(self, updated_values, oldNameservers):
|
||||||
for hostTuple in updated_values:
|
for hostTuple in updated_values:
|
||||||
updated_response_code = self._update_host(
|
updated_response_code = self._update_host(hostTuple[0], hostTuple[1], oldNameservers.get(hostTuple[0]))
|
||||||
hostTuple[0], hostTuple[1], oldNameservers.get(hostTuple[0])
|
|
||||||
)
|
|
||||||
if updated_response_code not in [
|
if updated_response_code not in [
|
||||||
ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
|
ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
|
||||||
ErrorCode.OBJECT_EXISTS,
|
ErrorCode.OBJECT_EXISTS,
|
||||||
]:
|
]:
|
||||||
logger.warning(
|
logger.warning("Could not update host %s. Error code was: %s " % (hostTuple[0], updated_response_code))
|
||||||
"Could not update host %s. Error code was: %s "
|
|
||||||
% (hostTuple[0], updated_response_code)
|
|
||||||
)
|
|
||||||
|
|
||||||
def createNewHostList(self, new_values: dict):
|
def createNewHostList(self, new_values: dict):
|
||||||
"""convert the dictionary of new values to a list of HostObjSet
|
"""convert the dictionary of new values to a list of HostObjSet
|
||||||
|
@ -469,13 +447,8 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
|
|
||||||
hostStringList = []
|
hostStringList = []
|
||||||
for key, value in new_values.items():
|
for key, value in new_values.items():
|
||||||
createdCode = self._create_host(
|
createdCode = self._create_host(host=key, addrs=value) # creates in registry
|
||||||
host=key, addrs=value
|
if createdCode == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY or createdCode == ErrorCode.OBJECT_EXISTS:
|
||||||
) # creates in registry
|
|
||||||
if (
|
|
||||||
createdCode == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
|
|
||||||
or createdCode == ErrorCode.OBJECT_EXISTS
|
|
||||||
):
|
|
||||||
hostStringList.append(key)
|
hostStringList.append(key)
|
||||||
if hostStringList == []:
|
if hostStringList == []:
|
||||||
return [], 0
|
return [], 0
|
||||||
|
@ -522,9 +495,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
logger.info("Domain does not have dnssec data defined %s" % err)
|
logger.info("Domain does not have dnssec data defined %s" % err)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getDnssecdataChanges(
|
def getDnssecdataChanges(self, _dnssecdata: Optional[extensions.DNSSECExtension]) -> tuple[dict, dict]:
|
||||||
self, _dnssecdata: Optional[extensions.DNSSECExtension]
|
|
||||||
) -> tuple[dict, dict]:
|
|
||||||
"""
|
"""
|
||||||
calls self.dnssecdata, it should pull from cache but may result
|
calls self.dnssecdata, it should pull from cache but may result
|
||||||
in an epp call
|
in an epp call
|
||||||
|
@ -550,20 +521,12 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
|
|
||||||
if oldDnssecdata and len(oldDnssecdata.dsData) > 0:
|
if oldDnssecdata and len(oldDnssecdata.dsData) > 0:
|
||||||
# if existing dsData not in new dsData, mark for removal
|
# if existing dsData not in new dsData, mark for removal
|
||||||
dsDataForRemoval = [
|
dsDataForRemoval = [dsData for dsData in oldDnssecdata.dsData if dsData not in _dnssecdata.dsData]
|
||||||
dsData
|
|
||||||
for dsData in oldDnssecdata.dsData
|
|
||||||
if dsData not in _dnssecdata.dsData
|
|
||||||
]
|
|
||||||
if len(dsDataForRemoval) > 0:
|
if len(dsDataForRemoval) > 0:
|
||||||
remDnssecdata["dsData"] = dsDataForRemoval
|
remDnssecdata["dsData"] = dsDataForRemoval
|
||||||
|
|
||||||
# if new dsData not in existing dsData, mark for add
|
# if new dsData not in existing dsData, mark for add
|
||||||
dsDataForAdd = [
|
dsDataForAdd = [dsData for dsData in _dnssecdata.dsData if dsData not in oldDnssecdata.dsData]
|
||||||
dsData
|
|
||||||
for dsData in _dnssecdata.dsData
|
|
||||||
if dsData not in oldDnssecdata.dsData
|
|
||||||
]
|
|
||||||
if len(dsDataForAdd) > 0:
|
if len(dsDataForAdd) > 0:
|
||||||
addDnssecdata["dsData"] = dsDataForAdd
|
addDnssecdata["dsData"] = dsDataForAdd
|
||||||
else:
|
else:
|
||||||
|
@ -598,9 +561,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
if "dsData" in _remDnssecdata and _remDnssecdata["dsData"] is not None:
|
if "dsData" in _remDnssecdata and _remDnssecdata["dsData"] is not None:
|
||||||
registry.send(remRequest, cleaned=True)
|
registry.send(remRequest, cleaned=True)
|
||||||
except RegistryError as e:
|
except RegistryError as e:
|
||||||
logger.error(
|
logger.error("Error updating DNSSEC, code was %s error was %s" % (e.code, e))
|
||||||
"Error updating DNSSEC, code was %s error was %s" % (e.code, e)
|
|
||||||
)
|
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
@nameservers.setter # type: ignore
|
@nameservers.setter # type: ignore
|
||||||
|
@ -630,14 +591,10 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
oldNameservers,
|
oldNameservers,
|
||||||
) = self.getNameserverChanges(hosts=hosts)
|
) = self.getNameserverChanges(hosts=hosts)
|
||||||
|
|
||||||
_ = self._update_host_values(
|
_ = self._update_host_values(updated_values, oldNameservers) # returns nothing, just need to be run and errors
|
||||||
updated_values, oldNameservers
|
|
||||||
) # returns nothing, just need to be run and errors
|
|
||||||
addToDomainList, addToDomainCount = self.createNewHostList(new_values)
|
addToDomainList, addToDomainCount = self.createNewHostList(new_values)
|
||||||
deleteHostList, deleteCount = self.createDeleteHostList(deleted_values)
|
deleteHostList, deleteCount = self.createDeleteHostList(deleted_values)
|
||||||
responseCode = self.addAndRemoveHostsFromDomain(
|
responseCode = self.addAndRemoveHostsFromDomain(hostsToAdd=addToDomainList, hostsToDelete=deleteHostList)
|
||||||
hostsToAdd=addToDomainList, hostsToDelete=deleteHostList
|
|
||||||
)
|
|
||||||
|
|
||||||
# if unable to update domain raise error and stop
|
# if unable to update domain raise error and stop
|
||||||
if responseCode != ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY:
|
if responseCode != ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY:
|
||||||
|
@ -651,19 +608,13 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
self.dns_needed()
|
self.dns_needed()
|
||||||
self.save()
|
self.save()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.info(
|
logger.info("nameserver setter checked for dns_needed state and it did not succeed. Warning: %s" % err)
|
||||||
"nameserver setter checked for dns_needed state "
|
|
||||||
"and it did not succeed. Warning: %s" % err
|
|
||||||
)
|
|
||||||
elif successTotalNameservers >= 2 and successTotalNameservers <= 13:
|
elif successTotalNameservers >= 2 and successTotalNameservers <= 13:
|
||||||
try:
|
try:
|
||||||
self.ready()
|
self.ready()
|
||||||
self.save()
|
self.save()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.info(
|
logger.info("nameserver setter checked for create state and it did not succeed. Warning: %s" % err)
|
||||||
"nameserver setter checked for create state "
|
|
||||||
"and it did not succeed. Warning: %s" % err
|
|
||||||
)
|
|
||||||
|
|
||||||
@Cache
|
@Cache
|
||||||
def statuses(self) -> list[str]:
|
def statuses(self) -> list[str]:
|
||||||
|
@ -698,9 +649,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
so follow on additions will update the current registrant"""
|
so follow on additions will update the current registrant"""
|
||||||
|
|
||||||
logger.info("making registrant contact")
|
logger.info("making registrant contact")
|
||||||
self._set_singleton_contact(
|
self._set_singleton_contact(contact=contact, expectedType=contact.ContactTypeChoices.REGISTRANT)
|
||||||
contact=contact, expectedType=contact.ContactTypeChoices.REGISTRANT
|
|
||||||
)
|
|
||||||
|
|
||||||
@Cache
|
@Cache
|
||||||
def administrative_contact(self) -> PublicContact | None:
|
def administrative_contact(self) -> PublicContact | None:
|
||||||
|
@ -712,9 +661,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
def administrative_contact(self, contact: PublicContact):
|
def administrative_contact(self, contact: PublicContact):
|
||||||
logger.info("making admin contact")
|
logger.info("making admin contact")
|
||||||
if contact.contact_type != contact.ContactTypeChoices.ADMINISTRATIVE:
|
if contact.contact_type != contact.ContactTypeChoices.ADMINISTRATIVE:
|
||||||
raise ValueError(
|
raise ValueError("Cannot set a registrant contact with a different contact type")
|
||||||
"Cannot set a registrant contact with a different contact type"
|
|
||||||
)
|
|
||||||
self._make_contact_in_registry(contact=contact)
|
self._make_contact_in_registry(contact=contact)
|
||||||
self._update_domain_with_contact(contact, rem=False)
|
self._update_domain_with_contact(contact, rem=False)
|
||||||
|
|
||||||
|
@ -736,20 +683,14 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
try:
|
try:
|
||||||
registry.send(updateContact, cleaned=True)
|
registry.send(updateContact, cleaned=True)
|
||||||
except RegistryError as e:
|
except RegistryError as e:
|
||||||
logger.error(
|
logger.error("Error updating contact, code was %s error was %s" % (e.code, e))
|
||||||
"Error updating contact, code was %s error was %s" % (e.code, e)
|
|
||||||
)
|
|
||||||
# TODO - ticket 433 human readable error handling here
|
# TODO - ticket 433 human readable error handling here
|
||||||
|
|
||||||
def _update_domain_with_contact(self, contact: PublicContact, rem=False):
|
def _update_domain_with_contact(self, contact: PublicContact, rem=False):
|
||||||
"""adds or removes a contact from a domain
|
"""adds or removes a contact from a domain
|
||||||
rem being true indicates the contact will be removed from registry"""
|
rem being true indicates the contact will be removed from registry"""
|
||||||
logger.info(
|
logger.info("_update_domain_with_contact() received type %s " % contact.contact_type)
|
||||||
"_update_domain_with_contact() received type %s " % contact.contact_type
|
domainContact = epp.DomainContact(contact=contact.registry_id, type=contact.contact_type)
|
||||||
)
|
|
||||||
domainContact = epp.DomainContact(
|
|
||||||
contact=contact.registry_id, type=contact.contact_type
|
|
||||||
)
|
|
||||||
|
|
||||||
updateDomain = commands.UpdateDomain(name=self.name, add=[domainContact])
|
updateDomain = commands.UpdateDomain(name=self.name, add=[domainContact])
|
||||||
if rem:
|
if rem:
|
||||||
|
@ -758,17 +699,12 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
try:
|
try:
|
||||||
registry.send(updateDomain, cleaned=True)
|
registry.send(updateDomain, cleaned=True)
|
||||||
except RegistryError as e:
|
except RegistryError as e:
|
||||||
logger.error(
|
logger.error("Error changing contact on a domain. Error code is %s error was %s" % (e.code, e))
|
||||||
"Error changing contact on a domain. Error code is %s error was %s"
|
|
||||||
% (e.code, e)
|
|
||||||
)
|
|
||||||
action = "add"
|
action = "add"
|
||||||
if rem:
|
if rem:
|
||||||
action = "remove"
|
action = "remove"
|
||||||
|
|
||||||
raise Exception(
|
raise Exception("Can't %s the contact of type %s" % (action, contact.contact_type))
|
||||||
"Can't %s the contact of type %s" % (action, contact.contact_type)
|
|
||||||
)
|
|
||||||
|
|
||||||
@Cache
|
@Cache
|
||||||
def security_contact(self) -> PublicContact | None:
|
def security_contact(self) -> PublicContact | None:
|
||||||
|
@ -778,16 +714,11 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
|
|
||||||
def _add_registrant_to_existing_domain(self, contact: PublicContact):
|
def _add_registrant_to_existing_domain(self, contact: PublicContact):
|
||||||
"""Used to change the registrant contact on an existing domain"""
|
"""Used to change the registrant contact on an existing domain"""
|
||||||
updateDomain = commands.UpdateDomain(
|
updateDomain = commands.UpdateDomain(name=self.name, registrant=contact.registry_id)
|
||||||
name=self.name, registrant=contact.registry_id
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
registry.send(updateDomain, cleaned=True)
|
registry.send(updateDomain, cleaned=True)
|
||||||
except RegistryError as e:
|
except RegistryError as e:
|
||||||
logger.error(
|
logger.error("Error changing to new registrant error code is %s, error is %s" % (e.code, e))
|
||||||
"Error changing to new registrant error code is %s, error is %s"
|
|
||||||
% (e.code, e)
|
|
||||||
)
|
|
||||||
# TODO-error handling better here?
|
# TODO-error handling better here?
|
||||||
|
|
||||||
def _set_singleton_contact(self, contact: PublicContact, expectedType: str): # noqa
|
def _set_singleton_contact(self, contact: PublicContact, expectedType: str): # noqa
|
||||||
|
@ -800,16 +731,10 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
Will throw error if contact type is not the same as expectType
|
Will throw error if contact type is not the same as expectType
|
||||||
Raises ValueError if expected type doesn't match the contact type"""
|
Raises ValueError if expected type doesn't match the contact type"""
|
||||||
if expectedType != contact.contact_type:
|
if expectedType != contact.contact_type:
|
||||||
raise ValueError(
|
raise ValueError("Cannot set a contact with a different contact type, expected type was %s" % expectedType)
|
||||||
"Cannot set a contact with a different contact type,"
|
|
||||||
" expected type was %s" % expectedType
|
|
||||||
)
|
|
||||||
|
|
||||||
isRegistrant = contact.contact_type == contact.ContactTypeChoices.REGISTRANT
|
isRegistrant = contact.contact_type == contact.ContactTypeChoices.REGISTRANT
|
||||||
isEmptySecurity = (
|
isEmptySecurity = contact.contact_type == contact.ContactTypeChoices.SECURITY and contact.email == ""
|
||||||
contact.contact_type == contact.ContactTypeChoices.SECURITY
|
|
||||||
and contact.email == ""
|
|
||||||
)
|
|
||||||
|
|
||||||
# get publicContact objects that have the matching
|
# get publicContact objects that have the matching
|
||||||
# domain and type but a different id
|
# domain and type but a different id
|
||||||
|
@ -827,10 +752,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
# contact is already added to the domain, but something may have changed on it
|
# contact is already added to the domain, but something may have changed on it
|
||||||
alreadyExistsInRegistry = errorCode == ErrorCode.OBJECT_EXISTS
|
alreadyExistsInRegistry = errorCode == ErrorCode.OBJECT_EXISTS
|
||||||
# if an error occured besides duplication, stop
|
# if an error occured besides duplication, stop
|
||||||
if (
|
if not alreadyExistsInRegistry and errorCode != ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY:
|
||||||
not alreadyExistsInRegistry
|
|
||||||
and errorCode != ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
|
|
||||||
):
|
|
||||||
# TODO- ticket #433 look here for error handling
|
# TODO- ticket #433 look here for error handling
|
||||||
raise RegistryError(code=errorCode)
|
raise RegistryError(code=errorCode)
|
||||||
|
|
||||||
|
@ -839,9 +761,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
|
|
||||||
# if has conflicting contacts in our db remove them
|
# if has conflicting contacts in our db remove them
|
||||||
if hasOtherContact:
|
if hasOtherContact:
|
||||||
logger.info(
|
logger.info("_set_singleton_contact()-> updating domain, removing old contact")
|
||||||
"_set_singleton_contact()-> updating domain, removing old contact"
|
|
||||||
)
|
|
||||||
|
|
||||||
existing_contact = (
|
existing_contact = (
|
||||||
PublicContact.objects.exclude(registry_id=contact.registry_id)
|
PublicContact.objects.exclude(registry_id=contact.registry_id)
|
||||||
|
@ -859,9 +779,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
self._update_domain_with_contact(contact=existing_contact, rem=True)
|
self._update_domain_with_contact(contact=existing_contact, rem=True)
|
||||||
existing_contact.delete()
|
existing_contact.delete()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error(
|
logger.error("Raising error after removing and adding a new contact")
|
||||||
"Raising error after removing and adding a new contact"
|
|
||||||
)
|
|
||||||
raise (err)
|
raise (err)
|
||||||
|
|
||||||
# update domain with contact or update the contact itself
|
# update domain with contact or update the contact itself
|
||||||
|
@ -870,9 +788,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
self._update_domain_with_contact(contact=contact, rem=False)
|
self._update_domain_with_contact(contact=contact, rem=False)
|
||||||
# if already exists just update
|
# if already exists just update
|
||||||
elif alreadyExistsInRegistry:
|
elif alreadyExistsInRegistry:
|
||||||
current_contact = PublicContact.objects.filter(
|
current_contact = PublicContact.objects.filter(registry_id=contact.registry_id).get()
|
||||||
registry_id=contact.registry_id
|
|
||||||
).get()
|
|
||||||
|
|
||||||
if current_contact.email != contact.email:
|
if current_contact.email != contact.email:
|
||||||
self._update_epp_contact(contact=contact)
|
self._update_epp_contact(contact=contact)
|
||||||
|
@ -880,9 +796,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
logger.info("removing security contact and setting default again")
|
logger.info("removing security contact and setting default again")
|
||||||
|
|
||||||
# get the current contact registry id for security
|
# get the current contact registry id for security
|
||||||
current_contact = PublicContact.objects.filter(
|
current_contact = PublicContact.objects.filter(registry_id=contact.registry_id).get()
|
||||||
registry_id=contact.registry_id
|
|
||||||
).get()
|
|
||||||
|
|
||||||
# don't let user delete the default without adding a new email
|
# don't let user delete the default without adding a new email
|
||||||
if current_contact.email != PublicContact.get_default_security().email:
|
if current_contact.email != PublicContact.get_default_security().email:
|
||||||
|
@ -900,9 +814,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
from domain information (not domain application)
|
from domain information (not domain application)
|
||||||
and should have the security email from DomainApplication"""
|
and should have the security email from DomainApplication"""
|
||||||
logger.info("making security contact in registry")
|
logger.info("making security contact in registry")
|
||||||
self._set_singleton_contact(
|
self._set_singleton_contact(contact, expectedType=contact.ContactTypeChoices.SECURITY)
|
||||||
contact, expectedType=contact.ContactTypeChoices.SECURITY
|
|
||||||
)
|
|
||||||
|
|
||||||
@Cache
|
@Cache
|
||||||
def technical_contact(self) -> PublicContact | None:
|
def technical_contact(self) -> PublicContact | None:
|
||||||
|
@ -913,9 +825,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
@technical_contact.setter # type: ignore
|
@technical_contact.setter # type: ignore
|
||||||
def technical_contact(self, contact: PublicContact):
|
def technical_contact(self, contact: PublicContact):
|
||||||
logger.info("making technical contact")
|
logger.info("making technical contact")
|
||||||
self._set_singleton_contact(
|
self._set_singleton_contact(contact, expectedType=contact.ContactTypeChoices.TECHNICAL)
|
||||||
contact, expectedType=contact.ContactTypeChoices.TECHNICAL
|
|
||||||
)
|
|
||||||
|
|
||||||
def is_active(self) -> bool:
|
def is_active(self) -> bool:
|
||||||
"""Currently just returns if the state is created,
|
"""Currently just returns if the state is created,
|
||||||
|
@ -996,17 +906,13 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
|
|
||||||
expiration_date = DateField(
|
expiration_date = DateField(
|
||||||
null=True,
|
null=True,
|
||||||
help_text=(
|
help_text=("Duplication of registry's expiration date saved for ease of reporting"),
|
||||||
"Duplication of registry's expiration" "date saved for ease of reporting"
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def isActive(self):
|
def isActive(self):
|
||||||
return self.state == Domain.State.CREATED
|
return self.state == Domain.State.CREATED
|
||||||
|
|
||||||
def map_epp_contact_to_public_contact(
|
def map_epp_contact_to_public_contact(self, contact: eppInfo.InfoContactResultData, contact_id, contact_type):
|
||||||
self, contact: eppInfo.InfoContactResultData, contact_id, contact_type
|
|
||||||
):
|
|
||||||
"""Maps the Epp contact representation to a PublicContact object.
|
"""Maps the Epp contact representation to a PublicContact object.
|
||||||
|
|
||||||
contact -> eppInfo.InfoContactResultData: The converted contact object
|
contact -> eppInfo.InfoContactResultData: The converted contact object
|
||||||
|
@ -1028,10 +934,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
# Since contact_id is registry_id,
|
# Since contact_id is registry_id,
|
||||||
# check that its the right length
|
# check that its the right length
|
||||||
contact_id_length = len(contact_id)
|
contact_id_length = len(contact_id)
|
||||||
if (
|
if contact_id_length > PublicContact.get_max_id_length() or contact_id_length < 1:
|
||||||
contact_id_length > PublicContact.get_max_id_length()
|
|
||||||
or contact_id_length < 1
|
|
||||||
):
|
|
||||||
raise ContactError(code=ContactErrorCodes.CONTACT_ID_INVALID_LENGTH)
|
raise ContactError(code=ContactErrorCodes.CONTACT_ID_INVALID_LENGTH)
|
||||||
|
|
||||||
if not isinstance(contact, eppInfo.InfoContactResultData):
|
if not isinstance(contact, eppInfo.InfoContactResultData):
|
||||||
|
@ -1114,9 +1017,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
)
|
)
|
||||||
raise error
|
raise error
|
||||||
|
|
||||||
def generic_contact_getter(
|
def generic_contact_getter(self, contact_type_choice: PublicContact.ContactTypeChoices) -> PublicContact | None:
|
||||||
self, contact_type_choice: PublicContact.ContactTypeChoices
|
|
||||||
) -> PublicContact | None:
|
|
||||||
"""Retrieves the desired PublicContact from the registry.
|
"""Retrieves the desired PublicContact from the registry.
|
||||||
This abstracts the caching and EPP retrieval for
|
This abstracts the caching and EPP retrieval for
|
||||||
all contact items and thus may result in EPP calls being sent.
|
all contact items and thus may result in EPP calls being sent.
|
||||||
|
@ -1187,9 +1088,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
if contact_type == PublicContact.ContactTypeChoices.REGISTRANT:
|
if contact_type == PublicContact.ContactTypeChoices.REGISTRANT:
|
||||||
desired_contact = None
|
desired_contact = None
|
||||||
if isinstance(contacts, str):
|
if isinstance(contacts, str):
|
||||||
desired_contact = self._registrant_to_public_contact(
|
desired_contact = self._registrant_to_public_contact(self._cache["registrant"])
|
||||||
self._cache["registrant"]
|
|
||||||
)
|
|
||||||
# Set the cache with the updated object
|
# Set the cache with the updated object
|
||||||
# for performance reasons.
|
# for performance reasons.
|
||||||
if "registrant" in self._cache:
|
if "registrant" in self._cache:
|
||||||
|
@ -1203,9 +1102,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
if contacts is not None and contact_type in contacts:
|
if contacts is not None and contact_type in contacts:
|
||||||
_registry_id = contacts.get(contact_type)
|
_registry_id = contacts.get(contact_type)
|
||||||
|
|
||||||
desired = PublicContact.objects.filter(
|
desired = PublicContact.objects.filter(registry_id=_registry_id, domain=self, contact_type=contact_type)
|
||||||
registry_id=_registry_id, domain=self, contact_type=contact_type
|
|
||||||
)
|
|
||||||
|
|
||||||
if desired.count() == 1:
|
if desired.count() == 1:
|
||||||
return desired.get()
|
return desired.get()
|
||||||
|
@ -1214,10 +1111,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _handle_registrant_contact(self, contact):
|
def _handle_registrant_contact(self, contact):
|
||||||
if (
|
if contact.contact_type is not None and contact.contact_type == PublicContact.ContactTypeChoices.REGISTRANT:
|
||||||
contact.contact_type is not None
|
|
||||||
and contact.contact_type == PublicContact.ContactTypeChoices.REGISTRANT
|
|
||||||
):
|
|
||||||
return contact
|
return contact
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid contact object for registrant_contact")
|
raise ValueError("Invalid contact object for registrant_contact")
|
||||||
|
@ -1297,9 +1191,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
administrative_contact = self.get_default_administrative_contact()
|
administrative_contact = self.get_default_administrative_contact()
|
||||||
administrative_contact.save()
|
administrative_contact.save()
|
||||||
|
|
||||||
@transition(
|
@transition(field="state", source=[State.READY, State.ON_HOLD], target=State.ON_HOLD)
|
||||||
field="state", source=[State.READY, State.ON_HOLD], target=State.ON_HOLD
|
|
||||||
)
|
|
||||||
def place_client_hold(self, ignoreEPP=False):
|
def place_client_hold(self, ignoreEPP=False):
|
||||||
"""place a clienthold on a domain (no longer should resolve)
|
"""place a clienthold on a domain (no longer should resolve)
|
||||||
ignoreEPP (boolean) - set to true to by-pass EPP (used for transition domains)
|
ignoreEPP (boolean) - set to true to by-pass EPP (used for transition domains)
|
||||||
|
@ -1325,9 +1217,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
self._remove_client_hold()
|
self._remove_client_hold()
|
||||||
# TODO -on the client hold ticket any additional error handling here
|
# TODO -on the client hold ticket any additional error handling here
|
||||||
|
|
||||||
@transition(
|
@transition(field="state", source=[State.ON_HOLD, State.DNS_NEEDED], target=State.DELETED)
|
||||||
field="state", source=[State.ON_HOLD, State.DNS_NEEDED], target=State.DELETED
|
|
||||||
)
|
|
||||||
def deletedInEpp(self):
|
def deletedInEpp(self):
|
||||||
"""Domain is deleted in epp but is saved in our database.
|
"""Domain is deleted in epp but is saved in our database.
|
||||||
Error handling should be provided by the caller."""
|
Error handling should be provided by the caller."""
|
||||||
|
@ -1345,9 +1235,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
logger.error("Could not delete domain. FSM failure: {err}")
|
logger.error("Could not delete domain. FSM failure: {err}")
|
||||||
raise err
|
raise err
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error(
|
logger.error(f"Could not delete domain. An unspecified error occured: {err}")
|
||||||
f"Could not delete domain. An unspecified error occured: {err}"
|
|
||||||
)
|
|
||||||
raise err
|
raise err
|
||||||
else:
|
else:
|
||||||
self._invalidate_cache()
|
self._invalidate_cache()
|
||||||
|
@ -1407,9 +1295,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
is_security = contact.contact_type == contact.ContactTypeChoices.SECURITY
|
is_security = contact.contact_type == contact.ContactTypeChoices.SECURITY
|
||||||
DF = epp.DiscloseField
|
DF = epp.DiscloseField
|
||||||
fields = {DF.EMAIL}
|
fields = {DF.EMAIL}
|
||||||
disclose = (
|
disclose = is_security and contact.email != PublicContact.get_default_security().email
|
||||||
is_security and contact.email != PublicContact.get_default_security().email
|
|
||||||
)
|
|
||||||
# Will only disclose DF.EMAIL if its not the default
|
# Will only disclose DF.EMAIL if its not the default
|
||||||
return epp.Disclose(
|
return epp.Disclose(
|
||||||
flag=disclose,
|
flag=disclose,
|
||||||
|
@ -1421,9 +1307,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
name=contact.name,
|
name=contact.name,
|
||||||
addr=epp.ContactAddr(
|
addr=epp.ContactAddr(
|
||||||
street=[
|
street=[
|
||||||
getattr(contact, street)
|
getattr(contact, street) for street in ["street1", "street2", "street3"] if hasattr(contact, street)
|
||||||
for street in ["street1", "street2", "street3"]
|
|
||||||
if hasattr(contact, street)
|
|
||||||
], # type: ignore
|
], # type: ignore
|
||||||
city=contact.city,
|
city=contact.city,
|
||||||
pc=contact.pc,
|
pc=contact.pc,
|
||||||
|
@ -1488,9 +1372,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
data = registry.send(req, cleaned=True).res_data[0]
|
data = registry.send(req, cleaned=True).res_data[0]
|
||||||
|
|
||||||
# Map the object we recieved from EPP to a PublicContact
|
# Map the object we recieved from EPP to a PublicContact
|
||||||
mapped_object = self.map_epp_contact_to_public_contact(
|
mapped_object = self.map_epp_contact_to_public_contact(data, domainContact.contact, domainContact.type)
|
||||||
data, domainContact.contact, domainContact.type
|
|
||||||
)
|
|
||||||
|
|
||||||
# Find/create it in the DB
|
# Find/create it in the DB
|
||||||
in_db = self._get_or_create_public_contact(mapped_object)
|
in_db = self._get_or_create_public_contact(mapped_object)
|
||||||
|
@ -1503,9 +1385,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
return self._request_contact_info(contact)
|
return self._request_contact_info(contact)
|
||||||
except RegistryError as e:
|
except RegistryError as e:
|
||||||
if e.code == ErrorCode.OBJECT_DOES_NOT_EXIST:
|
if e.code == ErrorCode.OBJECT_DOES_NOT_EXIST:
|
||||||
logger.info(
|
logger.info("_get_or_create_contact()-> contact doesn't exist so making it")
|
||||||
"_get_or_create_contact()-> contact doesn't exist so making it"
|
|
||||||
)
|
|
||||||
contact.domain = self
|
contact.domain = self
|
||||||
contact.save() # this will call the function based on type of contact
|
contact.save() # this will call the function based on type of contact
|
||||||
return self._request_contact_info(contact=contact)
|
return self._request_contact_info(contact=contact)
|
||||||
|
@ -1560,9 +1440,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
for ip_addr in ip_list:
|
for ip_addr in ip_list:
|
||||||
edited_ip_list.append(
|
edited_ip_list.append(epp.Ip(addr=ip_addr, ip="v6" if self.is_ipv6(ip_addr) else None))
|
||||||
epp.Ip(addr=ip_addr, ip="v6" if self.is_ipv6(ip_addr) else None)
|
|
||||||
)
|
|
||||||
|
|
||||||
return edited_ip_list
|
return edited_ip_list
|
||||||
|
|
||||||
|
@ -1579,12 +1457,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if (
|
if ip_list is None or len(ip_list) == 0 and isinstance(old_ip_list, list) and len(old_ip_list) != 0:
|
||||||
ip_list is None
|
|
||||||
or len(ip_list) == 0
|
|
||||||
and isinstance(old_ip_list, list)
|
|
||||||
and len(old_ip_list) != 0
|
|
||||||
):
|
|
||||||
return ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
|
return ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
|
||||||
|
|
||||||
added_ip_list = set(ip_list).difference(old_ip_list)
|
added_ip_list = set(ip_list).difference(old_ip_list)
|
||||||
|
@ -1607,9 +1480,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
def addAndRemoveHostsFromDomain(
|
def addAndRemoveHostsFromDomain(self, hostsToAdd: list[str], hostsToDelete: list[str]):
|
||||||
self, hostsToAdd: list[str], hostsToDelete: list[str]
|
|
||||||
):
|
|
||||||
"""sends an UpdateDomain message to the registry with the hosts provided
|
"""sends an UpdateDomain message to the registry with the hosts provided
|
||||||
Args:
|
Args:
|
||||||
hostsToDelete (list[epp.HostObjSet])- list of host objects to delete
|
hostsToDelete (list[epp.HostObjSet])- list of host objects to delete
|
||||||
|
@ -1624,22 +1495,14 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
return ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
|
return ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
|
||||||
|
|
||||||
try:
|
try:
|
||||||
updateReq = commands.UpdateDomain(
|
updateReq = commands.UpdateDomain(name=self.name, rem=hostsToDelete, add=hostsToAdd)
|
||||||
name=self.name, rem=hostsToDelete, add=hostsToAdd
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(
|
logger.info("addAndRemoveHostsFromDomain()-> sending update domain req as %s" % updateReq)
|
||||||
"addAndRemoveHostsFromDomain()-> sending update domain req as %s"
|
|
||||||
% updateReq
|
|
||||||
)
|
|
||||||
response = registry.send(updateReq, cleaned=True)
|
response = registry.send(updateReq, cleaned=True)
|
||||||
|
|
||||||
return response.code
|
return response.code
|
||||||
except RegistryError as e:
|
except RegistryError as e:
|
||||||
logger.error(
|
logger.error("Error addAndRemoveHostsFromDomain, code was %s error was %s" % (e.code, e))
|
||||||
"Error addAndRemoveHostsFromDomain, code was %s error was %s"
|
|
||||||
% (e.code, e)
|
|
||||||
)
|
|
||||||
return e.code
|
return e.code
|
||||||
|
|
||||||
def _delete_hosts_if_not_used(self, hostsToDelete: list[str]):
|
def _delete_hosts_if_not_used(self, hostsToDelete: list[str]):
|
||||||
|
@ -1657,22 +1520,13 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
for nameserver in hostsToDelete:
|
for nameserver in hostsToDelete:
|
||||||
deleteHostReq = commands.DeleteHost(name=nameserver)
|
deleteHostReq = commands.DeleteHost(name=nameserver)
|
||||||
registry.send(deleteHostReq, cleaned=True)
|
registry.send(deleteHostReq, cleaned=True)
|
||||||
logger.info(
|
logger.info("_delete_hosts_if_not_used()-> sending delete host req as %s" % deleteHostReq)
|
||||||
"_delete_hosts_if_not_used()-> sending delete host req as %s"
|
|
||||||
% deleteHostReq
|
|
||||||
)
|
|
||||||
|
|
||||||
except RegistryError as e:
|
except RegistryError as e:
|
||||||
if e.code == ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION:
|
if e.code == ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION:
|
||||||
logger.info(
|
logger.info("Did not remove host %s because it is in use on another domain." % nameserver)
|
||||||
"Did not remove host %s because it is in use on another domain."
|
|
||||||
% nameserver
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error("Error _delete_hosts_if_not_used, code was %s error was %s" % (e.code, e))
|
||||||
"Error _delete_hosts_if_not_used, code was %s error was %s"
|
|
||||||
% (e.code, e)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _fetch_cache(self, fetch_hosts=False, fetch_contacts=False):
|
def _fetch_cache(self, fetch_hosts=False, fetch_contacts=False):
|
||||||
"""Contact registry for info about a domain."""
|
"""Contact registry for info about a domain."""
|
||||||
|
@ -1768,9 +1622,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
# Raise an error if we find duplicates.
|
# Raise an error if we find duplicates.
|
||||||
# This should not occur
|
# This should not occur
|
||||||
if db_contact.count() > 1:
|
if db_contact.count() > 1:
|
||||||
raise Exception(
|
raise Exception(f"Multiple contacts found for {public_contact.contact_type}")
|
||||||
f"Multiple contacts found for {public_contact.contact_type}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Save to DB if it doesn't exist already.
|
# Save to DB if it doesn't exist already.
|
||||||
if db_contact.count() == 0:
|
if db_contact.count() == 0:
|
||||||
|
@ -1784,10 +1636,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
|
|
||||||
# Does the item we're grabbing match
|
# Does the item we're grabbing match
|
||||||
# what we have in our DB?
|
# what we have in our DB?
|
||||||
if (
|
if existing_contact.email != public_contact.email or existing_contact.registry_id != public_contact.registry_id:
|
||||||
existing_contact.email != public_contact.email
|
|
||||||
or existing_contact.registry_id != public_contact.registry_id
|
|
||||||
):
|
|
||||||
existing_contact.delete()
|
existing_contact.delete()
|
||||||
public_contact.save()
|
public_contact.save()
|
||||||
logger.warning("Requested PublicContact is out of sync " "with DB.")
|
logger.warning("Requested PublicContact is out of sync " "with DB.")
|
||||||
|
@ -1809,9 +1658,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
# Grabs the expanded contact
|
# Grabs the expanded contact
|
||||||
full_object = self._request_contact_info(contact)
|
full_object = self._request_contact_info(contact)
|
||||||
# Maps it to type PublicContact
|
# Maps it to type PublicContact
|
||||||
mapped_object = self.map_epp_contact_to_public_contact(
|
mapped_object = self.map_epp_contact_to_public_contact(full_object, contact.registry_id, contact.contact_type)
|
||||||
full_object, contact.registry_id, contact.contact_type
|
|
||||||
)
|
|
||||||
return self._get_or_create_public_contact(mapped_object)
|
return self._get_or_create_public_contact(mapped_object)
|
||||||
|
|
||||||
def _invalidate_cache(self):
|
def _invalidate_cache(self):
|
||||||
|
@ -1829,6 +1676,4 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
if property in self._cache:
|
if property in self._cache:
|
||||||
return self._cache[property]
|
return self._cache[property]
|
||||||
else:
|
else:
|
||||||
raise KeyError(
|
raise KeyError("Requested key %s was not found in registry cache." % str(property))
|
||||||
"Requested key %s was not found in registry cache." % str(property)
|
|
||||||
)
|
|
||||||
|
|
|
@ -131,8 +131,7 @@ class DomainApplication(TimeStampedModel):
|
||||||
|
|
||||||
FEDERAL = (
|
FEDERAL = (
|
||||||
"federal",
|
"federal",
|
||||||
"Federal: an agency of the U.S. government's executive, "
|
"Federal: an agency of the U.S. government's executive, legislative, or judicial branches",
|
||||||
"legislative, or judicial branches",
|
|
||||||
)
|
)
|
||||||
INTERSTATE = "interstate", "Interstate: an organization of two or more states"
|
INTERSTATE = "interstate", "Interstate: an organization of two or more states"
|
||||||
STATE_OR_TERRITORY = (
|
STATE_OR_TERRITORY = (
|
||||||
|
@ -143,8 +142,7 @@ class DomainApplication(TimeStampedModel):
|
||||||
)
|
)
|
||||||
TRIBAL = (
|
TRIBAL = (
|
||||||
"tribal",
|
"tribal",
|
||||||
"Tribal: a tribal government recognized by the federal or a state "
|
"Tribal: a tribal government recognized by the federal or a state government",
|
||||||
"government",
|
|
||||||
)
|
)
|
||||||
COUNTY = "county", "County: a county, parish, or borough"
|
COUNTY = "county", "County: a county, parish, or borough"
|
||||||
CITY = "city", "City: a city, town, township, village, etc."
|
CITY = "city", "City: a city, town, township, village, etc."
|
||||||
|
@ -154,8 +152,7 @@ class DomainApplication(TimeStampedModel):
|
||||||
)
|
)
|
||||||
SCHOOL_DISTRICT = (
|
SCHOOL_DISTRICT = (
|
||||||
"school_district",
|
"school_district",
|
||||||
"School district: a school district that is not part of a local "
|
"School district: a school district that is not part of a local government",
|
||||||
"government",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class BranchChoices(models.TextChoices):
|
class BranchChoices(models.TextChoices):
|
||||||
|
@ -168,10 +165,7 @@ class DomainApplication(TimeStampedModel):
|
||||||
"Advisory Council on Historic Preservation",
|
"Advisory Council on Historic Preservation",
|
||||||
"American Battle Monuments Commission",
|
"American Battle Monuments Commission",
|
||||||
"Appalachian Regional Commission",
|
"Appalachian Regional Commission",
|
||||||
(
|
("Appraisal Subcommittee of the Federal Financial Institutions Examination Council"),
|
||||||
"Appraisal Subcommittee of the Federal Financial "
|
|
||||||
"Institutions Examination Council"
|
|
||||||
),
|
|
||||||
"Armed Forces Retirement Home",
|
"Armed Forces Retirement Home",
|
||||||
"Barry Goldwater Scholarship and Excellence in Education Program",
|
"Barry Goldwater Scholarship and Excellence in Education Program",
|
||||||
"Central Intelligence Agency",
|
"Central Intelligence Agency",
|
||||||
|
@ -507,9 +501,7 @@ class DomainApplication(TimeStampedModel):
|
||||||
return not self.approved_domain.is_active()
|
return not self.approved_domain.is_active()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _send_status_update_email(
|
def _send_status_update_email(self, new_status, email_template, email_template_subject):
|
||||||
self, new_status, email_template, email_template_subject
|
|
||||||
):
|
|
||||||
"""Send a atatus update email to the submitter.
|
"""Send a atatus update email to the submitter.
|
||||||
|
|
||||||
The email goes to the email address that the submitter gave as their
|
The email goes to the email address that the submitter gave as their
|
||||||
|
@ -518,9 +510,7 @@ class DomainApplication(TimeStampedModel):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.submitter is None or self.submitter.email is None:
|
if self.submitter is None or self.submitter.email is None:
|
||||||
logger.warning(
|
logger.warning(f"Cannot send {new_status} email, no submitter email address.")
|
||||||
f"Cannot send {new_status} email, no submitter email address."
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
send_templated_email(
|
send_templated_email(
|
||||||
|
@ -533,9 +523,7 @@ class DomainApplication(TimeStampedModel):
|
||||||
except EmailSendingError:
|
except EmailSendingError:
|
||||||
logger.warning("Failed to send confirmation email", exc_info=True)
|
logger.warning("Failed to send confirmation email", exc_info=True)
|
||||||
|
|
||||||
@transition(
|
@transition(field="status", source=[STARTED, ACTION_NEEDED, WITHDRAWN], target=SUBMITTED)
|
||||||
field="status", source=[STARTED, ACTION_NEEDED, WITHDRAWN], target=SUBMITTED
|
|
||||||
)
|
|
||||||
def submit(self):
|
def submit(self):
|
||||||
"""Submit an application that is started.
|
"""Submit an application that is started.
|
||||||
|
|
||||||
|
|
|
@ -57,9 +57,7 @@ class DomainInvitation(TimeStampedModel):
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
# should not happen because a matching user should exist before
|
# should not happen because a matching user should exist before
|
||||||
# we retrieve this invitation
|
# we retrieve this invitation
|
||||||
raise RuntimeError(
|
raise RuntimeError("Cannot find the user to retrieve this domain invitation.")
|
||||||
"Cannot find the user to retrieve this domain invitation."
|
|
||||||
)
|
|
||||||
|
|
||||||
# and create a role for that user on this domain
|
# and create a role for that user on this domain
|
||||||
_, created = UserDomainRole.objects.get_or_create(
|
_, created = UserDomainRole.objects.get_or_create(
|
||||||
|
@ -68,6 +66,4 @@ class DomainInvitation(TimeStampedModel):
|
||||||
if not created:
|
if not created:
|
||||||
# something strange happened and this role already existed when
|
# something strange happened and this role already existed when
|
||||||
# the invitation was retrieved. Log that this occurred.
|
# the invitation was retrieved. Log that this occurred.
|
||||||
logger.warn(
|
logger.warn("Invitation %s was retrieved for a role that already exists.", self)
|
||||||
"Invitation %s was retrieved for a role that already exists.", self
|
|
||||||
)
|
|
||||||
|
|
|
@ -10,9 +10,7 @@ from .utility.time_stamped_model import TimeStampedModel
|
||||||
def get_id():
|
def get_id():
|
||||||
"""Generate a 16 character registry ID with a low probability of collision."""
|
"""Generate a 16 character registry ID with a low probability of collision."""
|
||||||
day = datetime.today().strftime("%A")[:2]
|
day = datetime.today().strftime("%A")[:2]
|
||||||
rand = "".join(
|
rand = "".join(choices(ascii_uppercase + ascii_lowercase + digits, k=14)) # nosec B311
|
||||||
choices(ascii_uppercase + ascii_lowercase + digits, k=14) # nosec B311
|
|
||||||
)
|
|
||||||
return f"{day}{rand}"
|
return f"{day}{rand}"
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,16 +67,12 @@ class PublicContact(TimeStampedModel):
|
||||||
pc = models.TextField(null=False, help_text="Contact's postal code")
|
pc = models.TextField(null=False, help_text="Contact's postal code")
|
||||||
cc = models.TextField(null=False, help_text="Contact's country code")
|
cc = models.TextField(null=False, help_text="Contact's country code")
|
||||||
email = models.TextField(null=False, help_text="Contact's email address")
|
email = models.TextField(null=False, help_text="Contact's email address")
|
||||||
voice = models.TextField(
|
voice = models.TextField(null=False, help_text="Contact's phone number. Must be in ITU.E164.2005 format")
|
||||||
null=False, help_text="Contact's phone number. Must be in ITU.E164.2005 format"
|
|
||||||
)
|
|
||||||
fax = models.TextField(
|
fax = models.TextField(
|
||||||
null=True,
|
null=True,
|
||||||
help_text="Contact's fax number (null ok). Must be in ITU.E164.2005 format.",
|
help_text="Contact's fax number (null ok). Must be in ITU.E164.2005 format.",
|
||||||
)
|
)
|
||||||
pw = models.TextField(
|
pw = models.TextField(null=False, help_text="Contact's authorization code. 16 characters minimum.")
|
||||||
null=False, help_text="Contact's authorization code. 16 characters minimum."
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_default_registrant(cls):
|
def get_default_registrant(cls):
|
||||||
|
@ -154,8 +148,4 @@ class PublicContact(TimeStampedModel):
|
||||||
return cls._meta.get_field("registry_id").max_length
|
return cls._meta.get_field("registry_id").max_length
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return f"{self.name} <{self.email}>" f"id: {self.registry_id} " f"type: {self.contact_type}"
|
||||||
f"{self.name} <{self.email}>"
|
|
||||||
f"id: {self.registry_id} "
|
|
||||||
f"type: {self.contact_type}"
|
|
||||||
)
|
|
||||||
|
|
|
@ -68,9 +68,7 @@ class User(AbstractUser):
|
||||||
def check_domain_invitations_on_login(self):
|
def check_domain_invitations_on_login(self):
|
||||||
"""When a user first arrives on the site, we need to retrieve any domain
|
"""When a user first arrives on the site, we need to retrieve any domain
|
||||||
invitations that match their email address."""
|
invitations that match their email address."""
|
||||||
for invitation in DomainInvitation.objects.filter(
|
for invitation in DomainInvitation.objects.filter(email=self.email, status=DomainInvitation.INVITED):
|
||||||
email=self.email, status=DomainInvitation.INVITED
|
|
||||||
):
|
|
||||||
try:
|
try:
|
||||||
invitation.retrieve()
|
invitation.retrieve()
|
||||||
invitation.save()
|
invitation.save()
|
||||||
|
@ -78,9 +76,7 @@ class User(AbstractUser):
|
||||||
# retrieving should not fail because of a missing user, but
|
# retrieving should not fail because of a missing user, but
|
||||||
# if it does fail, log the error so a new user can continue
|
# if it does fail, log the error so a new user can continue
|
||||||
# logging in
|
# logging in
|
||||||
logger.warn(
|
logger.warn("Failed to retrieve invitation %s", invitation, exc_info=True)
|
||||||
"Failed to retrieve invitation %s", invitation, exc_info=True
|
|
||||||
)
|
|
||||||
|
|
||||||
def create_domain_and_invite(self, transition_domain: TransitionDomain):
|
def create_domain_and_invite(self, transition_domain: TransitionDomain):
|
||||||
transition_domain_name = transition_domain.domain_name
|
transition_domain_name = transition_domain.domain_name
|
||||||
|
@ -89,9 +85,7 @@ class User(AbstractUser):
|
||||||
|
|
||||||
# type safety check. name should never be none
|
# type safety check. name should never be none
|
||||||
if transition_domain_name is not None:
|
if transition_domain_name is not None:
|
||||||
new_domain = Domain(
|
new_domain = Domain(name=transition_domain_name, state=transition_domain_status)
|
||||||
name=transition_domain_name, state=transition_domain_status
|
|
||||||
)
|
|
||||||
new_domain.save()
|
new_domain.save()
|
||||||
# check that a domain invitation doesn't already
|
# check that a domain invitation doesn't already
|
||||||
# exist for this e-mail / Domain pair
|
# exist for this e-mail / Domain pair
|
||||||
|
@ -100,9 +94,7 @@ class User(AbstractUser):
|
||||||
).exists()
|
).exists()
|
||||||
if not domain_email_already_in_domain_invites:
|
if not domain_email_already_in_domain_invites:
|
||||||
# Create new domain invitation
|
# Create new domain invitation
|
||||||
new_domain_invitation = DomainInvitation(
|
new_domain_invitation = DomainInvitation(email=transition_domain_email.lower(), domain=new_domain)
|
||||||
email=transition_domain_email.lower(), domain=new_domain
|
|
||||||
)
|
|
||||||
new_domain_invitation.save()
|
new_domain_invitation.save()
|
||||||
|
|
||||||
def check_transition_domains_on_login(self):
|
def check_transition_domains_on_login(self):
|
||||||
|
@ -129,9 +121,7 @@ class User(AbstractUser):
|
||||||
# with our data and migrations need to be run again.
|
# with our data and migrations need to be run again.
|
||||||
|
|
||||||
# Get the domain that corresponds with this transition domain
|
# Get the domain that corresponds with this transition domain
|
||||||
domain_exists = Domain.objects.filter(
|
domain_exists = Domain.objects.filter(name=transition_domain.domain_name).exists()
|
||||||
name=transition_domain.domain_name
|
|
||||||
).exists()
|
|
||||||
if not domain_exists:
|
if not domain_exists:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"""There are transition domains without
|
"""There are transition domains without
|
||||||
|
@ -147,9 +137,7 @@ class User(AbstractUser):
|
||||||
|
|
||||||
# Create a domain information object, if one doesn't
|
# Create a domain information object, if one doesn't
|
||||||
# already exist
|
# already exist
|
||||||
domain_info_exists = DomainInformation.objects.filter(
|
domain_info_exists = DomainInformation.objects.filter(domain=domain).exists()
|
||||||
domain=domain
|
|
||||||
).exists()
|
|
||||||
if not domain_info_exists:
|
if not domain_info_exists:
|
||||||
new_domain_info = DomainInformation(creator=self, domain=domain)
|
new_domain_info = DomainInformation(creator=self, domain=domain)
|
||||||
new_domain_info.save()
|
new_domain_info.save()
|
||||||
|
|
|
@ -44,7 +44,5 @@ class UserDomainRole(TimeStampedModel):
|
||||||
constraints = [
|
constraints = [
|
||||||
# a user can have only one role on a given domain, that is, there can
|
# a user can have only one role on a given domain, that is, there can
|
||||||
# be only a single row with a certain (user, domain) pair.
|
# be only a single row with a certain (user, domain) pair.
|
||||||
models.UniqueConstraint(
|
models.UniqueConstraint(fields=["user", "domain"], name="unique_user_domain_role")
|
||||||
fields=["user", "domain"], name="unique_user_domain_role"
|
|
||||||
)
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -87,14 +87,10 @@ class UserGroup(Group):
|
||||||
permissions = permission["permissions"]
|
permissions = permission["permissions"]
|
||||||
|
|
||||||
# Retrieve the content type for the app and model
|
# Retrieve the content type for the app and model
|
||||||
content_type = ContentType.objects.get(
|
content_type = ContentType.objects.get(app_label=app_label, model=model_name)
|
||||||
app_label=app_label, model=model_name
|
|
||||||
)
|
|
||||||
|
|
||||||
# Retrieve the permissions based on their codenames
|
# Retrieve the permissions based on their codenames
|
||||||
permissions = Permission.objects.filter(
|
permissions = Permission.objects.filter(content_type=content_type, codename__in=permissions)
|
||||||
content_type=content_type, codename__in=permissions
|
|
||||||
)
|
|
||||||
|
|
||||||
# Assign the permissions to the group
|
# Assign the permissions to the group
|
||||||
cisa_analysts_group.permissions.add(*permissions)
|
cisa_analysts_group.permissions.add(*permissions)
|
||||||
|
@ -113,9 +109,7 @@ class UserGroup(Group):
|
||||||
)
|
)
|
||||||
|
|
||||||
cisa_analysts_group.save()
|
cisa_analysts_group.save()
|
||||||
logger.debug(
|
logger.debug("CISA Analyt permissions added to group " + cisa_analysts_group.name)
|
||||||
"CISA Analyt permissions added to group " + cisa_analysts_group.name
|
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error creating analyst permissions group: {e}")
|
logger.error(f"Error creating analyst permissions group: {e}")
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,7 @@ def contains_checkbox(html_list):
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def get_organization_long_name(organization_type):
|
def get_organization_long_name(organization_type):
|
||||||
organization_choices_dict = dict(
|
organization_choices_dict = dict(DomainApplication.OrganizationChoicesVerbose.choices)
|
||||||
DomainApplication.OrganizationChoicesVerbose.choices
|
|
||||||
)
|
|
||||||
long_form_type = organization_choices_dict[organization_type]
|
long_form_type = organization_choices_dict[organization_type]
|
||||||
if long_form_type is None:
|
if long_form_type is None:
|
||||||
logger.error("Organization type error, triggered by a template's custom filter")
|
logger.error("Organization type error, triggered by a template's custom filter")
|
||||||
|
|
|
@ -317,9 +317,7 @@ class AuditedAdminMockData:
|
||||||
of either DomainApplication, DomainInvitation, or DomainInformation
|
of either DomainApplication, DomainInvitation, or DomainInformation
|
||||||
based on the 'domain_type' field.
|
based on the 'domain_type' field.
|
||||||
""" # noqa
|
""" # noqa
|
||||||
common_args = self.get_common_domain_arg_dictionary(
|
common_args = self.get_common_domain_arg_dictionary(item_name, org_type, federal_type, purpose)
|
||||||
item_name, org_type, federal_type, purpose
|
|
||||||
)
|
|
||||||
full_arg_dict = None
|
full_arg_dict = None
|
||||||
match domain_type:
|
match domain_type:
|
||||||
case self.APPLICATION:
|
case self.APPLICATION:
|
||||||
|
@ -344,40 +342,22 @@ class AuditedAdminMockData:
|
||||||
)
|
)
|
||||||
return full_arg_dict
|
return full_arg_dict
|
||||||
|
|
||||||
def create_full_dummy_domain_application(
|
def create_full_dummy_domain_application(self, item_name, status=DomainApplication.STARTED):
|
||||||
self, item_name, status=DomainApplication.STARTED
|
|
||||||
):
|
|
||||||
"""Creates a dummy domain application object"""
|
"""Creates a dummy domain application object"""
|
||||||
domain_application_kwargs = self.dummy_kwarg_boilerplate(
|
domain_application_kwargs = self.dummy_kwarg_boilerplate(self.APPLICATION, item_name, status)
|
||||||
self.APPLICATION, item_name, status
|
application = DomainApplication.objects.get_or_create(**domain_application_kwargs)[0]
|
||||||
)
|
|
||||||
application = DomainApplication.objects.get_or_create(
|
|
||||||
**domain_application_kwargs
|
|
||||||
)[0]
|
|
||||||
return application
|
return application
|
||||||
|
|
||||||
def create_full_dummy_domain_information(
|
def create_full_dummy_domain_information(self, item_name, status=DomainApplication.STARTED):
|
||||||
self, item_name, status=DomainApplication.STARTED
|
|
||||||
):
|
|
||||||
"""Creates a dummy domain information object"""
|
"""Creates a dummy domain information object"""
|
||||||
domain_application_kwargs = self.dummy_kwarg_boilerplate(
|
domain_application_kwargs = self.dummy_kwarg_boilerplate(self.INFORMATION, item_name, status)
|
||||||
self.INFORMATION, item_name, status
|
application = DomainInformation.objects.get_or_create(**domain_application_kwargs)[0]
|
||||||
)
|
|
||||||
application = DomainInformation.objects.get_or_create(
|
|
||||||
**domain_application_kwargs
|
|
||||||
)[0]
|
|
||||||
return application
|
return application
|
||||||
|
|
||||||
def create_full_dummy_domain_invitation(
|
def create_full_dummy_domain_invitation(self, item_name, status=DomainApplication.STARTED):
|
||||||
self, item_name, status=DomainApplication.STARTED
|
|
||||||
):
|
|
||||||
"""Creates a dummy domain invitation object"""
|
"""Creates a dummy domain invitation object"""
|
||||||
domain_application_kwargs = self.dummy_kwarg_boilerplate(
|
domain_application_kwargs = self.dummy_kwarg_boilerplate(self.INVITATION, item_name, status)
|
||||||
self.INVITATION, item_name, status
|
application = DomainInvitation.objects.get_or_create(**domain_application_kwargs)[0]
|
||||||
)
|
|
||||||
application = DomainInvitation.objects.get_or_create(
|
|
||||||
**domain_application_kwargs
|
|
||||||
)[0]
|
|
||||||
|
|
||||||
return application
|
return application
|
||||||
|
|
||||||
|
@ -394,17 +374,11 @@ class AuditedAdminMockData:
|
||||||
application = None
|
application = None
|
||||||
match domain_type:
|
match domain_type:
|
||||||
case self.APPLICATION:
|
case self.APPLICATION:
|
||||||
application = self.create_full_dummy_domain_application(
|
application = self.create_full_dummy_domain_application(item_name, status)
|
||||||
item_name, status
|
|
||||||
)
|
|
||||||
case self.INVITATION:
|
case self.INVITATION:
|
||||||
application = self.create_full_dummy_domain_invitation(
|
application = self.create_full_dummy_domain_invitation(item_name, status)
|
||||||
item_name, status
|
|
||||||
)
|
|
||||||
case self.INFORMATION:
|
case self.INFORMATION:
|
||||||
application = self.create_full_dummy_domain_information(
|
application = self.create_full_dummy_domain_information(item_name, status)
|
||||||
item_name, status
|
|
||||||
)
|
|
||||||
case _:
|
case _:
|
||||||
raise ValueError("Invalid domain_type, must conform to given constants")
|
raise ValueError("Invalid domain_type, must conform to given constants")
|
||||||
|
|
||||||
|
@ -527,9 +501,7 @@ def completed_application(
|
||||||
if has_anything_else:
|
if has_anything_else:
|
||||||
domain_application_kwargs["anything_else"] = "There is more"
|
domain_application_kwargs["anything_else"] = "There is more"
|
||||||
|
|
||||||
application, _ = DomainApplication.objects.get_or_create(
|
application, _ = DomainApplication.objects.get_or_create(**domain_application_kwargs)
|
||||||
**domain_application_kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
if has_other_contacts:
|
if has_other_contacts:
|
||||||
application.other_contacts.add(other)
|
application.other_contacts.add(other)
|
||||||
|
@ -631,11 +603,7 @@ class MockEppLib(TestCase):
|
||||||
mockDataInfoDomain = fakedEppObject(
|
mockDataInfoDomain = fakedEppObject(
|
||||||
"fakePw",
|
"fakePw",
|
||||||
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
|
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
|
||||||
contacts=[
|
contacts=[common.DomainContact(contact="123", type=PublicContact.ContactTypeChoices.SECURITY)],
|
||||||
common.DomainContact(
|
|
||||||
contact="123", type=PublicContact.ContactTypeChoices.SECURITY
|
|
||||||
)
|
|
||||||
],
|
|
||||||
hosts=["fake.host.com"],
|
hosts=["fake.host.com"],
|
||||||
statuses=[
|
statuses=[
|
||||||
common.Status(state="serverTransferProhibited", description="", lang="en"),
|
common.Status(state="serverTransferProhibited", description="", lang="en"),
|
||||||
|
@ -705,21 +673,11 @@ class MockEppLib(TestCase):
|
||||||
mockDefaultTechnicalContact = InfoDomainWithContacts.dummyInfoContactResultData(
|
mockDefaultTechnicalContact = InfoDomainWithContacts.dummyInfoContactResultData(
|
||||||
"defaultTech", "dotgov@cisa.dhs.gov"
|
"defaultTech", "dotgov@cisa.dhs.gov"
|
||||||
)
|
)
|
||||||
mockDefaultSecurityContact = InfoDomainWithContacts.dummyInfoContactResultData(
|
mockDefaultSecurityContact = InfoDomainWithContacts.dummyInfoContactResultData("defaultSec", "dotgov@cisa.dhs.gov")
|
||||||
"defaultSec", "dotgov@cisa.dhs.gov"
|
mockSecurityContact = InfoDomainWithContacts.dummyInfoContactResultData("securityContact", "security@mail.gov")
|
||||||
)
|
mockTechnicalContact = InfoDomainWithContacts.dummyInfoContactResultData("technicalContact", "tech@mail.gov")
|
||||||
mockSecurityContact = InfoDomainWithContacts.dummyInfoContactResultData(
|
mockAdministrativeContact = InfoDomainWithContacts.dummyInfoContactResultData("adminContact", "admin@mail.gov")
|
||||||
"securityContact", "security@mail.gov"
|
mockRegistrantContact = InfoDomainWithContacts.dummyInfoContactResultData("regContact", "registrant@mail.gov")
|
||||||
)
|
|
||||||
mockTechnicalContact = InfoDomainWithContacts.dummyInfoContactResultData(
|
|
||||||
"technicalContact", "tech@mail.gov"
|
|
||||||
)
|
|
||||||
mockAdministrativeContact = InfoDomainWithContacts.dummyInfoContactResultData(
|
|
||||||
"adminContact", "admin@mail.gov"
|
|
||||||
)
|
|
||||||
mockRegistrantContact = InfoDomainWithContacts.dummyInfoContactResultData(
|
|
||||||
"regContact", "registrant@mail.gov"
|
|
||||||
)
|
|
||||||
|
|
||||||
infoDomainNoContact = fakedEppObject(
|
infoDomainNoContact = fakedEppObject(
|
||||||
"security",
|
"security",
|
||||||
|
@ -759,9 +717,7 @@ class MockEppLib(TestCase):
|
||||||
addrs=[common.Ip(addr="1.2.3.4"), common.Ip(addr="2.3.4.5")],
|
addrs=[common.Ip(addr="1.2.3.4"), common.Ip(addr="2.3.4.5")],
|
||||||
)
|
)
|
||||||
|
|
||||||
mockDataHostChange = fakedEppObject(
|
mockDataHostChange = fakedEppObject("lastPw", cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35))
|
||||||
"lastPw", cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35)
|
|
||||||
)
|
|
||||||
addDsData1 = {
|
addDsData1 = {
|
||||||
"keyTag": 1234,
|
"keyTag": 1234,
|
||||||
"alg": 3,
|
"alg": 3,
|
||||||
|
@ -852,9 +808,7 @@ class MockEppLib(TestCase):
|
||||||
def _mockDomainName(self, _name, _avail=False):
|
def _mockDomainName(self, _name, _avail=False):
|
||||||
return MagicMock(
|
return MagicMock(
|
||||||
res_data=[
|
res_data=[
|
||||||
responses.check.CheckDomainResultData(
|
responses.check.CheckDomainResultData(name=_name, avail=_avail, reason=None),
|
||||||
name=_name, avail=_avail, reason=None
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -927,9 +881,7 @@ class MockEppLib(TestCase):
|
||||||
name = getattr(_request, "name", None)
|
name = getattr(_request, "name", None)
|
||||||
fake_nameserver = "ns1.failDelete.gov"
|
fake_nameserver = "ns1.failDelete.gov"
|
||||||
if name in fake_nameserver:
|
if name in fake_nameserver:
|
||||||
raise RegistryError(
|
raise RegistryError(code=ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION)
|
||||||
code=ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mockInfoDomainCommands(self, _request, cleaned):
|
def mockInfoDomainCommands(self, _request, cleaned):
|
||||||
|
@ -948,9 +900,7 @@ class MockEppLib(TestCase):
|
||||||
),
|
),
|
||||||
"dnssec-none.gov": (self.mockDataInfoDomain, None),
|
"dnssec-none.gov": (self.mockDataInfoDomain, None),
|
||||||
"my-nameserver.gov": (
|
"my-nameserver.gov": (
|
||||||
self.infoDomainTwoHosts
|
self.infoDomainTwoHosts if self.mockedSendFunction.call_count == 5 else self.infoDomainNoHost,
|
||||||
if self.mockedSendFunction.call_count == 5
|
|
||||||
else self.infoDomainNoHost,
|
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
"nameserverwithip.gov": (self.infoDomainHasIP, None),
|
"nameserverwithip.gov": (self.infoDomainHasIP, None),
|
||||||
|
@ -963,9 +913,7 @@ class MockEppLib(TestCase):
|
||||||
}
|
}
|
||||||
|
|
||||||
# Retrieve the corresponding values from the dictionary
|
# Retrieve the corresponding values from the dictionary
|
||||||
res_data, extensions = request_mappings.get(
|
res_data, extensions = request_mappings.get(request_name, (self.mockDataInfoDomain, None))
|
||||||
request_name, (self.mockDataInfoDomain, None)
|
|
||||||
)
|
|
||||||
|
|
||||||
return MagicMock(
|
return MagicMock(
|
||||||
res_data=[res_data],
|
res_data=[res_data],
|
||||||
|
@ -996,10 +944,7 @@ class MockEppLib(TestCase):
|
||||||
return MagicMock(res_data=[mocked_result])
|
return MagicMock(res_data=[mocked_result])
|
||||||
|
|
||||||
def mockCreateContactCommands(self, _request, cleaned):
|
def mockCreateContactCommands(self, _request, cleaned):
|
||||||
if (
|
if getattr(_request, "id", None) == "fail" and self.mockedSendFunction.call_count == 3:
|
||||||
getattr(_request, "id", None) == "fail"
|
|
||||||
and self.mockedSendFunction.call_count == 3
|
|
||||||
):
|
|
||||||
# use this for when a contact is being updated
|
# use this for when a contact is being updated
|
||||||
# sets the second send() to fail
|
# sets the second send() to fail
|
||||||
raise RegistryError(code=ErrorCode.OBJECT_EXISTS)
|
raise RegistryError(code=ErrorCode.OBJECT_EXISTS)
|
||||||
|
@ -1019,9 +964,7 @@ class MockEppLib(TestCase):
|
||||||
self.mockedSendFunction = self.mockSendPatch.start()
|
self.mockedSendFunction = self.mockSendPatch.start()
|
||||||
self.mockedSendFunction.side_effect = self.mockSend
|
self.mockedSendFunction.side_effect = self.mockSend
|
||||||
|
|
||||||
def _convertPublicContactToEpp(
|
def _convertPublicContactToEpp(self, contact: PublicContact, disclose_email=False, createContact=True):
|
||||||
self, contact: PublicContact, disclose_email=False, createContact=True
|
|
||||||
):
|
|
||||||
DF = common.DiscloseField
|
DF = common.DiscloseField
|
||||||
fields = {DF.EMAIL}
|
fields = {DF.EMAIL}
|
||||||
|
|
||||||
|
@ -1033,9 +976,7 @@ class MockEppLib(TestCase):
|
||||||
# check docs here looks like we may have more than one address field but
|
# check docs here looks like we may have more than one address field but
|
||||||
addr = common.ContactAddr(
|
addr = common.ContactAddr(
|
||||||
[
|
[
|
||||||
getattr(contact, street)
|
getattr(contact, street) for street in ["street1", "street2", "street3"] if hasattr(contact, street)
|
||||||
for street in ["street1", "street2", "street3"]
|
|
||||||
if hasattr(contact, street)
|
|
||||||
], # type: ignore
|
], # type: ignore
|
||||||
city=contact.city,
|
city=contact.city,
|
||||||
pc=contact.pc,
|
pc=contact.pc,
|
||||||
|
|
|
@ -67,9 +67,7 @@ class TestDomainAdmin(MockEppLib):
|
||||||
# for our actual application
|
# for our actual application
|
||||||
self.assertContains(response, "Federal", count=4)
|
self.assertContains(response, "Federal", count=4)
|
||||||
# This may be a bit more robust
|
# This may be a bit more robust
|
||||||
self.assertContains(
|
self.assertContains(response, '<td class="field-organization_type">Federal</td>', count=1)
|
||||||
response, '<td class="field-organization_type">Federal</td>', count=1
|
|
||||||
)
|
|
||||||
# Now let's make sure the long description does not exist
|
# Now let's make sure the long description does not exist
|
||||||
self.assertNotContains(response, "Federal: an agency of the U.S. government")
|
self.assertNotContains(response, "Federal: an agency of the U.S. government")
|
||||||
|
|
||||||
|
@ -318,9 +316,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.site = AdminSite()
|
self.site = AdminSite()
|
||||||
self.factory = RequestFactory()
|
self.factory = RequestFactory()
|
||||||
self.admin = DomainApplicationAdmin(
|
self.admin = DomainApplicationAdmin(model=DomainApplication, admin_site=self.site)
|
||||||
model=DomainApplication, admin_site=self.site
|
|
||||||
)
|
|
||||||
self.superuser = create_superuser()
|
self.superuser = create_superuser()
|
||||||
self.staffuser = create_user()
|
self.staffuser = create_user()
|
||||||
|
|
||||||
|
@ -335,9 +331,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
# for our actual application
|
# for our actual application
|
||||||
self.assertContains(response, "Federal", count=4)
|
self.assertContains(response, "Federal", count=4)
|
||||||
# This may be a bit more robust
|
# This may be a bit more robust
|
||||||
self.assertContains(
|
self.assertContains(response, '<td class="field-organization_type">Federal</td>', count=1)
|
||||||
response, '<td class="field-organization_type">Federal</td>', count=1
|
|
||||||
)
|
|
||||||
# Now let's make sure the long description does not exist
|
# Now let's make sure the long description does not exist
|
||||||
self.assertNotContains(response, "Federal: an agency of the U.S. government")
|
self.assertNotContains(response, "Federal: an agency of the U.S. government")
|
||||||
|
|
||||||
|
@ -355,9 +349,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
application = completed_application()
|
application = completed_application()
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Modify the application's property
|
# Modify the application's property
|
||||||
application.status = DomainApplication.SUBMITTED
|
application.status = DomainApplication.SUBMITTED
|
||||||
|
@ -398,9 +390,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
application = completed_application(status=DomainApplication.SUBMITTED)
|
application = completed_application(status=DomainApplication.SUBMITTED)
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Modify the application's property
|
# Modify the application's property
|
||||||
application.status = DomainApplication.IN_REVIEW
|
application.status = DomainApplication.IN_REVIEW
|
||||||
|
@ -441,9 +431,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
application = completed_application(status=DomainApplication.IN_REVIEW)
|
application = completed_application(status=DomainApplication.IN_REVIEW)
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Modify the application's property
|
# Modify the application's property
|
||||||
application.status = DomainApplication.APPROVED
|
application.status = DomainApplication.APPROVED
|
||||||
|
@ -479,9 +467,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
application = completed_application(status=DomainApplication.IN_REVIEW)
|
application = completed_application(status=DomainApplication.IN_REVIEW)
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Modify the application's property
|
# Modify the application's property
|
||||||
application.status = DomainApplication.APPROVED
|
application.status = DomainApplication.APPROVED
|
||||||
|
@ -490,9 +476,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
self.admin.save_model(request, application, form=None, change=True)
|
self.admin.save_model(request, application, form=None, change=True)
|
||||||
|
|
||||||
# Test that approved domain exists and equals requested domain
|
# Test that approved domain exists and equals requested domain
|
||||||
self.assertEqual(
|
self.assertEqual(application.requested_domain.name, application.approved_domain.name)
|
||||||
application.requested_domain.name, application.approved_domain.name
|
|
||||||
)
|
|
||||||
|
|
||||||
@boto3_mocking.patching
|
@boto3_mocking.patching
|
||||||
def test_save_model_sends_action_needed_email(self):
|
def test_save_model_sends_action_needed_email(self):
|
||||||
|
@ -508,9 +492,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
application = completed_application(status=DomainApplication.IN_REVIEW)
|
application = completed_application(status=DomainApplication.IN_REVIEW)
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Modify the application's property
|
# Modify the application's property
|
||||||
application.status = DomainApplication.ACTION_NEEDED
|
application.status = DomainApplication.ACTION_NEEDED
|
||||||
|
@ -529,10 +511,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
email_body = email_content["Simple"]["Body"]["Text"]["Data"]
|
email_body = email_content["Simple"]["Body"]["Text"]["Data"]
|
||||||
|
|
||||||
# Assert or perform other checks on the email details
|
# Assert or perform other checks on the email details
|
||||||
expected_string = (
|
expected_string = "We've identified an action needed to complete the review of your .gov domain request."
|
||||||
"We've identified an action needed to complete the "
|
|
||||||
"review of your .gov domain request."
|
|
||||||
)
|
|
||||||
self.assertEqual(from_email, settings.DEFAULT_FROM_EMAIL)
|
self.assertEqual(from_email, settings.DEFAULT_FROM_EMAIL)
|
||||||
self.assertEqual(to_email, EMAIL)
|
self.assertEqual(to_email, EMAIL)
|
||||||
self.assertIn(expected_string, email_body)
|
self.assertIn(expected_string, email_body)
|
||||||
|
@ -554,9 +533,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
application = completed_application(status=DomainApplication.IN_REVIEW)
|
application = completed_application(status=DomainApplication.IN_REVIEW)
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Modify the application's property
|
# Modify the application's property
|
||||||
application.status = DomainApplication.REJECTED
|
application.status = DomainApplication.REJECTED
|
||||||
|
@ -592,9 +569,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
application = completed_application(status=DomainApplication.IN_REVIEW)
|
application = completed_application(status=DomainApplication.IN_REVIEW)
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Modify the application's property
|
# Modify the application's property
|
||||||
application.status = DomainApplication.INELIGIBLE
|
application.status = DomainApplication.INELIGIBLE
|
||||||
|
@ -699,8 +674,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
# Assert that the error message was called with the correct argument
|
# Assert that the error message was called with the correct argument
|
||||||
mock_error.assert_called_once_with(
|
mock_error.assert_called_once_with(
|
||||||
request,
|
request,
|
||||||
"This action is not permitted for applications "
|
"This action is not permitted for applications with a restricted creator.",
|
||||||
+ "with a restricted creator.",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Assert that the status has not changed
|
# Assert that the status has not changed
|
||||||
|
@ -714,9 +688,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
|
|
||||||
with patch("django.contrib.messages.warning") as mock_warning:
|
with patch("django.contrib.messages.warning") as mock_warning:
|
||||||
# Create a request object with a superuser
|
# Create a request object with a superuser
|
||||||
request = self.factory.get(
|
request = self.factory.get("/admin/your_app/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/your_app/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
request.user = self.superuser
|
request.user = self.superuser
|
||||||
|
|
||||||
self.admin.display_restricted_warning(request, application)
|
self.admin.display_restricted_warning(request, application)
|
||||||
|
@ -735,9 +707,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
application.save()
|
application.save()
|
||||||
|
|
||||||
# Create a request object with a superuser
|
# Create a request object with a superuser
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
request.user = self.superuser
|
request.user = self.superuser
|
||||||
|
|
||||||
# Define a custom implementation for is_active
|
# Define a custom implementation for is_active
|
||||||
|
@ -764,16 +734,12 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
# Create an instance of the model
|
# Create an instance of the model
|
||||||
application = completed_application(status=DomainApplication.APPROVED)
|
application = completed_application(status=DomainApplication.APPROVED)
|
||||||
domain = Domain.objects.create(name=application.requested_domain.name)
|
domain = Domain.objects.create(name=application.requested_domain.name)
|
||||||
domain_information = DomainInformation.objects.create(
|
domain_information = DomainInformation.objects.create(creator=self.superuser, domain=domain)
|
||||||
creator=self.superuser, domain=domain
|
|
||||||
)
|
|
||||||
application.approved_domain = domain
|
application.approved_domain = domain
|
||||||
application.save()
|
application.save()
|
||||||
|
|
||||||
# Create a request object with a superuser
|
# Create a request object with a superuser
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
request.user = self.superuser
|
request.user = self.superuser
|
||||||
|
|
||||||
# Define a custom implementation for is_active
|
# Define a custom implementation for is_active
|
||||||
|
@ -811,9 +777,7 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
application.save()
|
application.save()
|
||||||
|
|
||||||
# Create a request object with a superuser
|
# Create a request object with a superuser
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
request.user = self.superuser
|
request.user = self.superuser
|
||||||
|
|
||||||
# Define a custom implementation for is_active
|
# Define a custom implementation for is_active
|
||||||
|
@ -840,16 +804,12 @@ class TestDomainApplicationAdmin(MockEppLib):
|
||||||
# Create an instance of the model
|
# Create an instance of the model
|
||||||
application = completed_application(status=DomainApplication.APPROVED)
|
application = completed_application(status=DomainApplication.APPROVED)
|
||||||
domain = Domain.objects.create(name=application.requested_domain.name)
|
domain = Domain.objects.create(name=application.requested_domain.name)
|
||||||
domain_information = DomainInformation.objects.create(
|
domain_information = DomainInformation.objects.create(creator=self.superuser, domain=domain)
|
||||||
creator=self.superuser, domain=domain
|
|
||||||
)
|
|
||||||
application.approved_domain = domain
|
application.approved_domain = domain
|
||||||
application.save()
|
application.save()
|
||||||
|
|
||||||
# Create a request object with a superuser
|
# Create a request object with a superuser
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(application.pk)
|
|
||||||
)
|
|
||||||
request.user = self.superuser
|
request.user = self.superuser
|
||||||
|
|
||||||
# Define a custom implementation for is_active
|
# Define a custom implementation for is_active
|
||||||
|
@ -1012,17 +972,13 @@ class AuditedAdminTest(TestCase):
|
||||||
self.factory = RequestFactory()
|
self.factory = RequestFactory()
|
||||||
self.client = Client(HTTP_HOST="localhost:8080")
|
self.client = Client(HTTP_HOST="localhost:8080")
|
||||||
|
|
||||||
def order_by_desired_field_helper(
|
def order_by_desired_field_helper(self, obj_to_sort: AuditedAdmin, request, field_name, *obj_names):
|
||||||
self, obj_to_sort: AuditedAdmin, request, field_name, *obj_names
|
|
||||||
):
|
|
||||||
formatted_sort_fields = []
|
formatted_sort_fields = []
|
||||||
for obj in obj_names:
|
for obj in obj_names:
|
||||||
formatted_sort_fields.append("{}__{}".format(field_name, obj))
|
formatted_sort_fields.append("{}__{}".format(field_name, obj))
|
||||||
|
|
||||||
ordered_list = list(
|
ordered_list = list(
|
||||||
obj_to_sort.get_queryset(request)
|
obj_to_sort.get_queryset(request).order_by(*formatted_sort_fields).values_list(*formatted_sort_fields)
|
||||||
.order_by(*formatted_sort_fields)
|
|
||||||
.values_list(*formatted_sort_fields)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return ordered_list
|
return ordered_list
|
||||||
|
@ -1040,9 +996,7 @@ class AuditedAdminTest(TestCase):
|
||||||
applications = multiple_unalphabetical_domain_objects("application")
|
applications = multiple_unalphabetical_domain_objects("application")
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(applications[0].pk))
|
||||||
"/admin/registrar/domainapplication/{}/change/".format(applications[0].pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
model_admin = AuditedAdmin(DomainApplication, self.site)
|
model_admin = AuditedAdmin(DomainApplication, self.site)
|
||||||
|
|
||||||
|
@ -1058,12 +1012,8 @@ class AuditedAdminTest(TestCase):
|
||||||
sorted_fields = ["first_name", "last_name"]
|
sorted_fields = ["first_name", "last_name"]
|
||||||
# We want both of these to be lists, as it is richer test wise.
|
# We want both of these to be lists, as it is richer test wise.
|
||||||
|
|
||||||
desired_order = self.order_by_desired_field_helper(
|
desired_order = self.order_by_desired_field_helper(model_admin, request, field.name, *sorted_fields)
|
||||||
model_admin, request, field.name, *sorted_fields
|
current_sort_order = list(model_admin.formfield_for_foreignkey(field, request).queryset)
|
||||||
)
|
|
||||||
current_sort_order = list(
|
|
||||||
model_admin.formfield_for_foreignkey(field, request).queryset
|
|
||||||
)
|
|
||||||
|
|
||||||
# Conforms to the same object structure as desired_order
|
# Conforms to the same object structure as desired_order
|
||||||
current_sort_order_coerced_type = []
|
current_sort_order_coerced_type = []
|
||||||
|
@ -1101,9 +1051,7 @@ class AuditedAdminTest(TestCase):
|
||||||
applications = multiple_unalphabetical_domain_objects("information")
|
applications = multiple_unalphabetical_domain_objects("information")
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domaininformation/{}/change/".format(applications[0].pk))
|
||||||
"/admin/registrar/domaininformation/{}/change/".format(applications[0].pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
model_admin = AuditedAdmin(DomainInformation, self.site)
|
model_admin = AuditedAdmin(DomainInformation, self.site)
|
||||||
|
|
||||||
|
@ -1121,12 +1069,8 @@ class AuditedAdminTest(TestCase):
|
||||||
sorted_fields = ["first_name", "last_name"]
|
sorted_fields = ["first_name", "last_name"]
|
||||||
field_obj = field
|
field_obj = field
|
||||||
# We want both of these to be lists, as it is richer test wise.
|
# We want both of these to be lists, as it is richer test wise.
|
||||||
desired_order = self.order_by_desired_field_helper(
|
desired_order = self.order_by_desired_field_helper(model_admin, request, field_obj.name, *sorted_fields)
|
||||||
model_admin, request, field_obj.name, *sorted_fields
|
current_sort_order = list(model_admin.formfield_for_foreignkey(field_obj, request).queryset)
|
||||||
)
|
|
||||||
current_sort_order = list(
|
|
||||||
model_admin.formfield_for_foreignkey(field_obj, request).queryset
|
|
||||||
)
|
|
||||||
|
|
||||||
# Conforms to the same object structure as desired_order
|
# Conforms to the same object structure as desired_order
|
||||||
current_sort_order_coerced_type = []
|
current_sort_order_coerced_type = []
|
||||||
|
@ -1144,9 +1088,7 @@ class AuditedAdminTest(TestCase):
|
||||||
elif field_obj == DomainInformation.domain_application.field:
|
elif field_obj == DomainInformation.domain_application.field:
|
||||||
first = obj.requested_domain.name
|
first = obj.requested_domain.name
|
||||||
|
|
||||||
name_tuple = self.coerced_fk_field_helper(
|
name_tuple = self.coerced_fk_field_helper(first, last, field_obj.name, ":")
|
||||||
first, last, field_obj.name, ":"
|
|
||||||
)
|
|
||||||
if name_tuple is not None:
|
if name_tuple is not None:
|
||||||
current_sort_order_coerced_type.append(name_tuple)
|
current_sort_order_coerced_type.append(name_tuple)
|
||||||
|
|
||||||
|
@ -1163,9 +1105,7 @@ class AuditedAdminTest(TestCase):
|
||||||
applications = multiple_unalphabetical_domain_objects("invitation")
|
applications = multiple_unalphabetical_domain_objects("invitation")
|
||||||
|
|
||||||
# Create a mock request
|
# Create a mock request
|
||||||
request = self.factory.post(
|
request = self.factory.post("/admin/registrar/domaininvitation/{}/change/".format(applications[0].pk))
|
||||||
"/admin/registrar/domaininvitation/{}/change/".format(applications[0].pk)
|
|
||||||
)
|
|
||||||
|
|
||||||
model_admin = AuditedAdmin(DomainInvitation, self.site)
|
model_admin = AuditedAdmin(DomainInvitation, self.site)
|
||||||
|
|
||||||
|
@ -1177,12 +1117,8 @@ class AuditedAdminTest(TestCase):
|
||||||
sorted_fields = ["name"]
|
sorted_fields = ["name"]
|
||||||
# We want both of these to be lists, as it is richer test wise.
|
# We want both of these to be lists, as it is richer test wise.
|
||||||
|
|
||||||
desired_order = self.order_by_desired_field_helper(
|
desired_order = self.order_by_desired_field_helper(model_admin, request, field.name, *sorted_fields)
|
||||||
model_admin, request, field.name, *sorted_fields
|
current_sort_order = list(model_admin.formfield_for_foreignkey(field, request).queryset)
|
||||||
)
|
|
||||||
current_sort_order = list(
|
|
||||||
model_admin.formfield_for_foreignkey(field, request).queryset
|
|
||||||
)
|
|
||||||
|
|
||||||
# Conforms to the same object structure as desired_order
|
# Conforms to the same object structure as desired_order
|
||||||
current_sort_order_coerced_type = []
|
current_sort_order_coerced_type = []
|
||||||
|
@ -1204,9 +1140,7 @@ class AuditedAdminTest(TestCase):
|
||||||
"{} is not ordered alphabetically".format(field.name),
|
"{} is not ordered alphabetically".format(field.name),
|
||||||
)
|
)
|
||||||
|
|
||||||
def coerced_fk_field_helper(
|
def coerced_fk_field_helper(self, first_name, last_name, field_name, queryset_shorthand):
|
||||||
self, first_name, last_name, field_name, queryset_shorthand
|
|
||||||
):
|
|
||||||
"""Handles edge cases for test cases"""
|
"""Handles edge cases for test cases"""
|
||||||
if first_name is None:
|
if first_name is None:
|
||||||
raise ValueError("Invalid value for first_name, must be defined")
|
raise ValueError("Invalid value for first_name, must be defined")
|
||||||
|
@ -1256,9 +1190,7 @@ class DomainSessionVariableTest(TestCase):
|
||||||
p = "adminpass"
|
p = "adminpass"
|
||||||
self.client.login(username="superuser", password=p)
|
self.client.login(username="superuser", password=p)
|
||||||
|
|
||||||
dummy_domain_information: Domain = generic_domain_object(
|
dummy_domain_information: Domain = generic_domain_object("information", "session")
|
||||||
"information", "session"
|
|
||||||
)
|
|
||||||
dummy_domain_information.domain.pk = 1
|
dummy_domain_information.domain.pk = 1
|
||||||
|
|
||||||
request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk)
|
request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk)
|
||||||
|
@ -1275,9 +1207,7 @@ class DomainSessionVariableTest(TestCase):
|
||||||
dummy_domain_information = generic_domain_object("information", "session")
|
dummy_domain_information = generic_domain_object("information", "session")
|
||||||
request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk)
|
request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk)
|
||||||
|
|
||||||
self.populate_session_values(
|
self.populate_session_values(request, dummy_domain_information.domain, preload_bad_data=True)
|
||||||
request, dummy_domain_information.domain, preload_bad_data=True
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(request.session["analyst_action"], "edit")
|
self.assertEqual(request.session["analyst_action"], "edit")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
@ -1291,9 +1221,7 @@ class DomainSessionVariableTest(TestCase):
|
||||||
p = "adminpass"
|
p = "adminpass"
|
||||||
self.client.login(username="superuser", password=p)
|
self.client.login(username="superuser", password=p)
|
||||||
|
|
||||||
dummy_domain_information_list = multiple_unalphabetical_domain_objects(
|
dummy_domain_information_list = multiple_unalphabetical_domain_objects("information")
|
||||||
"information"
|
|
||||||
)
|
|
||||||
for item in dummy_domain_information_list:
|
for item in dummy_domain_information_list:
|
||||||
request = self.get_factory_post_edit_domain(item.domain.pk)
|
request = self.get_factory_post_edit_domain(item.domain.pk)
|
||||||
self.populate_session_values(request, item.domain)
|
self.populate_session_values(request, item.domain)
|
||||||
|
|
|
@ -42,10 +42,7 @@ class TestFormValidation(MockEppLib):
|
||||||
form = CurrentSitesForm(data={"website": "nah"})
|
form = CurrentSitesForm(data={"website": "nah"})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
form.errors["website"],
|
form.errors["website"],
|
||||||
[
|
["Enter your organization's current website in the required format, like www.city.com."],
|
||||||
"Enter your organization's current website in the required format, like"
|
|
||||||
" www.city.com."
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_website_valid(self):
|
def test_website_valid(self):
|
||||||
|
@ -82,10 +79,7 @@ class TestFormValidation(MockEppLib):
|
||||||
form = DotGovDomainForm(data={"requested_domain": "underscores_forever"})
|
form = DotGovDomainForm(data={"requested_domain": "underscores_forever"})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
form.errors["requested_domain"],
|
form.errors["requested_domain"],
|
||||||
[
|
["Enter a domain using only letters, numbers, or hyphens (though we don't recommend using hyphens)."],
|
||||||
"Enter a domain using only letters, numbers, or hyphens (though we"
|
|
||||||
" don't recommend using hyphens)."
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_authorizing_official_email_invalid(self):
|
def test_authorizing_official_email_invalid(self):
|
||||||
|
@ -187,9 +181,7 @@ class TestFormValidation(MockEppLib):
|
||||||
def test_authorizing_official_phone_invalid(self):
|
def test_authorizing_official_phone_invalid(self):
|
||||||
"""Must be a valid phone number."""
|
"""Must be a valid phone number."""
|
||||||
form = AuthorizingOfficialForm(data={"phone": "boss@boss"})
|
form = AuthorizingOfficialForm(data={"phone": "boss@boss"})
|
||||||
self.assertTrue(
|
self.assertTrue(form.errors["phone"][0].startswith("Enter a valid phone number "))
|
||||||
form.errors["phone"][0].startswith("Enter a valid phone number ")
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_your_contact_email_invalid(self):
|
def test_your_contact_email_invalid(self):
|
||||||
"""must be a valid email address."""
|
"""must be a valid email address."""
|
||||||
|
@ -202,9 +194,7 @@ class TestFormValidation(MockEppLib):
|
||||||
def test_your_contact_phone_invalid(self):
|
def test_your_contact_phone_invalid(self):
|
||||||
"""Must be a valid phone number."""
|
"""Must be a valid phone number."""
|
||||||
form = YourContactForm(data={"phone": "boss@boss"})
|
form = YourContactForm(data={"phone": "boss@boss"})
|
||||||
self.assertTrue(
|
self.assertTrue(form.errors["phone"][0].startswith("Enter a valid phone number "))
|
||||||
form.errors["phone"][0].startswith("Enter a valid phone number ")
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_other_contact_email_invalid(self):
|
def test_other_contact_email_invalid(self):
|
||||||
"""must be a valid email address."""
|
"""must be a valid email address."""
|
||||||
|
@ -217,19 +207,14 @@ class TestFormValidation(MockEppLib):
|
||||||
def test_other_contact_phone_invalid(self):
|
def test_other_contact_phone_invalid(self):
|
||||||
"""Must be a valid phone number."""
|
"""Must be a valid phone number."""
|
||||||
form = OtherContactsForm(data={"phone": "boss@boss"})
|
form = OtherContactsForm(data={"phone": "boss@boss"})
|
||||||
self.assertTrue(
|
self.assertTrue(form.errors["phone"][0].startswith("Enter a valid phone number "))
|
||||||
form.errors["phone"][0].startswith("Enter a valid phone number ")
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_requirements_form_blank(self):
|
def test_requirements_form_blank(self):
|
||||||
"""Requirements box unchecked is an error."""
|
"""Requirements box unchecked is an error."""
|
||||||
form = RequirementsForm(data={})
|
form = RequirementsForm(data={})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
form.errors["is_policy_acknowledged"],
|
form.errors["is_policy_acknowledged"],
|
||||||
[
|
["Check the box if you read and agree to the requirements for operating .gov domains."],
|
||||||
"Check the box if you read and agree to the requirements for"
|
|
||||||
" operating .gov domains."
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_requirements_form_unchecked(self):
|
def test_requirements_form_unchecked(self):
|
||||||
|
@ -237,23 +222,13 @@ class TestFormValidation(MockEppLib):
|
||||||
form = RequirementsForm(data={"is_policy_acknowledged": False})
|
form = RequirementsForm(data={"is_policy_acknowledged": False})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
form.errors["is_policy_acknowledged"],
|
form.errors["is_policy_acknowledged"],
|
||||||
[
|
["Check the box if you read and agree to the requirements for operating .gov domains."],
|
||||||
"Check the box if you read and agree to the requirements for"
|
|
||||||
" operating .gov domains."
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_tribal_government_unrecognized(self):
|
def test_tribal_government_unrecognized(self):
|
||||||
"""Not state or federally recognized is an error."""
|
"""Not state or federally recognized is an error."""
|
||||||
form = TribalGovernmentForm(
|
form = TribalGovernmentForm(data={"state_recognized": False, "federally_recognized": False})
|
||||||
data={"state_recognized": False, "federally_recognized": False}
|
self.assertTrue(any("tell us more about your tribe" in error for error in form.non_field_errors()))
|
||||||
)
|
|
||||||
self.assertTrue(
|
|
||||||
any(
|
|
||||||
"tell us more about your tribe" in error
|
|
||||||
for error in form.non_field_errors()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestContactForm(TestCase):
|
class TestContactForm(TestCase):
|
||||||
|
|
|
@ -22,14 +22,10 @@ class TestGroups(TestCase):
|
||||||
full_access_group = UserGroup.objects.get(name="full_access_group")
|
full_access_group = UserGroup.objects.get(name="full_access_group")
|
||||||
|
|
||||||
# Assert that the cisa_analysts_group exists in the database
|
# Assert that the cisa_analysts_group exists in the database
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(UserGroup.objects.filter(name="cisa_analysts_group"), [cisa_analysts_group])
|
||||||
UserGroup.objects.filter(name="cisa_analysts_group"), [cisa_analysts_group]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Assert that the full_access_group exists in the database
|
# Assert that the full_access_group exists in the database
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(UserGroup.objects.filter(name="full_access_group"), [full_access_group])
|
||||||
UserGroup.objects.filter(name="full_access_group"), [full_access_group]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test permissions for cisa_analysts_group
|
# Test permissions for cisa_analysts_group
|
||||||
# Verifies permission data migrations ran as expected.
|
# Verifies permission data migrations ran as expected.
|
||||||
|
|
|
@ -104,9 +104,7 @@ class TestDomainApplication(TestCase):
|
||||||
def test_status_fsm_submit_succeed(self):
|
def test_status_fsm_submit_succeed(self):
|
||||||
user, _ = User.objects.get_or_create()
|
user, _ = User.objects.get_or_create()
|
||||||
site = DraftDomain.objects.create(name="igorville.gov")
|
site = DraftDomain.objects.create(name="igorville.gov")
|
||||||
application = DomainApplication.objects.create(
|
application = DomainApplication.objects.create(creator=user, requested_domain=site)
|
||||||
creator=user, requested_domain=site
|
|
||||||
)
|
|
||||||
# no submitter email so this emits a log warning
|
# no submitter email so this emits a log warning
|
||||||
with less_console_noise():
|
with less_console_noise():
|
||||||
application.submit()
|
application.submit()
|
||||||
|
@ -543,9 +541,7 @@ class TestPermissions(TestCase):
|
||||||
def test_approval_creates_role(self):
|
def test_approval_creates_role(self):
|
||||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
||||||
user, _ = User.objects.get_or_create()
|
user, _ = User.objects.get_or_create()
|
||||||
application = DomainApplication.objects.create(
|
application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain)
|
||||||
creator=user, requested_domain=draft_domain
|
|
||||||
)
|
|
||||||
# skip using the submit method
|
# skip using the submit method
|
||||||
application.status = DomainApplication.SUBMITTED
|
application.status = DomainApplication.SUBMITTED
|
||||||
application.approve()
|
application.approve()
|
||||||
|
@ -562,9 +558,7 @@ class TestDomainInfo(TestCase):
|
||||||
def test_approval_creates_info(self):
|
def test_approval_creates_info(self):
|
||||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
||||||
user, _ = User.objects.get_or_create()
|
user, _ = User.objects.get_or_create()
|
||||||
application = DomainApplication.objects.create(
|
application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain)
|
||||||
creator=user, requested_domain=draft_domain
|
|
||||||
)
|
|
||||||
# skip using the submit method
|
# skip using the submit method
|
||||||
application.status = DomainApplication.SUBMITTED
|
application.status = DomainApplication.SUBMITTED
|
||||||
application.approve()
|
application.approve()
|
||||||
|
@ -581,9 +575,7 @@ class TestInvitations(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
self.domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
||||||
self.email = "mayor@igorville.gov"
|
self.email = "mayor@igorville.gov"
|
||||||
self.invitation, _ = DomainInvitation.objects.get_or_create(
|
self.invitation, _ = DomainInvitation.objects.get_or_create(email=self.email, domain=self.domain)
|
||||||
email=self.email, domain=self.domain
|
|
||||||
)
|
|
||||||
self.user, _ = User.objects.get_or_create(email=self.email)
|
self.user, _ = User.objects.get_or_create(email=self.email)
|
||||||
|
|
||||||
# clean out the roles each time
|
# clean out the roles each time
|
||||||
|
@ -601,9 +593,7 @@ class TestInvitations(TestCase):
|
||||||
|
|
||||||
def test_retrieve_existing_role_no_error(self):
|
def test_retrieve_existing_role_no_error(self):
|
||||||
# make the overlapping role
|
# make the overlapping role
|
||||||
UserDomainRole.objects.get_or_create(
|
UserDomainRole.objects.get_or_create(user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER)
|
||||||
user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER
|
|
||||||
)
|
|
||||||
# this is not an error but does produce a console warning
|
# this is not an error but does produce a console warning
|
||||||
with less_console_noise():
|
with less_console_noise():
|
||||||
self.invitation.retrieve()
|
self.invitation.retrieve()
|
||||||
|
@ -627,9 +617,7 @@ class TestUser(TestCase):
|
||||||
# clean out the roles each time
|
# clean out the roles each time
|
||||||
UserDomainRole.objects.all().delete()
|
UserDomainRole.objects.all().delete()
|
||||||
|
|
||||||
TransitionDomain.objects.get_or_create(
|
TransitionDomain.objects.get_or_create(username="mayor@igorville.gov", domain_name=self.domain_name)
|
||||||
username="mayor@igorville.gov", domain_name=self.domain_name
|
|
||||||
)
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
|
@ -84,9 +84,7 @@ class TestDomainCache(MockEppLib):
|
||||||
|
|
||||||
# send was only called once & not on the second getter call
|
# send was only called once & not on the second getter call
|
||||||
expectedCalls = [
|
expectedCalls = [
|
||||||
call(
|
call(commands.InfoDomain(name="igorville.gov", auth_info=None), cleaned=True),
|
||||||
commands.InfoDomain(name="igorville.gov", auth_info=None), cleaned=True
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
self.mockedSendFunction.assert_has_calls(expectedCalls)
|
self.mockedSendFunction.assert_has_calls(expectedCalls)
|
||||||
|
@ -261,9 +259,7 @@ class TestDomainCreation(MockEppLib):
|
||||||
"""
|
"""
|
||||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
||||||
user, _ = User.objects.get_or_create()
|
user, _ = User.objects.get_or_create()
|
||||||
application = DomainApplication.objects.create(
|
application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain)
|
||||||
creator=user, requested_domain=draft_domain
|
|
||||||
)
|
|
||||||
# skip using the submit method
|
# skip using the submit method
|
||||||
application.status = DomainApplication.SUBMITTED
|
application.status = DomainApplication.SUBMITTED
|
||||||
# transition to approve state
|
# transition to approve state
|
||||||
|
@ -412,11 +408,7 @@ class TestDomainAvailable(MockEppLib):
|
||||||
|
|
||||||
def side_effect(_request, cleaned):
|
def side_effect(_request, cleaned):
|
||||||
return MagicMock(
|
return MagicMock(
|
||||||
res_data=[
|
res_data=[responses.check.CheckDomainResultData(name="available.gov", avail=True, reason=None)],
|
||||||
responses.check.CheckDomainResultData(
|
|
||||||
name="available.gov", avail=True, reason=None
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
patcher = patch("registrar.models.domain.registry.send")
|
patcher = patch("registrar.models.domain.registry.send")
|
||||||
|
@ -449,11 +441,7 @@ class TestDomainAvailable(MockEppLib):
|
||||||
|
|
||||||
def side_effect(_request, cleaned):
|
def side_effect(_request, cleaned):
|
||||||
return MagicMock(
|
return MagicMock(
|
||||||
res_data=[
|
res_data=[responses.check.CheckDomainResultData(name="unavailable.gov", avail=False, reason="In Use")],
|
||||||
responses.check.CheckDomainResultData(
|
|
||||||
name="unavailable.gov", avail=False, reason="In Use"
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
patcher = patch("registrar.models.domain.registry.send")
|
patcher = patch("registrar.models.domain.registry.send")
|
||||||
|
@ -556,16 +544,10 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
).registry_id
|
).registry_id
|
||||||
|
|
||||||
expectedSecContact.registry_id = id
|
expectedSecContact.registry_id = id
|
||||||
expectedCreateCommand = self._convertPublicContactToEpp(
|
expectedCreateCommand = self._convertPublicContactToEpp(expectedSecContact, disclose_email=False)
|
||||||
expectedSecContact, disclose_email=False
|
|
||||||
)
|
|
||||||
expectedUpdateDomain = commands.UpdateDomain(
|
expectedUpdateDomain = commands.UpdateDomain(
|
||||||
name=self.domain.name,
|
name=self.domain.name,
|
||||||
add=[
|
add=[common.DomainContact(contact=expectedSecContact.registry_id, type="security")],
|
||||||
common.DomainContact(
|
|
||||||
contact=expectedSecContact.registry_id, type="security"
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
||||||
|
@ -594,17 +576,11 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
expectedSecContact.save()
|
expectedSecContact.save()
|
||||||
|
|
||||||
# no longer the default email it should be disclosed
|
# no longer the default email it should be disclosed
|
||||||
expectedCreateCommand = self._convertPublicContactToEpp(
|
expectedCreateCommand = self._convertPublicContactToEpp(expectedSecContact, disclose_email=True)
|
||||||
expectedSecContact, disclose_email=True
|
|
||||||
)
|
|
||||||
|
|
||||||
expectedUpdateDomain = commands.UpdateDomain(
|
expectedUpdateDomain = commands.UpdateDomain(
|
||||||
name=self.domain.name,
|
name=self.domain.name,
|
||||||
add=[
|
add=[common.DomainContact(contact=expectedSecContact.registry_id, type="security")],
|
||||||
common.DomainContact(
|
|
||||||
contact=expectedSecContact.registry_id, type="security"
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# check that send has triggered the create command for the contact
|
# check that send has triggered the create command for the contact
|
||||||
|
@ -630,17 +606,11 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
|
|
||||||
self.domain.security_contact = security_contact
|
self.domain.security_contact = security_contact
|
||||||
|
|
||||||
expectedCreateCommand = self._convertPublicContactToEpp(
|
expectedCreateCommand = self._convertPublicContactToEpp(security_contact, disclose_email=False)
|
||||||
security_contact, disclose_email=False
|
|
||||||
)
|
|
||||||
|
|
||||||
expectedUpdateDomain = commands.UpdateDomain(
|
expectedUpdateDomain = commands.UpdateDomain(
|
||||||
name=self.domain.name,
|
name=self.domain.name,
|
||||||
add=[
|
add=[common.DomainContact(contact=security_contact.registry_id, type="security")],
|
||||||
common.DomainContact(
|
|
||||||
contact=security_contact.registry_id, type="security"
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
expected_calls = [
|
expected_calls = [
|
||||||
call(expectedCreateCommand, cleaned=True),
|
call(expectedCreateCommand, cleaned=True),
|
||||||
|
@ -671,38 +641,26 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
new_contact.email = ""
|
new_contact.email = ""
|
||||||
self.domain.security_contact = new_contact
|
self.domain.security_contact = new_contact
|
||||||
|
|
||||||
firstCreateContactCall = self._convertPublicContactToEpp(
|
firstCreateContactCall = self._convertPublicContactToEpp(old_contact, disclose_email=True)
|
||||||
old_contact, disclose_email=True
|
|
||||||
)
|
|
||||||
updateDomainAddCall = commands.UpdateDomain(
|
updateDomainAddCall = commands.UpdateDomain(
|
||||||
name=self.domain.name,
|
name=self.domain.name,
|
||||||
add=[
|
add=[common.DomainContact(contact=old_contact.registry_id, type="security")],
|
||||||
common.DomainContact(contact=old_contact.registry_id, type="security")
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
PublicContact.objects.filter(domain=self.domain).get().email,
|
PublicContact.objects.filter(domain=self.domain).get().email,
|
||||||
PublicContact.get_default_security().email,
|
PublicContact.get_default_security().email,
|
||||||
)
|
)
|
||||||
# this one triggers the fail
|
# this one triggers the fail
|
||||||
secondCreateContact = self._convertPublicContactToEpp(
|
secondCreateContact = self._convertPublicContactToEpp(new_contact, disclose_email=True)
|
||||||
new_contact, disclose_email=True
|
|
||||||
)
|
|
||||||
updateDomainRemCall = commands.UpdateDomain(
|
updateDomainRemCall = commands.UpdateDomain(
|
||||||
name=self.domain.name,
|
name=self.domain.name,
|
||||||
rem=[
|
rem=[common.DomainContact(contact=old_contact.registry_id, type="security")],
|
||||||
common.DomainContact(contact=old_contact.registry_id, type="security")
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
defaultSecID = (
|
defaultSecID = PublicContact.objects.filter(domain=self.domain).get().registry_id
|
||||||
PublicContact.objects.filter(domain=self.domain).get().registry_id
|
|
||||||
)
|
|
||||||
default_security = PublicContact.get_default_security()
|
default_security = PublicContact.get_default_security()
|
||||||
default_security.registry_id = defaultSecID
|
default_security.registry_id = defaultSecID
|
||||||
createDefaultContact = self._convertPublicContactToEpp(
|
createDefaultContact = self._convertPublicContactToEpp(default_security, disclose_email=False)
|
||||||
default_security, disclose_email=False
|
|
||||||
)
|
|
||||||
updateDomainWDefault = commands.UpdateDomain(
|
updateDomainWDefault = commands.UpdateDomain(
|
||||||
name=self.domain.name,
|
name=self.domain.name,
|
||||||
add=[common.DomainContact(contact=defaultSecID, type="security")],
|
add=[common.DomainContact(contact=defaultSecID, type="security")],
|
||||||
|
@ -731,26 +689,16 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
security_contact.email = "originalUserEmail@gmail.com"
|
security_contact.email = "originalUserEmail@gmail.com"
|
||||||
security_contact.registry_id = "fail"
|
security_contact.registry_id = "fail"
|
||||||
security_contact.save()
|
security_contact.save()
|
||||||
expectedCreateCommand = self._convertPublicContactToEpp(
|
expectedCreateCommand = self._convertPublicContactToEpp(security_contact, disclose_email=True)
|
||||||
security_contact, disclose_email=True
|
|
||||||
)
|
|
||||||
|
|
||||||
expectedUpdateDomain = commands.UpdateDomain(
|
expectedUpdateDomain = commands.UpdateDomain(
|
||||||
name=self.domain.name,
|
name=self.domain.name,
|
||||||
add=[
|
add=[common.DomainContact(contact=security_contact.registry_id, type="security")],
|
||||||
common.DomainContact(
|
|
||||||
contact=security_contact.registry_id, type="security"
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
security_contact.email = "changedEmail@email.com"
|
security_contact.email = "changedEmail@email.com"
|
||||||
security_contact.save()
|
security_contact.save()
|
||||||
expectedSecondCreateCommand = self._convertPublicContactToEpp(
|
expectedSecondCreateCommand = self._convertPublicContactToEpp(security_contact, disclose_email=True)
|
||||||
security_contact, disclose_email=True
|
updateContact = self._convertPublicContactToEpp(security_contact, disclose_email=True, createContact=False)
|
||||||
)
|
|
||||||
updateContact = self._convertPublicContactToEpp(
|
|
||||||
security_contact, disclose_email=True, createContact=False
|
|
||||||
)
|
|
||||||
|
|
||||||
expected_calls = [
|
expected_calls = [
|
||||||
call(expectedCreateCommand, cleaned=True),
|
call(expectedCreateCommand, cleaned=True),
|
||||||
|
@ -804,9 +752,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
actual_contact = contact[1]
|
actual_contact = contact[1]
|
||||||
is_security = expected_contact.contact_type == "security"
|
is_security = expected_contact.contact_type == "security"
|
||||||
|
|
||||||
expectedCreateCommand = self._convertPublicContactToEpp(
|
expectedCreateCommand = self._convertPublicContactToEpp(expected_contact, disclose_email=is_security)
|
||||||
expected_contact, disclose_email=is_security
|
|
||||||
)
|
|
||||||
|
|
||||||
# Should only be disclosed if the type is security, as the email is valid
|
# Should only be disclosed if the type is security, as the email is valid
|
||||||
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
||||||
|
@ -818,20 +764,14 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
domain, _ = Domain.objects.get_or_create(name="freeman.gov")
|
domain, _ = Domain.objects.get_or_create(name="freeman.gov")
|
||||||
dummy_contact = domain.get_default_security_contact()
|
dummy_contact = domain.get_default_security_contact()
|
||||||
test_disclose = self._convertPublicContactToEpp(
|
test_disclose = self._convertPublicContactToEpp(dummy_contact, disclose_email=True).__dict__
|
||||||
dummy_contact, disclose_email=True
|
test_not_disclose = self._convertPublicContactToEpp(dummy_contact, disclose_email=False).__dict__
|
||||||
).__dict__
|
|
||||||
test_not_disclose = self._convertPublicContactToEpp(
|
|
||||||
dummy_contact, disclose_email=False
|
|
||||||
).__dict__
|
|
||||||
|
|
||||||
# Separated for linter
|
# Separated for linter
|
||||||
disclose_email_field = {common.DiscloseField.EMAIL}
|
disclose_email_field = {common.DiscloseField.EMAIL}
|
||||||
expected_disclose = {
|
expected_disclose = {
|
||||||
"auth_info": common.ContactAuthInfo(pw="2fooBAR123fooBaz"),
|
"auth_info": common.ContactAuthInfo(pw="2fooBAR123fooBaz"),
|
||||||
"disclose": common.Disclose(
|
"disclose": common.Disclose(flag=True, fields=disclose_email_field, types=None),
|
||||||
flag=True, fields=disclose_email_field, types=None
|
|
||||||
),
|
|
||||||
"email": "dotgov@cisa.dhs.gov",
|
"email": "dotgov@cisa.dhs.gov",
|
||||||
"extensions": [],
|
"extensions": [],
|
||||||
"fax": None,
|
"fax": None,
|
||||||
|
@ -857,9 +797,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
# Separated for linter
|
# Separated for linter
|
||||||
expected_not_disclose = {
|
expected_not_disclose = {
|
||||||
"auth_info": common.ContactAuthInfo(pw="2fooBAR123fooBaz"),
|
"auth_info": common.ContactAuthInfo(pw="2fooBAR123fooBaz"),
|
||||||
"disclose": common.Disclose(
|
"disclose": common.Disclose(flag=False, fields=disclose_email_field, types=None),
|
||||||
flag=False, fields=disclose_email_field, types=None
|
|
||||||
),
|
|
||||||
"email": "dotgov@cisa.dhs.gov",
|
"email": "dotgov@cisa.dhs.gov",
|
||||||
"extensions": [],
|
"extensions": [],
|
||||||
"fax": None,
|
"fax": None,
|
||||||
|
@ -902,9 +840,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
expectedSecContact.registry_id = "defaultSec"
|
expectedSecContact.registry_id = "defaultSec"
|
||||||
domain.security_contact = expectedSecContact
|
domain.security_contact = expectedSecContact
|
||||||
|
|
||||||
expectedCreateCommand = self._convertPublicContactToEpp(
|
expectedCreateCommand = self._convertPublicContactToEpp(expectedSecContact, disclose_email=False)
|
||||||
expectedSecContact, disclose_email=False
|
|
||||||
)
|
|
||||||
|
|
||||||
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
||||||
# Confirm that we are getting a default email
|
# Confirm that we are getting a default email
|
||||||
|
@ -923,9 +859,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
expectedTechContact.registry_id = "defaultTech"
|
expectedTechContact.registry_id = "defaultTech"
|
||||||
domain.technical_contact = expectedTechContact
|
domain.technical_contact = expectedTechContact
|
||||||
|
|
||||||
expectedCreateCommand = self._convertPublicContactToEpp(
|
expectedCreateCommand = self._convertPublicContactToEpp(expectedTechContact, disclose_email=False)
|
||||||
expectedTechContact, disclose_email=False
|
|
||||||
)
|
|
||||||
|
|
||||||
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
||||||
# Confirm that we are getting a default email
|
# Confirm that we are getting a default email
|
||||||
|
@ -945,9 +879,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
expectedSecContact.email = "123@mail.gov"
|
expectedSecContact.email = "123@mail.gov"
|
||||||
domain.security_contact = expectedSecContact
|
domain.security_contact = expectedSecContact
|
||||||
|
|
||||||
expectedCreateCommand = self._convertPublicContactToEpp(
|
expectedCreateCommand = self._convertPublicContactToEpp(expectedSecContact, disclose_email=True)
|
||||||
expectedSecContact, disclose_email=True
|
|
||||||
)
|
|
||||||
|
|
||||||
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
||||||
# Confirm that we are getting the desired email
|
# Confirm that we are getting the desired email
|
||||||
|
@ -972,9 +904,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Checks if we grabbed the correct PublicContact
|
# Checks if we grabbed the correct PublicContact
|
||||||
self.assertEqual(
|
self.assertEqual(self.domain_contact.security_contact.email, expected_contact.email)
|
||||||
self.domain_contact.security_contact.email, expected_contact.email
|
|
||||||
)
|
|
||||||
|
|
||||||
expected_contact_db = PublicContact.objects.filter(
|
expected_contact_db = PublicContact.objects.filter(
|
||||||
registry_id=self.domain_contact.security_contact.registry_id,
|
registry_id=self.domain_contact.security_contact.registry_id,
|
||||||
|
@ -1003,9 +933,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
contact_type=technical,
|
contact_type=technical,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(self.domain_contact.technical_contact.email, expected_contact.email)
|
||||||
self.domain_contact.technical_contact.email, expected_contact.email
|
|
||||||
)
|
|
||||||
|
|
||||||
# Checks if we grab the correct PublicContact
|
# Checks if we grab the correct PublicContact
|
||||||
expected_contact_db = PublicContact.objects.filter(
|
expected_contact_db = PublicContact.objects.filter(
|
||||||
|
@ -1035,9 +963,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
contact_type=administrative,
|
contact_type=administrative,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(self.domain_contact.administrative_contact.email, expected_contact.email)
|
||||||
self.domain_contact.administrative_contact.email, expected_contact.email
|
|
||||||
)
|
|
||||||
|
|
||||||
expected_contact_db = PublicContact.objects.filter(
|
expected_contact_db = PublicContact.objects.filter(
|
||||||
registry_id=self.domain_contact.administrative_contact.registry_id,
|
registry_id=self.domain_contact.administrative_contact.registry_id,
|
||||||
|
@ -1045,9 +971,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
).get()
|
).get()
|
||||||
|
|
||||||
# Checks if we grab the correct PublicContact
|
# Checks if we grab the correct PublicContact
|
||||||
self.assertEqual(
|
self.assertEqual(self.domain_contact.administrative_contact, expected_contact_db)
|
||||||
self.domain_contact.administrative_contact, expected_contact_db
|
|
||||||
)
|
|
||||||
self.mockedSendFunction.assert_has_calls(
|
self.mockedSendFunction.assert_has_calls(
|
||||||
[
|
[
|
||||||
call(
|
call(
|
||||||
|
@ -1067,9 +991,7 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
contact_type=PublicContact.ContactTypeChoices.REGISTRANT,
|
contact_type=PublicContact.ContactTypeChoices.REGISTRANT,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(self.domain_contact.registrant_contact.email, expected_contact.email)
|
||||||
self.domain_contact.registrant_contact.email, expected_contact.email
|
|
||||||
)
|
|
||||||
|
|
||||||
expected_contact_db = PublicContact.objects.filter(
|
expected_contact_db = PublicContact.objects.filter(
|
||||||
registry_id=self.domain_contact.registrant_contact.registry_id,
|
registry_id=self.domain_contact.registrant_contact.registry_id,
|
||||||
|
@ -1104,9 +1026,7 @@ class TestRegistrantNameservers(MockEppLib):
|
||||||
self.nameserver2 = "ns1.my-nameserver-2.com"
|
self.nameserver2 = "ns1.my-nameserver-2.com"
|
||||||
self.nameserver3 = "ns1.cats-are-superior3.com"
|
self.nameserver3 = "ns1.cats-are-superior3.com"
|
||||||
|
|
||||||
self.domain, _ = Domain.objects.get_or_create(
|
self.domain, _ = Domain.objects.get_or_create(name="my-nameserver.gov", state=Domain.State.DNS_NEEDED)
|
||||||
name="my-nameserver.gov", state=Domain.State.DNS_NEEDED
|
|
||||||
)
|
|
||||||
self.domainWithThreeNS, _ = Domain.objects.get_or_create(
|
self.domainWithThreeNS, _ = Domain.objects.get_or_create(
|
||||||
name="threenameserversDomain.gov", state=Domain.State.READY
|
name="threenameserversDomain.gov", state=Domain.State.READY
|
||||||
)
|
)
|
||||||
|
@ -1476,9 +1396,7 @@ class TestRegistrantNameservers(MockEppLib):
|
||||||
with a different IP address(es)
|
with a different IP address(es)
|
||||||
Then `commands.UpdateHost` is sent to the registry
|
Then `commands.UpdateHost` is sent to the registry
|
||||||
"""
|
"""
|
||||||
domain, _ = Domain.objects.get_or_create(
|
domain, _ = Domain.objects.get_or_create(name="nameserverwithip.gov", state=Domain.State.READY)
|
||||||
name="nameserverwithip.gov", state=Domain.State.READY
|
|
||||||
)
|
|
||||||
domain.nameservers = [
|
domain.nameservers = [
|
||||||
("ns1.nameserverwithip.gov", ["2.3.4.5", "1.2.3.4"]),
|
("ns1.nameserverwithip.gov", ["2.3.4.5", "1.2.3.4"]),
|
||||||
(
|
(
|
||||||
|
@ -1499,11 +1417,7 @@ class TestRegistrantNameservers(MockEppLib):
|
||||||
call(
|
call(
|
||||||
commands.UpdateHost(
|
commands.UpdateHost(
|
||||||
name="ns2.nameserverwithip.gov",
|
name="ns2.nameserverwithip.gov",
|
||||||
add=[
|
add=[common.Ip(addr="2001:0db8:85a3:0000:0000:8a2e:0370:7334", ip="v6")],
|
||||||
common.Ip(
|
|
||||||
addr="2001:0db8:85a3:0000:0000:8a2e:0370:7334", ip="v6"
|
|
||||||
)
|
|
||||||
],
|
|
||||||
rem=[],
|
rem=[],
|
||||||
chg=None,
|
chg=None,
|
||||||
),
|
),
|
||||||
|
@ -1565,9 +1479,7 @@ class TestRegistrantNameservers(MockEppLib):
|
||||||
self.assertEqual(self.mockedSendFunction.call_count, 4)
|
self.assertEqual(self.mockedSendFunction.call_count, 4)
|
||||||
|
|
||||||
def test_is_subdomain_with_no_ip(self):
|
def test_is_subdomain_with_no_ip(self):
|
||||||
domain, _ = Domain.objects.get_or_create(
|
domain, _ = Domain.objects.get_or_create(name="nameserversubdomain.gov", state=Domain.State.READY)
|
||||||
name="nameserversubdomain.gov", state=Domain.State.READY
|
|
||||||
)
|
|
||||||
|
|
||||||
with self.assertRaises(NameserverError):
|
with self.assertRaises(NameserverError):
|
||||||
domain.nameservers = [
|
domain.nameservers = [
|
||||||
|
@ -1576,9 +1488,7 @@ class TestRegistrantNameservers(MockEppLib):
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_not_subdomain_but_has_ip(self):
|
def test_not_subdomain_but_has_ip(self):
|
||||||
domain, _ = Domain.objects.get_or_create(
|
domain, _ = Domain.objects.get_or_create(name="nameserversubdomain.gov", state=Domain.State.READY)
|
||||||
name="nameserversubdomain.gov", state=Domain.State.READY
|
|
||||||
)
|
|
||||||
|
|
||||||
with self.assertRaises(NameserverError):
|
with self.assertRaises(NameserverError):
|
||||||
domain.nameservers = [
|
domain.nameservers = [
|
||||||
|
@ -1587,9 +1497,7 @@ class TestRegistrantNameservers(MockEppLib):
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_is_subdomain_but_ip_addr_not_valid(self):
|
def test_is_subdomain_but_ip_addr_not_valid(self):
|
||||||
domain, _ = Domain.objects.get_or_create(
|
domain, _ = Domain.objects.get_or_create(name="nameserversubdomain.gov", state=Domain.State.READY)
|
||||||
name="nameserversubdomain.gov", state=Domain.State.READY
|
|
||||||
)
|
|
||||||
|
|
||||||
with self.assertRaises(NameserverError):
|
with self.assertRaises(NameserverError):
|
||||||
domain.nameservers = [
|
domain.nameservers = [
|
||||||
|
@ -1600,9 +1508,7 @@ class TestRegistrantNameservers(MockEppLib):
|
||||||
def test_setting_not_allowed(self):
|
def test_setting_not_allowed(self):
|
||||||
"""Scenario: A domain state is not Ready or DNS Needed
|
"""Scenario: A domain state is not Ready or DNS Needed
|
||||||
then setting nameservers is not allowed"""
|
then setting nameservers is not allowed"""
|
||||||
domain, _ = Domain.objects.get_or_create(
|
domain, _ = Domain.objects.get_or_create(name="onholdDomain.gov", state=Domain.State.ON_HOLD)
|
||||||
name="onholdDomain.gov", state=Domain.State.ON_HOLD
|
|
||||||
)
|
|
||||||
with self.assertRaises(ActionNotAllowed):
|
with self.assertRaises(ActionNotAllowed):
|
||||||
domain.nameservers = [self.nameserver1, self.nameserver2]
|
domain.nameservers = [self.nameserver1, self.nameserver2]
|
||||||
|
|
||||||
|
@ -1618,9 +1524,7 @@ class TestRegistrantNameservers(MockEppLib):
|
||||||
don't want to lose user info (and exit out too early)
|
don't want to lose user info (and exit out too early)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
domain, _ = Domain.objects.get_or_create(
|
domain, _ = Domain.objects.get_or_create(name="failednameserver.gov", state=Domain.State.READY)
|
||||||
name="failednameserver.gov", state=Domain.State.READY
|
|
||||||
)
|
|
||||||
|
|
||||||
with self.assertRaises(RegistryError):
|
with self.assertRaises(RegistryError):
|
||||||
domain.nameservers = [("ns1.failednameserver.gov", ["4.5.6"])]
|
domain.nameservers = [("ns1.failednameserver.gov", ["4.5.6"])]
|
||||||
|
@ -1647,9 +1551,7 @@ class TestNameserverValidation(TestCase):
|
||||||
|
|
||||||
def test_64_char_label_too_long(self):
|
def test_64_char_label_too_long(self):
|
||||||
"""Test that label of 64 characters or longer is invalid"""
|
"""Test that label of 64 characters or longer is invalid"""
|
||||||
label_too_long = (
|
label_too_long = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
|
||||||
)
|
|
||||||
domain_label_too_long = "www." + label_too_long + ".gov"
|
domain_label_too_long = "www." + label_too_long + ".gov"
|
||||||
self.assertFalse(Domain.isValidHost(domain_label_too_long))
|
self.assertFalse(Domain.isValidHost(domain_label_too_long))
|
||||||
|
|
||||||
|
@ -1684,9 +1586,7 @@ class TestRegistrantDNSSEC(MockEppLib):
|
||||||
"""Rule: Registrants may modify their secure DNS data"""
|
"""Rule: Registrants may modify their secure DNS data"""
|
||||||
|
|
||||||
# helper function to create UpdateDomainDNSSECExtention object for verification
|
# helper function to create UpdateDomainDNSSECExtention object for verification
|
||||||
def createUpdateExtension(
|
def createUpdateExtension(self, dnssecdata: extensions.DNSSECExtension, remove=False):
|
||||||
self, dnssecdata: extensions.DNSSECExtension, remove=False
|
|
||||||
):
|
|
||||||
if not remove:
|
if not remove:
|
||||||
return commands.UpdateDomainDNSSECExtension(
|
return commands.UpdateDomainDNSSECExtension(
|
||||||
maxSigLife=dnssecdata.maxSigLife,
|
maxSigLife=dnssecdata.maxSigLife,
|
||||||
|
@ -1946,9 +1846,7 @@ class TestRegistrantDNSSEC(MockEppLib):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(
|
self.assertEquals(dnssecdata_get.dsData, self.dnssecExtensionWithMultDsData.dsData)
|
||||||
dnssecdata_get.dsData, self.dnssecExtensionWithMultDsData.dsData
|
|
||||||
)
|
|
||||||
|
|
||||||
patcher.stop()
|
patcher.stop()
|
||||||
|
|
||||||
|
@ -2052,9 +1950,7 @@ class TestRegistrantDNSSEC(MockEppLib):
|
||||||
|
|
||||||
with self.assertRaises(RegistryError) as err:
|
with self.assertRaises(RegistryError) as err:
|
||||||
domain.dnssecdata = self.dnssecExtensionWithDsData
|
domain.dnssecdata = self.dnssecExtensionWithDsData
|
||||||
self.assertTrue(
|
self.assertTrue(err.is_client_error() or err.is_session_error() or err.is_server_error())
|
||||||
err.is_client_error() or err.is_session_error() or err.is_server_error()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestAnalystClientHold(MockEppLib):
|
class TestAnalystClientHold(MockEppLib):
|
||||||
|
@ -2068,13 +1964,9 @@ class TestAnalystClientHold(MockEppLib):
|
||||||
"""
|
"""
|
||||||
super().setUp()
|
super().setUp()
|
||||||
# for the tests, need a domain in the ready state
|
# for the tests, need a domain in the ready state
|
||||||
self.domain, _ = Domain.objects.get_or_create(
|
self.domain, _ = Domain.objects.get_or_create(name="fake.gov", state=Domain.State.READY)
|
||||||
name="fake.gov", state=Domain.State.READY
|
|
||||||
)
|
|
||||||
# for the tests, need a domain in the on_hold state
|
# for the tests, need a domain in the on_hold state
|
||||||
self.domain_on_hold, _ = Domain.objects.get_or_create(
|
self.domain_on_hold, _ = Domain.objects.get_or_create(name="fake-on-hold.gov", state=Domain.State.ON_HOLD)
|
||||||
name="fake-on-hold.gov", state=Domain.State.ON_HOLD
|
|
||||||
)
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
Domain.objects.all().delete()
|
Domain.objects.all().delete()
|
||||||
|
@ -2222,9 +2114,7 @@ class TestAnalystClientHold(MockEppLib):
|
||||||
# is_server_error; so test for those conditions
|
# is_server_error; so test for those conditions
|
||||||
with self.assertRaises(RegistryError) as err:
|
with self.assertRaises(RegistryError) as err:
|
||||||
self.domain.place_client_hold()
|
self.domain.place_client_hold()
|
||||||
self.assertTrue(
|
self.assertTrue(err.is_client_error() or err.is_session_error() or err.is_server_error())
|
||||||
err.is_client_error() or err.is_session_error() or err.is_server_error()
|
|
||||||
)
|
|
||||||
|
|
||||||
patcher.stop()
|
patcher.stop()
|
||||||
|
|
||||||
|
@ -2303,12 +2193,8 @@ class TestAnalystDelete(MockEppLib):
|
||||||
And a domain exists in the registry
|
And a domain exists in the registry
|
||||||
"""
|
"""
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.domain, _ = Domain.objects.get_or_create(
|
self.domain, _ = Domain.objects.get_or_create(name="fake.gov", state=Domain.State.READY)
|
||||||
name="fake.gov", state=Domain.State.READY
|
self.domain_on_hold, _ = Domain.objects.get_or_create(name="fake-on-hold.gov", state=Domain.State.ON_HOLD)
|
||||||
)
|
|
||||||
self.domain_on_hold, _ = Domain.objects.get_or_create(
|
|
||||||
name="fake-on-hold.gov", state=Domain.State.ON_HOLD
|
|
||||||
)
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
Domain.objects.all().delete()
|
Domain.objects.all().delete()
|
||||||
|
@ -2351,19 +2237,14 @@ class TestAnalystDelete(MockEppLib):
|
||||||
And `state` is not set to `DELETED`
|
And `state` is not set to `DELETED`
|
||||||
"""
|
"""
|
||||||
# Desired domain
|
# Desired domain
|
||||||
domain, _ = Domain.objects.get_or_create(
|
domain, _ = Domain.objects.get_or_create(name="failDelete.gov", state=Domain.State.ON_HOLD)
|
||||||
name="failDelete.gov", state=Domain.State.ON_HOLD
|
|
||||||
)
|
|
||||||
# Put the domain in client hold
|
# Put the domain in client hold
|
||||||
domain.place_client_hold()
|
domain.place_client_hold()
|
||||||
|
|
||||||
# Delete it
|
# Delete it
|
||||||
with self.assertRaises(RegistryError) as err:
|
with self.assertRaises(RegistryError) as err:
|
||||||
domain.deletedInEpp()
|
domain.deletedInEpp()
|
||||||
self.assertTrue(
|
self.assertTrue(err.is_client_error() and err.code == ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION)
|
||||||
err.is_client_error()
|
|
||||||
and err.code == ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION
|
|
||||||
)
|
|
||||||
self.mockedSendFunction.assert_has_calls(
|
self.mockedSendFunction.assert_has_calls(
|
||||||
[
|
[
|
||||||
call(
|
call(
|
||||||
|
@ -2390,10 +2271,7 @@ class TestAnalystDelete(MockEppLib):
|
||||||
self.assertEqual(self.domain.state, Domain.State.READY)
|
self.assertEqual(self.domain.state, Domain.State.READY)
|
||||||
with self.assertRaises(TransitionNotAllowed) as err:
|
with self.assertRaises(TransitionNotAllowed) as err:
|
||||||
self.domain.deletedInEpp()
|
self.domain.deletedInEpp()
|
||||||
self.assertTrue(
|
self.assertTrue(err.is_client_error() and err.code == ErrorCode.OBJECT_STATUS_PROHIBITS_OPERATION)
|
||||||
err.is_client_error()
|
|
||||||
and err.code == ErrorCode.OBJECT_STATUS_PROHIBITS_OPERATION
|
|
||||||
)
|
|
||||||
# Domain should not be deleted
|
# Domain should not be deleted
|
||||||
self.assertNotEqual(self.domain, None)
|
self.assertNotEqual(self.domain, None)
|
||||||
# Domain should have the right state
|
# Domain should have the right state
|
||||||
|
|
|
@ -12,9 +12,7 @@ class TestNameserverError(TestCase):
|
||||||
nameserver = "nameserver val"
|
nameserver = "nameserver val"
|
||||||
expected = "Using your domain for a name server requires an IP address"
|
expected = "Using your domain for a name server requires an IP address"
|
||||||
|
|
||||||
nsException = NameserverError(
|
nsException = NameserverError(code=nsErrorCodes.MISSING_IP, nameserver=nameserver)
|
||||||
code=nsErrorCodes.MISSING_IP, nameserver=nameserver
|
|
||||||
)
|
|
||||||
self.assertEqual(nsException.message, expected)
|
self.assertEqual(nsException.message, expected)
|
||||||
self.assertEqual(nsException.code, nsErrorCodes.MISSING_IP)
|
self.assertEqual(nsException.code, nsErrorCodes.MISSING_IP)
|
||||||
|
|
||||||
|
@ -24,9 +22,7 @@ class TestNameserverError(TestCase):
|
||||||
nameserver = "nameserver val"
|
nameserver = "nameserver val"
|
||||||
expected = "Too many hosts provided, you may not have more than 13 nameservers."
|
expected = "Too many hosts provided, you may not have more than 13 nameservers."
|
||||||
|
|
||||||
nsException = NameserverError(
|
nsException = NameserverError(code=nsErrorCodes.TOO_MANY_HOSTS, nameserver=nameserver)
|
||||||
code=nsErrorCodes.TOO_MANY_HOSTS, nameserver=nameserver
|
|
||||||
)
|
|
||||||
self.assertEqual(nsException.message, expected)
|
self.assertEqual(nsException.message, expected)
|
||||||
self.assertEqual(nsException.code, nsErrorCodes.TOO_MANY_HOSTS)
|
self.assertEqual(nsException.code, nsErrorCodes.TOO_MANY_HOSTS)
|
||||||
|
|
||||||
|
@ -36,8 +32,6 @@ class TestNameserverError(TestCase):
|
||||||
nameserver = "nameserver val"
|
nameserver = "nameserver val"
|
||||||
|
|
||||||
expected = f"{nameserver}: Enter an IP address in the required format."
|
expected = f"{nameserver}: Enter an IP address in the required format."
|
||||||
nsException = NameserverError(
|
nsException = NameserverError(code=nsErrorCodes.INVALID_IP, nameserver=nameserver, ip=ip)
|
||||||
code=nsErrorCodes.INVALID_IP, nameserver=nameserver, ip=ip
|
|
||||||
)
|
|
||||||
self.assertEqual(nsException.message, expected)
|
self.assertEqual(nsException.message, expected)
|
||||||
self.assertEqual(nsException.code, nsErrorCodes.INVALID_IP)
|
self.assertEqual(nsException.code, nsErrorCodes.INVALID_IP)
|
||||||
|
|
|
@ -18,21 +18,11 @@ class ExportDataTest(TestCase):
|
||||||
username=username, first_name=first_name, last_name=last_name, email=email
|
username=username, first_name=first_name, last_name=last_name, email=email
|
||||||
)
|
)
|
||||||
|
|
||||||
self.domain_1, _ = Domain.objects.get_or_create(
|
self.domain_1, _ = Domain.objects.get_or_create(name="cdomain1.gov", state=Domain.State.READY)
|
||||||
name="cdomain1.gov", state=Domain.State.READY
|
self.domain_2, _ = Domain.objects.get_or_create(name="adomain2.gov", state=Domain.State.DNS_NEEDED)
|
||||||
)
|
self.domain_3, _ = Domain.objects.get_or_create(name="ddomain3.gov", state=Domain.State.ON_HOLD)
|
||||||
self.domain_2, _ = Domain.objects.get_or_create(
|
self.domain_4, _ = Domain.objects.get_or_create(name="bdomain4.gov", state=Domain.State.UNKNOWN)
|
||||||
name="adomain2.gov", state=Domain.State.DNS_NEEDED
|
self.domain_4, _ = Domain.objects.get_or_create(name="bdomain4.gov", state=Domain.State.UNKNOWN)
|
||||||
)
|
|
||||||
self.domain_3, _ = Domain.objects.get_or_create(
|
|
||||||
name="ddomain3.gov", state=Domain.State.ON_HOLD
|
|
||||||
)
|
|
||||||
self.domain_4, _ = Domain.objects.get_or_create(
|
|
||||||
name="bdomain4.gov", state=Domain.State.UNKNOWN
|
|
||||||
)
|
|
||||||
self.domain_4, _ = Domain.objects.get_or_create(
|
|
||||||
name="bdomain4.gov", state=Domain.State.UNKNOWN
|
|
||||||
)
|
|
||||||
|
|
||||||
self.domain_information_1, _ = DomainInformation.objects.get_or_create(
|
self.domain_information_1, _ = DomainInformation.objects.get_or_create(
|
||||||
creator=self.user,
|
creator=self.user,
|
||||||
|
@ -121,16 +111,8 @@ class ExportDataTest(TestCase):
|
||||||
|
|
||||||
# Normalize line endings and remove commas,
|
# Normalize line endings and remove commas,
|
||||||
# spaces and leading/trailing whitespace
|
# spaces and leading/trailing whitespace
|
||||||
csv_content = (
|
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
|
||||||
csv_content.replace(",,", "")
|
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
|
||||||
.replace(",", "")
|
|
||||||
.replace(" ", "")
|
|
||||||
.replace("\r\n", "\n")
|
|
||||||
.strip()
|
|
||||||
)
|
|
||||||
expected_content = (
|
|
||||||
expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(csv_content, expected_content)
|
self.assertEqual(csv_content, expected_content)
|
||||||
|
|
||||||
|
@ -181,15 +163,7 @@ class ExportDataTest(TestCase):
|
||||||
|
|
||||||
# Normalize line endings and remove commas,
|
# Normalize line endings and remove commas,
|
||||||
# spaces and leading/trailing whitespace
|
# spaces and leading/trailing whitespace
|
||||||
csv_content = (
|
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
|
||||||
csv_content.replace(",,", "")
|
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
|
||||||
.replace(",", "")
|
|
||||||
.replace(" ", "")
|
|
||||||
.replace("\r\n", "\n")
|
|
||||||
.strip()
|
|
||||||
)
|
|
||||||
expected_content = (
|
|
||||||
expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(csv_content, expected_content)
|
self.assertEqual(csv_content, expected_content)
|
||||||
|
|
|
@ -58,9 +58,7 @@ class TestUserPostSave(TestCase):
|
||||||
"""Expect 1 Contact containing data copied from User."""
|
"""Expect 1 Contact containing data copied from User."""
|
||||||
# create the user
|
# create the user
|
||||||
self.assertEqual(len(Contact.objects.all()), 0)
|
self.assertEqual(len(Contact.objects.all()), 0)
|
||||||
user = get_user_model().objects.create(
|
user = get_user_model().objects.create(username=self.username, first_name="", last_name="", email="", phone="")
|
||||||
username=self.username, first_name="", last_name="", email="", phone=""
|
|
||||||
)
|
|
||||||
# delete the contact
|
# delete the contact
|
||||||
Contact.objects.all().delete()
|
Contact.objects.all().delete()
|
||||||
self.assertEqual(len(Contact.objects.all()), 0)
|
self.assertEqual(len(Contact.objects.all()), 0)
|
||||||
|
|
|
@ -23,16 +23,12 @@ class TestTemplateTags(TestCase):
|
||||||
return Template(string).render(context)
|
return Template(string).render(context)
|
||||||
|
|
||||||
def test_public_site_url(self):
|
def test_public_site_url(self):
|
||||||
result = self._render_template(
|
result = self._render_template("{% load url_helpers %}{% public_site_url 'directory/page' %}")
|
||||||
"{% load url_helpers %}{% public_site_url 'directory/page' %}"
|
|
||||||
)
|
|
||||||
self.assertTrue(result.startswith(settings.GETGOV_PUBLIC_SITE_URL))
|
self.assertTrue(result.startswith(settings.GETGOV_PUBLIC_SITE_URL))
|
||||||
self.assertTrue(result.endswith("/directory/page"))
|
self.assertTrue(result.endswith("/directory/page"))
|
||||||
|
|
||||||
def test_public_site_url_leading_slash(self):
|
def test_public_site_url_leading_slash(self):
|
||||||
result = self._render_template(
|
result = self._render_template("{% load url_helpers %}{% public_site_url '/directory/page' %}")
|
||||||
"{% load url_helpers %}{% public_site_url '/directory/page' %}"
|
|
||||||
)
|
|
||||||
self.assertTrue(result.startswith(settings.GETGOV_PUBLIC_SITE_URL))
|
self.assertTrue(result.startswith(settings.GETGOV_PUBLIC_SITE_URL))
|
||||||
# slash-slash host slash directory slash page
|
# slash-slash host slash directory slash page
|
||||||
self.assertEqual(result.count("/"), 4)
|
self.assertEqual(result.count("/"), 4)
|
||||||
|
@ -40,17 +36,11 @@ class TestTemplateTags(TestCase):
|
||||||
|
|
||||||
class CustomFiltersTestCase(TestCase):
|
class CustomFiltersTestCase(TestCase):
|
||||||
def test_extract_value_filter(self):
|
def test_extract_value_filter(self):
|
||||||
html_input = (
|
html_input = '<input type="checkbox" name="_selected_action" value="123" id="label_123" class="action-select">'
|
||||||
'<input type="checkbox" name="_selected_action" value="123" '
|
|
||||||
'id="label_123" class="action-select">'
|
|
||||||
)
|
|
||||||
result = extract_value(html_input)
|
result = extract_value(html_input)
|
||||||
self.assertEqual(result, "123")
|
self.assertEqual(result, "123")
|
||||||
|
|
||||||
html_input = (
|
html_input = '<input type="checkbox" name="_selected_action" value="abc" id="label_123" class="action-select">'
|
||||||
'<input type="checkbox" name="_selected_action" value="abc" '
|
|
||||||
'id="label_123" class="action-select">'
|
|
||||||
)
|
|
||||||
result = extract_value(html_input)
|
result = extract_value(html_input)
|
||||||
self.assertEqual(result, "abc")
|
self.assertEqual(result, "abc")
|
||||||
|
|
||||||
|
@ -81,9 +71,7 @@ class CustomFiltersTestCase(TestCase):
|
||||||
|
|
||||||
substring = "XYZ"
|
substring = "XYZ"
|
||||||
result = slice_after(value, substring)
|
result = slice_after(value, substring)
|
||||||
self.assertEqual(
|
self.assertEqual(result, value) # Should return the original value if substring not found
|
||||||
result, value
|
|
||||||
) # Should return the original value if substring not found
|
|
||||||
|
|
||||||
def test_contains_checkbox_with_checkbox(self):
|
def test_contains_checkbox_with_checkbox(self):
|
||||||
# Test the filter when HTML list contains a checkbox
|
# Test the filter when HTML list contains a checkbox
|
||||||
|
|
|
@ -85,9 +85,7 @@ class TestLogins(TestCase):
|
||||||
# Check Domain table
|
# Check Domain table
|
||||||
matching_domains = Domain.objects.filter(name=transition_domain_name)
|
matching_domains = Domain.objects.filter(name=transition_domain_name)
|
||||||
# Check Domain Information table
|
# Check Domain Information table
|
||||||
matching_domain_informations = DomainInformation.objects.filter(
|
matching_domain_informations = DomainInformation.objects.filter(domain__name=transition_domain_name)
|
||||||
domain__name=transition_domain_name
|
|
||||||
)
|
|
||||||
# Check Domain Invitation table
|
# Check Domain Invitation table
|
||||||
matching_domain_invitations = DomainInvitation.objects.filter(
|
matching_domain_invitations = DomainInvitation.objects.filter(
|
||||||
email=transition_domain_email.lower(),
|
email=transition_domain_email.lower(),
|
||||||
|
@ -129,12 +127,8 @@ class TestLogins(TestCase):
|
||||||
|
|
||||||
self.assertTrue(total_missing_domains == expected_missing_domains)
|
self.assertTrue(total_missing_domains == expected_missing_domains)
|
||||||
self.assertTrue(total_duplicate_domains == expected_duplicate_domains)
|
self.assertTrue(total_duplicate_domains == expected_duplicate_domains)
|
||||||
self.assertTrue(
|
self.assertTrue(total_missing_domain_informations == expected_missing_domain_informations)
|
||||||
total_missing_domain_informations == expected_missing_domain_informations
|
self.assertTrue(total_missing_domain_invitations == expected_missing_domain_invitations)
|
||||||
)
|
|
||||||
self.assertTrue(
|
|
||||||
total_missing_domain_invitations == expected_missing_domain_invitations
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertTrue(total_transition_domains == expected_total_transition_domains)
|
self.assertTrue(total_transition_domains == expected_total_transition_domains)
|
||||||
self.assertTrue(total_domains == expected_total_domains)
|
self.assertTrue(total_domains == expected_total_domains)
|
||||||
|
@ -234,9 +228,7 @@ class TestLogins(TestCase):
|
||||||
# Simluate Logins
|
# Simluate Logins
|
||||||
for invite in DomainInvitation.objects.all():
|
for invite in DomainInvitation.objects.all():
|
||||||
# get a user with this email address
|
# get a user with this email address
|
||||||
user, user_created = User.objects.get_or_create(
|
user, user_created = User.objects.get_or_create(email=invite.email, username=invite.email)
|
||||||
email=invite.email, username=invite.email
|
|
||||||
)
|
|
||||||
user.on_each_login()
|
user.on_each_login()
|
||||||
|
|
||||||
# Analyze the tables
|
# Analyze the tables
|
||||||
|
|
|
@ -52,9 +52,7 @@ def iter_patterns(urlconf, patterns=None, namespace=None):
|
||||||
if isinstance(pattern, URLPattern):
|
if isinstance(pattern, URLPattern):
|
||||||
viewname = pattern.name
|
viewname = pattern.name
|
||||||
if viewname is None and namespace not in NAMESPACES_WITH_UNNAMED_VIEWS:
|
if viewname is None and namespace not in NAMESPACES_WITH_UNNAMED_VIEWS:
|
||||||
raise AssertionError(
|
raise AssertionError(f"namespace {namespace} cannot contain unnamed views")
|
||||||
f"namespace {namespace} cannot contain unnamed views"
|
|
||||||
)
|
|
||||||
if namespace and viewname is not None:
|
if namespace and viewname is not None:
|
||||||
viewname = f"{namespace}:{viewname}"
|
viewname = f"{namespace}:{viewname}"
|
||||||
yield (viewname, pattern.pattern)
|
yield (viewname, pattern.pattern)
|
||||||
|
@ -65,9 +63,7 @@ def iter_patterns(urlconf, patterns=None, namespace=None):
|
||||||
raise AssertionError("nested namespaces are not currently supported")
|
raise AssertionError("nested namespaces are not currently supported")
|
||||||
if pattern.namespace in IGNORE_NAMESPACES:
|
if pattern.namespace in IGNORE_NAMESPACES:
|
||||||
continue
|
continue
|
||||||
yield from iter_patterns(
|
yield from iter_patterns(urlconf, pattern.url_patterns, namespace or pattern.namespace)
|
||||||
urlconf, pattern.url_patterns, namespace or pattern.namespace
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise AssertionError("unknown pattern class")
|
raise AssertionError("unknown pattern class")
|
||||||
|
|
||||||
|
@ -91,9 +87,7 @@ def iter_sample_urls(urlconf):
|
||||||
|
|
||||||
for kwarg in named_groups:
|
for kwarg in named_groups:
|
||||||
if kwarg not in SAMPLE_KWARGS:
|
if kwarg not in SAMPLE_KWARGS:
|
||||||
raise AssertionError(
|
raise AssertionError(f'Sample value for {kwarg} in pattern "{route}" not found')
|
||||||
f'Sample value for {kwarg} in pattern "{route}" not found'
|
|
||||||
)
|
|
||||||
kwargs[kwarg] = SAMPLE_KWARGS[kwarg]
|
kwargs[kwarg] = SAMPLE_KWARGS[kwarg]
|
||||||
|
|
||||||
url = reverse(viewname, args=args, kwargs=kwargs)
|
url = reverse(viewname, args=args, kwargs=kwargs)
|
||||||
|
@ -141,15 +135,13 @@ class TestURLAuth(TestCase):
|
||||||
self.assertRegex(
|
self.assertRegex(
|
||||||
redirect,
|
redirect,
|
||||||
r"^\/openid\/login",
|
r"^\/openid\/login",
|
||||||
f"GET {url} should redirect to login or deny access, but instead "
|
f"GET {url} should redirect to login or deny access, but instead " f"it redirects to {redirect}",
|
||||||
f"it redirects to {redirect}",
|
|
||||||
)
|
)
|
||||||
elif code == 401 or code == 403:
|
elif code == 401 or code == 403:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
f"GET {url} returned HTTP {code}, but should redirect to login or "
|
f"GET {url} returned HTTP {code}, but should redirect to login or deny access",
|
||||||
"deny access",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_login_required_all_urls(self):
|
def test_login_required_all_urls(self):
|
||||||
|
|
|
@ -79,9 +79,7 @@ class LoggedInTests(TestWithUser):
|
||||||
response = self.client.get("/")
|
response = self.client.get("/")
|
||||||
self.assertNotContains(response, "igorville.gov")
|
self.assertNotContains(response, "igorville.gov")
|
||||||
site = DraftDomain.objects.create(name="igorville.gov")
|
site = DraftDomain.objects.create(name="igorville.gov")
|
||||||
application = DomainApplication.objects.create(
|
application = DomainApplication.objects.create(creator=self.user, requested_domain=site)
|
||||||
creator=self.user, requested_domain=site
|
|
||||||
)
|
|
||||||
response = self.client.get("/")
|
response = self.client.get("/")
|
||||||
# count = 2 because it is also in screenreader content
|
# count = 2 because it is also in screenreader content
|
||||||
self.assertContains(response, "igorville.gov", count=2)
|
self.assertContains(response, "igorville.gov", count=2)
|
||||||
|
@ -92,9 +90,7 @@ class LoggedInTests(TestWithUser):
|
||||||
response = self.client.get("/")
|
response = self.client.get("/")
|
||||||
domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
||||||
self.assertNotContains(response, "igorville.gov")
|
self.assertNotContains(response, "igorville.gov")
|
||||||
role, _ = UserDomainRole.objects.get_or_create(
|
role, _ = UserDomainRole.objects.get_or_create(user=self.user, domain=domain, role=UserDomainRole.Roles.MANAGER)
|
||||||
user=self.user, domain=domain, role=UserDomainRole.Roles.MANAGER
|
|
||||||
)
|
|
||||||
response = self.client.get("/")
|
response = self.client.get("/")
|
||||||
# count = 2 because it is also in screenreader content
|
# count = 2 because it is also in screenreader content
|
||||||
self.assertContains(response, "igorville.gov", count=2)
|
self.assertContains(response, "igorville.gov", count=2)
|
||||||
|
@ -140,9 +136,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
page = self.app.get(reverse("application:")).follow()
|
page = self.app.get(reverse("application:")).follow()
|
||||||
# submitting should get back the same page if the required field is empty
|
# submitting should get back the same page if the required field is empty
|
||||||
result = page.form.submit()
|
result = page.form.submit()
|
||||||
self.assertIn(
|
self.assertIn("What kind of U.S.-based government organization do you represent?", result)
|
||||||
"What kind of U.S.-based government organization do you represent?", result
|
|
||||||
)
|
|
||||||
|
|
||||||
@boto3_mocking.patching
|
@boto3_mocking.patching
|
||||||
def test_application_form_submission(self):
|
def test_application_form_submission(self):
|
||||||
|
@ -206,9 +200,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
org_contact_page = federal_result.follow()
|
org_contact_page = federal_result.follow()
|
||||||
org_contact_form = org_contact_page.form
|
org_contact_form = org_contact_page.form
|
||||||
# federal agency so we have to fill in federal_agency
|
# federal agency so we have to fill in federal_agency
|
||||||
org_contact_form[
|
org_contact_form["organization_contact-federal_agency"] = "General Services Administration"
|
||||||
"organization_contact-federal_agency"
|
|
||||||
] = "General Services Administration"
|
|
||||||
org_contact_form["organization_contact-organization_name"] = "Testorg"
|
org_contact_form["organization_contact-organization_name"] = "Testorg"
|
||||||
org_contact_form["organization_contact-address_line1"] = "address 1"
|
org_contact_form["organization_contact-address_line1"] = "address 1"
|
||||||
org_contact_form["organization_contact-address_line2"] = "address 2"
|
org_contact_form["organization_contact-address_line2"] = "address 2"
|
||||||
|
@ -232,9 +224,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
# the post request should return a redirect to the next form in
|
# the post request should return a redirect to the next form in
|
||||||
# the application
|
# the application
|
||||||
self.assertEqual(org_contact_result.status_code, 302)
|
self.assertEqual(org_contact_result.status_code, 302)
|
||||||
self.assertEqual(
|
self.assertEqual(org_contact_result["Location"], "/register/authorizing_official/")
|
||||||
org_contact_result["Location"], "/register/authorizing_official/"
|
|
||||||
)
|
|
||||||
num_pages_tested += 1
|
num_pages_tested += 1
|
||||||
|
|
||||||
# ---- AUTHORIZING OFFICIAL PAGE ----
|
# ---- AUTHORIZING OFFICIAL PAGE ----
|
||||||
|
@ -299,9 +289,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
# validate that data from this step are being saved
|
# validate that data from this step are being saved
|
||||||
application = DomainApplication.objects.get() # there's only one
|
application = DomainApplication.objects.get() # there's only one
|
||||||
self.assertEqual(application.requested_domain.name, "city.gov")
|
self.assertEqual(application.requested_domain.name, "city.gov")
|
||||||
self.assertEqual(
|
self.assertEqual(application.alternative_domains.filter(website="city1.gov").count(), 1)
|
||||||
application.alternative_domains.filter(website="city1.gov").count(), 1
|
|
||||||
)
|
|
||||||
# the post request should return a redirect to the next form in
|
# the post request should return a redirect to the next form in
|
||||||
# the application
|
# the application
|
||||||
self.assertEqual(dotgov_result.status_code, 302)
|
self.assertEqual(dotgov_result.status_code, 302)
|
||||||
|
@ -649,9 +637,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
|
|
||||||
type_form = type_page.form
|
type_form = type_page.form
|
||||||
type_form[
|
type_form["organization_type-organization_type"] = DomainApplication.OrganizationChoices.INTERSTATE
|
||||||
"organization_type-organization_type"
|
|
||||||
] = DomainApplication.OrganizationChoices.INTERSTATE
|
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
type_result = type_page.form.submit()
|
type_result = type_page.form.submit()
|
||||||
|
|
||||||
|
@ -675,9 +661,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
# the post request should return a redirect to the
|
# the post request should return a redirect to the
|
||||||
# about your organization page if it was successful.
|
# about your organization page if it was successful.
|
||||||
self.assertEqual(contact_result.status_code, 302)
|
self.assertEqual(contact_result.status_code, 302)
|
||||||
self.assertEqual(
|
self.assertEqual(contact_result["Location"], "/register/about_your_organization/")
|
||||||
contact_result["Location"], "/register/about_your_organization/"
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_application_about_your_organization_special(self):
|
def test_application_about_your_organization_special(self):
|
||||||
"""Special districts have to answer an additional question."""
|
"""Special districts have to answer an additional question."""
|
||||||
|
@ -689,9 +673,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
|
|
||||||
type_form = type_page.form
|
type_form = type_page.form
|
||||||
type_form[
|
type_form["organization_type-organization_type"] = DomainApplication.OrganizationChoices.SPECIAL_DISTRICT
|
||||||
"organization_type-organization_type"
|
|
||||||
] = DomainApplication.OrganizationChoices.SPECIAL_DISTRICT
|
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
type_result = type_page.form.submit()
|
type_result = type_page.form.submit()
|
||||||
# follow first redirect
|
# follow first redirect
|
||||||
|
@ -728,9 +710,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
|
|
||||||
type_form = type_page.form
|
type_form = type_page.form
|
||||||
type_form[
|
type_form["organization_type-organization_type"] = DomainApplication.OrganizationChoices.INTERSTATE
|
||||||
"organization_type-organization_type"
|
|
||||||
] = DomainApplication.OrganizationChoices.INTERSTATE
|
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
type_result = type_page.form.submit()
|
type_result = type_page.form.submit()
|
||||||
# follow first redirect
|
# follow first redirect
|
||||||
|
@ -748,9 +728,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
# and then setting the cookie on each request.
|
# and then setting the cookie on each request.
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
type_form = type_page.form
|
type_form = type_page.form
|
||||||
type_form[
|
type_form["organization_type-organization_type"] = DomainApplication.OrganizationChoices.TRIBAL
|
||||||
"organization_type-organization_type"
|
|
||||||
] = DomainApplication.OrganizationChoices.TRIBAL
|
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
type_result = type_page.form.submit()
|
type_result = type_page.form.submit()
|
||||||
# the tribal government page comes immediately afterwards
|
# the tribal government page comes immediately afterwards
|
||||||
|
@ -793,9 +771,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
org_contact_page = federal_result.follow()
|
org_contact_page = federal_result.follow()
|
||||||
org_contact_form = org_contact_page.form
|
org_contact_form = org_contact_page.form
|
||||||
# federal agency so we have to fill in federal_agency
|
# federal agency so we have to fill in federal_agency
|
||||||
org_contact_form[
|
org_contact_form["organization_contact-federal_agency"] = "General Services Administration"
|
||||||
"organization_contact-federal_agency"
|
|
||||||
] = "General Services Administration"
|
|
||||||
org_contact_form["organization_contact-organization_name"] = "Testorg"
|
org_contact_form["organization_contact-organization_name"] = "Testorg"
|
||||||
org_contact_form["organization_contact-address_line1"] = "address 1"
|
org_contact_form["organization_contact-address_line1"] = "address 1"
|
||||||
org_contact_form["organization_contact-address_line2"] = "address 2"
|
org_contact_form["organization_contact-address_line2"] = "address 2"
|
||||||
|
@ -856,9 +832,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
||||||
org_contact_page = federal_result.follow()
|
org_contact_page = federal_result.follow()
|
||||||
org_contact_form = org_contact_page.form
|
org_contact_form = org_contact_page.form
|
||||||
# federal agency so we have to fill in federal_agency
|
# federal agency so we have to fill in federal_agency
|
||||||
org_contact_form[
|
org_contact_form["organization_contact-federal_agency"] = "General Services Administration"
|
||||||
"organization_contact-federal_agency"
|
|
||||||
] = "General Services Administration"
|
|
||||||
org_contact_form["organization_contact-organization_name"] = "Testorg"
|
org_contact_form["organization_contact-organization_name"] = "Testorg"
|
||||||
org_contact_form["organization_contact-address_line1"] = "address 1"
|
org_contact_form["organization_contact-address_line1"] = "address 1"
|
||||||
org_contact_form["organization_contact-address_line2"] = "address 2"
|
org_contact_form["organization_contact-address_line2"] = "address 2"
|
||||||
|
@ -1099,45 +1073,23 @@ class TestWithDomainPermissions(TestWithUser):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
self.domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
||||||
self.domain_with_ip, _ = Domain.objects.get_or_create(
|
self.domain_with_ip, _ = Domain.objects.get_or_create(name="nameserverwithip.gov")
|
||||||
name="nameserverwithip.gov"
|
self.domain_just_nameserver, _ = Domain.objects.get_or_create(name="justnameserver.com")
|
||||||
)
|
self.domain_no_information, _ = Domain.objects.get_or_create(name="noinformation.gov")
|
||||||
self.domain_just_nameserver, _ = Domain.objects.get_or_create(
|
|
||||||
name="justnameserver.com"
|
|
||||||
)
|
|
||||||
self.domain_no_information, _ = Domain.objects.get_or_create(
|
|
||||||
name="noinformation.gov"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.domain_dsdata, _ = Domain.objects.get_or_create(name="dnssec-dsdata.gov")
|
self.domain_dsdata, _ = Domain.objects.get_or_create(name="dnssec-dsdata.gov")
|
||||||
self.domain_multdsdata, _ = Domain.objects.get_or_create(
|
self.domain_multdsdata, _ = Domain.objects.get_or_create(name="dnssec-multdsdata.gov")
|
||||||
name="dnssec-multdsdata.gov"
|
|
||||||
)
|
|
||||||
# We could simply use domain (igorville) but this will be more readable in tests
|
# We could simply use domain (igorville) but this will be more readable in tests
|
||||||
# that inherit this setUp
|
# that inherit this setUp
|
||||||
self.domain_dnssec_none, _ = Domain.objects.get_or_create(
|
self.domain_dnssec_none, _ = Domain.objects.get_or_create(name="dnssec-none.gov")
|
||||||
name="dnssec-none.gov"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.domain_information, _ = DomainInformation.objects.get_or_create(
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
||||||
creator=self.user, domain=self.domain
|
|
||||||
)
|
|
||||||
|
|
||||||
DomainInformation.objects.get_or_create(
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_dsdata)
|
||||||
creator=self.user, domain=self.domain_dsdata
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_multdsdata)
|
||||||
)
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_dnssec_none)
|
||||||
DomainInformation.objects.get_or_create(
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_with_ip)
|
||||||
creator=self.user, domain=self.domain_multdsdata
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_just_nameserver)
|
||||||
)
|
|
||||||
DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user, domain=self.domain_dnssec_none
|
|
||||||
)
|
|
||||||
DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user, domain=self.domain_with_ip
|
|
||||||
)
|
|
||||||
DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user, domain=self.domain_just_nameserver
|
|
||||||
)
|
|
||||||
|
|
||||||
self.role, _ = UserDomainRole.objects.get_or_create(
|
self.role, _ = UserDomainRole.objects.get_or_create(
|
||||||
user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER
|
user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER
|
||||||
|
@ -1196,9 +1148,7 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
||||||
"domain-security-email",
|
"domain-security-email",
|
||||||
]:
|
]:
|
||||||
with self.subTest(view_name=view_name):
|
with self.subTest(view_name=view_name):
|
||||||
response = self.client.get(
|
response = self.client.get(reverse(view_name, kwargs={"pk": self.domain.id}))
|
||||||
reverse(view_name, kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
def test_no_domain_role(self):
|
def test_no_domain_role(self):
|
||||||
|
@ -1218,9 +1168,7 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
||||||
]:
|
]:
|
||||||
with self.subTest(view_name=view_name):
|
with self.subTest(view_name=view_name):
|
||||||
with less_console_noise():
|
with less_console_noise():
|
||||||
response = self.client.get(
|
response = self.client.get(reverse(view_name, kwargs={"pk": self.domain.id}))
|
||||||
reverse(view_name, kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertEqual(response.status_code, 403)
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1255,9 +1203,7 @@ class TestDomainOverview(TestWithDomainPermissions, WebTest):
|
||||||
self.assertContains(home_page, "justnameserver.com")
|
self.assertContains(home_page, "justnameserver.com")
|
||||||
|
|
||||||
# View nameserver on Domain Overview page
|
# View nameserver on Domain Overview page
|
||||||
detail_page = self.app.get(
|
detail_page = self.app.get(reverse("domain", kwargs={"pk": self.domain_just_nameserver.id}))
|
||||||
reverse("domain", kwargs={"pk": self.domain_just_nameserver.id})
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertContains(detail_page, "justnameserver.com")
|
self.assertContains(detail_page, "justnameserver.com")
|
||||||
self.assertContains(detail_page, "ns1.justnameserver.com")
|
self.assertContains(detail_page, "ns1.justnameserver.com")
|
||||||
|
@ -1268,9 +1214,7 @@ class TestDomainOverview(TestWithDomainPermissions, WebTest):
|
||||||
self.assertContains(home_page, "nameserverwithip.gov")
|
self.assertContains(home_page, "nameserverwithip.gov")
|
||||||
|
|
||||||
# View nameserver on Domain Overview page
|
# View nameserver on Domain Overview page
|
||||||
detail_page = self.app.get(
|
detail_page = self.app.get(reverse("domain", kwargs={"pk": self.domain_with_ip.id}))
|
||||||
reverse("domain", kwargs={"pk": self.domain_with_ip.id})
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertContains(detail_page, "nameserverwithip.gov")
|
self.assertContains(detail_page, "nameserverwithip.gov")
|
||||||
|
|
||||||
|
@ -1297,9 +1241,7 @@ class TestDomainOverview(TestWithDomainPermissions, WebTest):
|
||||||
session["analyst_action_location"] = self.domain_no_information.id
|
session["analyst_action_location"] = self.domain_no_information.id
|
||||||
session.save()
|
session.save()
|
||||||
|
|
||||||
detail_page = self.client.get(
|
detail_page = self.client.get(reverse("domain", kwargs={"pk": self.domain_no_information.id}))
|
||||||
reverse("domain", kwargs={"pk": self.domain_no_information.id})
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertContains(detail_page, "noinformation.gov")
|
self.assertContains(detail_page, "noinformation.gov")
|
||||||
self.assertContains(detail_page, "Domain missing domain information")
|
self.assertContains(detail_page, "Domain missing domain information")
|
||||||
|
@ -1307,33 +1249,23 @@ class TestDomainOverview(TestWithDomainPermissions, WebTest):
|
||||||
|
|
||||||
class TestDomainManagers(TestDomainOverview):
|
class TestDomainManagers(TestDomainOverview):
|
||||||
def test_domain_managers(self):
|
def test_domain_managers(self):
|
||||||
response = self.client.get(
|
response = self.client.get(reverse("domain-users", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-users", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertContains(response, "Domain managers")
|
self.assertContains(response, "Domain managers")
|
||||||
|
|
||||||
def test_domain_managers_add_link(self):
|
def test_domain_managers_add_link(self):
|
||||||
"""Button to get to user add page works."""
|
"""Button to get to user add page works."""
|
||||||
management_page = self.app.get(
|
management_page = self.app.get(reverse("domain-users", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-users", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
add_page = management_page.click("Add another user")
|
add_page = management_page.click("Add another user")
|
||||||
self.assertContains(add_page, "Add another user")
|
self.assertContains(add_page, "Add another user")
|
||||||
|
|
||||||
def test_domain_user_add(self):
|
def test_domain_user_add(self):
|
||||||
response = self.client.get(
|
response = self.client.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-users-add", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertContains(response, "Add another user")
|
self.assertContains(response, "Add another user")
|
||||||
|
|
||||||
def test_domain_user_add_form(self):
|
def test_domain_user_add_form(self):
|
||||||
"""Adding an existing user works."""
|
"""Adding an existing user works."""
|
||||||
other_user, _ = get_user_model().objects.get_or_create(
|
other_user, _ = get_user_model().objects.get_or_create(email="mayor@igorville.gov")
|
||||||
email="mayor@igorville.gov"
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||||
)
|
|
||||||
add_page = self.app.get(
|
|
||||||
reverse("domain-users-add", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
|
|
||||||
add_page.form["email"] = "mayor@igorville.gov"
|
add_page.form["email"] = "mayor@igorville.gov"
|
||||||
|
@ -1362,13 +1294,9 @@ class TestDomainManagers(TestDomainOverview):
|
||||||
EMAIL = "mayor@igorville.gov"
|
EMAIL = "mayor@igorville.gov"
|
||||||
User.objects.filter(email=EMAIL).delete()
|
User.objects.filter(email=EMAIL).delete()
|
||||||
|
|
||||||
self.domain_information, _ = DomainInformation.objects.get_or_create(
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
||||||
creator=self.user, domain=self.domain
|
|
||||||
)
|
|
||||||
|
|
||||||
add_page = self.app.get(
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-users-add", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
add_page.form["email"] = EMAIL
|
add_page.form["email"] = EMAIL
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
|
@ -1387,16 +1315,12 @@ class TestDomainManagers(TestDomainOverview):
|
||||||
EMAIL = "mayor@igorville.gov"
|
EMAIL = "mayor@igorville.gov"
|
||||||
User.objects.filter(email=EMAIL).delete()
|
User.objects.filter(email=EMAIL).delete()
|
||||||
|
|
||||||
self.domain_information, _ = DomainInformation.objects.get_or_create(
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
||||||
creator=self.user, domain=self.domain
|
|
||||||
)
|
|
||||||
|
|
||||||
mock_client = MagicMock()
|
mock_client = MagicMock()
|
||||||
mock_client_instance = mock_client.return_value
|
mock_client_instance = mock_client.return_value
|
||||||
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||||
add_page = self.app.get(
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-users-add", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
add_page.form["email"] = EMAIL
|
add_page.form["email"] = EMAIL
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
|
@ -1411,9 +1335,7 @@ class TestDomainManagers(TestDomainOverview):
|
||||||
def test_domain_invitation_cancel(self):
|
def test_domain_invitation_cancel(self):
|
||||||
"""Posting to the delete view deletes an invitation."""
|
"""Posting to the delete view deletes an invitation."""
|
||||||
EMAIL = "mayor@igorville.gov"
|
EMAIL = "mayor@igorville.gov"
|
||||||
invitation, _ = DomainInvitation.objects.get_or_create(
|
invitation, _ = DomainInvitation.objects.get_or_create(domain=self.domain, email=EMAIL)
|
||||||
domain=self.domain, email=EMAIL
|
|
||||||
)
|
|
||||||
self.client.post(reverse("invitation-delete", kwargs={"pk": invitation.id}))
|
self.client.post(reverse("invitation-delete", kwargs={"pk": invitation.id}))
|
||||||
with self.assertRaises(DomainInvitation.DoesNotExist):
|
with self.assertRaises(DomainInvitation.DoesNotExist):
|
||||||
DomainInvitation.objects.get(id=invitation.id)
|
DomainInvitation.objects.get(id=invitation.id)
|
||||||
|
@ -1421,17 +1343,13 @@ class TestDomainManagers(TestDomainOverview):
|
||||||
def test_domain_invitation_cancel_no_permissions(self):
|
def test_domain_invitation_cancel_no_permissions(self):
|
||||||
"""Posting to the delete view as a different user should fail."""
|
"""Posting to the delete view as a different user should fail."""
|
||||||
EMAIL = "mayor@igorville.gov"
|
EMAIL = "mayor@igorville.gov"
|
||||||
invitation, _ = DomainInvitation.objects.get_or_create(
|
invitation, _ = DomainInvitation.objects.get_or_create(domain=self.domain, email=EMAIL)
|
||||||
domain=self.domain, email=EMAIL
|
|
||||||
)
|
|
||||||
|
|
||||||
other_user = User()
|
other_user = User()
|
||||||
other_user.save()
|
other_user.save()
|
||||||
self.client.force_login(other_user)
|
self.client.force_login(other_user)
|
||||||
with less_console_noise(): # permission denied makes console errors
|
with less_console_noise(): # permission denied makes console errors
|
||||||
result = self.client.post(
|
result = self.client.post(reverse("invitation-delete", kwargs={"pk": invitation.id}))
|
||||||
reverse("invitation-delete", kwargs={"pk": invitation.id})
|
|
||||||
)
|
|
||||||
self.assertEqual(result.status_code, 403)
|
self.assertEqual(result.status_code, 403)
|
||||||
|
|
||||||
@boto3_mocking.patching
|
@boto3_mocking.patching
|
||||||
|
@ -1440,13 +1358,9 @@ class TestDomainManagers(TestDomainOverview):
|
||||||
EMAIL = "mayor@igorville.gov"
|
EMAIL = "mayor@igorville.gov"
|
||||||
User.objects.filter(email=EMAIL).delete()
|
User.objects.filter(email=EMAIL).delete()
|
||||||
|
|
||||||
add_page = self.app.get(
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-users-add", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
|
|
||||||
self.domain_information, _ = DomainInformation.objects.get_or_create(
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
||||||
creator=self.user, domain=self.domain
|
|
||||||
)
|
|
||||||
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
add_page.form["email"] = EMAIL
|
add_page.form["email"] = EMAIL
|
||||||
|
@ -1468,9 +1382,7 @@ class TestDomainManagers(TestDomainOverview):
|
||||||
class TestDomainNameservers(TestDomainOverview):
|
class TestDomainNameservers(TestDomainOverview):
|
||||||
def test_domain_nameservers(self):
|
def test_domain_nameservers(self):
|
||||||
"""Can load domain's nameservers page."""
|
"""Can load domain's nameservers page."""
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertContains(page, "DNS name servers")
|
self.assertContains(page, "DNS name servers")
|
||||||
|
|
||||||
def test_domain_nameservers_form_submit_one_nameserver(self):
|
def test_domain_nameservers_form_submit_one_nameserver(self):
|
||||||
|
@ -1479,9 +1391,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
Uses self.app WebTest because we need to interact with forms.
|
Uses self.app WebTest because we need to interact with forms.
|
||||||
"""
|
"""
|
||||||
# initial nameservers page has one server with two ips
|
# initial nameservers page has one server with two ips
|
||||||
nameservers_page = self.app.get(
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
# attempt to submit the form with only one nameserver, should error
|
# attempt to submit the form with only one nameserver, should error
|
||||||
|
@ -1504,9 +1414,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
Uses self.app WebTest because we need to interact with forms.
|
Uses self.app WebTest because we need to interact with forms.
|
||||||
"""
|
"""
|
||||||
# initial nameservers page has one server with two ips
|
# initial nameservers page has one server with two ips
|
||||||
nameservers_page = self.app.get(
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
# attempt to submit the form without two hosts, both subdomains,
|
# attempt to submit the form without two hosts, both subdomains,
|
||||||
|
@ -1530,9 +1438,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
Uses self.app WebTest because we need to interact with forms.
|
Uses self.app WebTest because we need to interact with forms.
|
||||||
"""
|
"""
|
||||||
# initial nameservers page has one server with two ips
|
# initial nameservers page has one server with two ips
|
||||||
nameservers_page = self.app.get(
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
# attempt to submit the form without two hosts, both subdomains,
|
# attempt to submit the form without two hosts, both subdomains,
|
||||||
|
@ -1560,9 +1466,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
nameserver2 = "ns2.igorville.com"
|
nameserver2 = "ns2.igorville.com"
|
||||||
valid_ip = "127.0.0.1"
|
valid_ip = "127.0.0.1"
|
||||||
# initial nameservers page has one server with two ips
|
# initial nameservers page has one server with two ips
|
||||||
nameservers_page = self.app.get(
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
# attempt to submit the form without two hosts, both subdomains,
|
# attempt to submit the form without two hosts, both subdomains,
|
||||||
|
@ -1590,9 +1494,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
nameserver = "ns2.igorville.gov"
|
nameserver = "ns2.igorville.gov"
|
||||||
invalid_ip = "123"
|
invalid_ip = "123"
|
||||||
# initial nameservers page has one server with two ips
|
# initial nameservers page has one server with two ips
|
||||||
nameservers_page = self.app.get(
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
# attempt to submit the form without two hosts, both subdomains,
|
# attempt to submit the form without two hosts, both subdomains,
|
||||||
|
@ -1606,11 +1508,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
# the required field. nameserver has ip but missing host
|
# the required field. nameserver has ip but missing host
|
||||||
self.assertContains(
|
self.assertContains(
|
||||||
result,
|
result,
|
||||||
str(
|
str(NameserverError(code=NameserverErrorCodes.INVALID_IP, nameserver=nameserver)),
|
||||||
NameserverError(
|
|
||||||
code=NameserverErrorCodes.INVALID_IP, nameserver=nameserver
|
|
||||||
)
|
|
||||||
),
|
|
||||||
count=2,
|
count=2,
|
||||||
status_code=200,
|
status_code=200,
|
||||||
)
|
)
|
||||||
|
@ -1623,9 +1521,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
nameserver = "invalid-nameserver.gov"
|
nameserver = "invalid-nameserver.gov"
|
||||||
valid_ip = "123.2.45.111"
|
valid_ip = "123.2.45.111"
|
||||||
# initial nameservers page has one server with two ips
|
# initial nameservers page has one server with two ips
|
||||||
nameservers_page = self.app.get(
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
# attempt to submit the form without two hosts, both subdomains,
|
# attempt to submit the form without two hosts, both subdomains,
|
||||||
|
@ -1639,11 +1535,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
# the required field. nameserver has invalid host
|
# the required field. nameserver has invalid host
|
||||||
self.assertContains(
|
self.assertContains(
|
||||||
result,
|
result,
|
||||||
str(
|
str(NameserverError(code=NameserverErrorCodes.INVALID_HOST, nameserver=nameserver)),
|
||||||
NameserverError(
|
|
||||||
code=NameserverErrorCodes.INVALID_HOST, nameserver=nameserver
|
|
||||||
)
|
|
||||||
),
|
|
||||||
count=2,
|
count=2,
|
||||||
status_code=200,
|
status_code=200,
|
||||||
)
|
)
|
||||||
|
@ -1657,9 +1549,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
nameserver2 = "ns2.igorville.gov"
|
nameserver2 = "ns2.igorville.gov"
|
||||||
invalid_ip = "127.0.0.1"
|
invalid_ip = "127.0.0.1"
|
||||||
# initial nameservers page has one server with two ips
|
# initial nameservers page has one server with two ips
|
||||||
nameservers_page = self.app.get(
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
# attempt to submit the form without two hosts, both subdomains,
|
# attempt to submit the form without two hosts, both subdomains,
|
||||||
|
@ -1684,9 +1574,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
|
|
||||||
Uses self.app WebTest because we need to interact with forms.
|
Uses self.app WebTest because we need to interact with forms.
|
||||||
"""
|
"""
|
||||||
nameservers_page = self.app.get(
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
# first two nameservers are required, so if we empty one out we should
|
# first two nameservers are required, so if we empty one out we should
|
||||||
|
@ -1708,9 +1596,7 @@ class TestDomainNameservers(TestDomainOverview):
|
||||||
class TestDomainAuthorizingOfficial(TestDomainOverview):
|
class TestDomainAuthorizingOfficial(TestDomainOverview):
|
||||||
def test_domain_authorizing_official(self):
|
def test_domain_authorizing_official(self):
|
||||||
"""Can load domain's authorizing official page."""
|
"""Can load domain's authorizing official page."""
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-authorizing-official", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-authorizing-official", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
# once on the sidebar, once in the title
|
# once on the sidebar, once in the title
|
||||||
self.assertContains(page, "Authorizing official", count=2)
|
self.assertContains(page, "Authorizing official", count=2)
|
||||||
|
|
||||||
|
@ -1719,18 +1605,14 @@ class TestDomainAuthorizingOfficial(TestDomainOverview):
|
||||||
self.domain_information.authorizing_official = Contact(first_name="Testy")
|
self.domain_information.authorizing_official = Contact(first_name="Testy")
|
||||||
self.domain_information.authorizing_official.save()
|
self.domain_information.authorizing_official.save()
|
||||||
self.domain_information.save()
|
self.domain_information.save()
|
||||||
page = self.app.get(
|
page = self.app.get(reverse("domain-authorizing-official", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-authorizing-official", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertContains(page, "Testy")
|
self.assertContains(page, "Testy")
|
||||||
|
|
||||||
|
|
||||||
class TestDomainOrganization(TestDomainOverview):
|
class TestDomainOrganization(TestDomainOverview):
|
||||||
def test_domain_org_name_address(self):
|
def test_domain_org_name_address(self):
|
||||||
"""Can load domain's org name and mailing address page."""
|
"""Can load domain's org name and mailing address page."""
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-org-name-address", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
# once on the sidebar, once in the page title, once as H1
|
# once on the sidebar, once in the page title, once as H1
|
||||||
self.assertContains(page, "Organization name and mailing address", count=3)
|
self.assertContains(page, "Organization name and mailing address", count=3)
|
||||||
|
|
||||||
|
@ -1738,18 +1620,14 @@ class TestDomainOrganization(TestDomainOverview):
|
||||||
"""Org name and address information appears on the page."""
|
"""Org name and address information appears on the page."""
|
||||||
self.domain_information.organization_name = "Town of Igorville"
|
self.domain_information.organization_name = "Town of Igorville"
|
||||||
self.domain_information.save()
|
self.domain_information.save()
|
||||||
page = self.app.get(
|
page = self.app.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-org-name-address", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertContains(page, "Town of Igorville")
|
self.assertContains(page, "Town of Igorville")
|
||||||
|
|
||||||
def test_domain_org_name_address_form(self):
|
def test_domain_org_name_address_form(self):
|
||||||
"""Submitting changes works on the org name address page."""
|
"""Submitting changes works on the org name address page."""
|
||||||
self.domain_information.organization_name = "Town of Igorville"
|
self.domain_information.organization_name = "Town of Igorville"
|
||||||
self.domain_information.save()
|
self.domain_information.save()
|
||||||
org_name_page = self.app.get(
|
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-org-name-address", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
|
|
||||||
org_name_page.form["organization_name"] = "Not igorville"
|
org_name_page.form["organization_name"] = "Not igorville"
|
||||||
|
@ -1766,18 +1644,14 @@ class TestDomainOrganization(TestDomainOverview):
|
||||||
class TestDomainContactInformation(TestDomainOverview):
|
class TestDomainContactInformation(TestDomainOverview):
|
||||||
def test_domain_your_contact_information(self):
|
def test_domain_your_contact_information(self):
|
||||||
"""Can load domain's your contact information page."""
|
"""Can load domain's your contact information page."""
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-your-contact-information", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-your-contact-information", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertContains(page, "Your contact information")
|
self.assertContains(page, "Your contact information")
|
||||||
|
|
||||||
def test_domain_your_contact_information_content(self):
|
def test_domain_your_contact_information_content(self):
|
||||||
"""Logged-in user's contact information appears on the page."""
|
"""Logged-in user's contact information appears on the page."""
|
||||||
self.user.contact.first_name = "Testy"
|
self.user.contact.first_name = "Testy"
|
||||||
self.user.contact.save()
|
self.user.contact.save()
|
||||||
page = self.app.get(
|
page = self.app.get(reverse("domain-your-contact-information", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-your-contact-information", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertContains(page, "Testy")
|
self.assertContains(page, "Testy")
|
||||||
|
|
||||||
|
|
||||||
|
@ -1791,9 +1665,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
||||||
domain_contact, _ = Domain.objects.get_or_create(name="freeman.gov")
|
domain_contact, _ = Domain.objects.get_or_create(name="freeman.gov")
|
||||||
# Add current user to this domain
|
# Add current user to this domain
|
||||||
_ = UserDomainRole(user=self.user, domain=domain_contact, role="admin").save()
|
_ = UserDomainRole(user=self.user, domain=domain_contact, role="admin").save()
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-security-email", kwargs={"pk": domain_contact.id}))
|
||||||
reverse("domain-security-email", kwargs={"pk": domain_contact.id})
|
|
||||||
)
|
|
||||||
|
|
||||||
# Loads correctly
|
# Loads correctly
|
||||||
self.assertContains(page, "Security email")
|
self.assertContains(page, "Security email")
|
||||||
|
@ -1807,9 +1679,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
||||||
self.mockedSendFunction = self.mockSendPatch.start()
|
self.mockedSendFunction = self.mockSendPatch.start()
|
||||||
self.mockedSendFunction.side_effect = self.mockSend
|
self.mockedSendFunction.side_effect = self.mockSend
|
||||||
|
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-security-email", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-security-email", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
|
|
||||||
# Loads correctly
|
# Loads correctly
|
||||||
self.assertContains(page, "Security email")
|
self.assertContains(page, "Security email")
|
||||||
|
@ -1818,18 +1688,14 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
||||||
|
|
||||||
def test_domain_security_email(self):
|
def test_domain_security_email(self):
|
||||||
"""Can load domain's security email page."""
|
"""Can load domain's security email page."""
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-security-email", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-security-email", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertContains(page, "Security email")
|
self.assertContains(page, "Security email")
|
||||||
|
|
||||||
def test_domain_security_email_form(self):
|
def test_domain_security_email_form(self):
|
||||||
"""Adding a security email works.
|
"""Adding a security email works.
|
||||||
Uses self.app WebTest because we need to interact with forms.
|
Uses self.app WebTest because we need to interact with forms.
|
||||||
"""
|
"""
|
||||||
security_email_page = self.app.get(
|
security_email_page = self.app.get(reverse("domain-security-email", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-security-email", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
security_email_page.form["security_email"] = "mayor@igorville.gov"
|
security_email_page.form["security_email"] = "mayor@igorville.gov"
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
|
@ -1843,9 +1709,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
||||||
|
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
success_page = result.follow()
|
success_page = result.follow()
|
||||||
self.assertContains(
|
self.assertContains(success_page, "The security email for this domain has been updated")
|
||||||
success_page, "The security email for this domain has been updated"
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_security_email_form_messages(self):
|
def test_security_email_form_messages(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1932,18 +1796,14 @@ class TestDomainDNSSEC(TestDomainOverview):
|
||||||
"""DNSSEC overview page loads when domain has no DNSSEC data
|
"""DNSSEC overview page loads when domain has no DNSSEC data
|
||||||
and shows a 'Enable DNSSEC' button."""
|
and shows a 'Enable DNSSEC' button."""
|
||||||
|
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id}))
|
||||||
reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id})
|
|
||||||
)
|
|
||||||
self.assertContains(page, "Enable DNSSEC")
|
self.assertContains(page, "Enable DNSSEC")
|
||||||
|
|
||||||
def test_dnssec_page_loads_with_data_in_domain(self):
|
def test_dnssec_page_loads_with_data_in_domain(self):
|
||||||
"""DNSSEC overview page loads when domain has DNSSEC data
|
"""DNSSEC overview page loads when domain has DNSSEC data
|
||||||
and the template contains a button to disable DNSSEC."""
|
and the template contains a button to disable DNSSEC."""
|
||||||
|
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"pk": self.domain_multdsdata.id}))
|
||||||
reverse("domain-dns-dnssec", kwargs={"pk": self.domain_multdsdata.id})
|
|
||||||
)
|
|
||||||
self.assertContains(page, "Disable DNSSEC")
|
self.assertContains(page, "Disable DNSSEC")
|
||||||
|
|
||||||
# Prepare the data for the POST request
|
# Prepare the data for the POST request
|
||||||
|
@ -1964,11 +1824,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
||||||
"""DNSSEC Add DS Data page loads when there is no
|
"""DNSSEC Add DS Data page loads when there is no
|
||||||
domain DNSSEC data and shows a button to Add new record"""
|
domain DNSSEC data and shows a button to Add new record"""
|
||||||
|
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dnssec_none.id}))
|
||||||
reverse(
|
|
||||||
"domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dnssec_none.id}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.assertContains(page, "You have no DS Data added")
|
self.assertContains(page, "You have no DS Data added")
|
||||||
self.assertContains(page, "Add new record")
|
self.assertContains(page, "Add new record")
|
||||||
|
|
||||||
|
@ -1976,16 +1832,12 @@ class TestDomainDNSSEC(TestDomainOverview):
|
||||||
"""DNSSEC Add DS Data page loads when there is
|
"""DNSSEC Add DS Data page loads when there is
|
||||||
domain DNSSEC DS data and shows the data"""
|
domain DNSSEC DS data and shows the data"""
|
||||||
|
|
||||||
page = self.client.get(
|
page = self.client.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||||
reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id})
|
|
||||||
)
|
|
||||||
self.assertContains(page, "DS Data record 1")
|
self.assertContains(page, "DS Data record 1")
|
||||||
|
|
||||||
def test_ds_data_form_modal(self):
|
def test_ds_data_form_modal(self):
|
||||||
"""When user clicks on save, a modal pops up."""
|
"""When user clicks on save, a modal pops up."""
|
||||||
add_data_page = self.app.get(
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||||
reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id})
|
|
||||||
)
|
|
||||||
# Assert that a hidden trigger for the modal does not exist.
|
# Assert that a hidden trigger for the modal does not exist.
|
||||||
# This hidden trigger will pop on the page when certain condition are met:
|
# This hidden trigger will pop on the page when certain condition are met:
|
||||||
# 1) Initial form contained DS data, 2) All data is deleted and form is
|
# 1) Initial form contained DS data, 2) All data is deleted and form is
|
||||||
|
@ -2006,9 +1858,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
||||||
|
|
||||||
Uses self.app WebTest because we need to interact with forms.
|
Uses self.app WebTest because we need to interact with forms.
|
||||||
"""
|
"""
|
||||||
add_data_page = self.app.get(
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||||
reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
with less_console_noise(): # swallow log warning message
|
with less_console_noise(): # swallow log warning message
|
||||||
|
@ -2021,18 +1871,14 @@ class TestDomainDNSSEC(TestDomainOverview):
|
||||||
)
|
)
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
page = result.follow()
|
page = result.follow()
|
||||||
self.assertContains(
|
self.assertContains(page, "The DS Data records for this domain have been updated.")
|
||||||
page, "The DS Data records for this domain have been updated."
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_ds_data_form_invalid(self):
|
def test_ds_data_form_invalid(self):
|
||||||
"""DS Data form errors with invalid data
|
"""DS Data form errors with invalid data
|
||||||
|
|
||||||
Uses self.app WebTest because we need to interact with forms.
|
Uses self.app WebTest because we need to interact with forms.
|
||||||
"""
|
"""
|
||||||
add_data_page = self.app.get(
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||||
reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id})
|
|
||||||
)
|
|
||||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||||
# first two nameservers are required, so if we empty one out we should
|
# first two nameservers are required, so if we empty one out we should
|
||||||
|
@ -2054,9 +1900,7 @@ class TestApplicationStatus(TestWithUser, WebTest):
|
||||||
|
|
||||||
def test_application_status(self):
|
def test_application_status(self):
|
||||||
"""Checking application status page"""
|
"""Checking application status page"""
|
||||||
application = completed_application(
|
application = completed_application(status=DomainApplication.SUBMITTED, user=self.user)
|
||||||
status=DomainApplication.SUBMITTED, user=self.user
|
|
||||||
)
|
|
||||||
application.save()
|
application.save()
|
||||||
|
|
||||||
home_page = self.app.get("/")
|
home_page = self.app.get("/")
|
||||||
|
@ -2076,9 +1920,7 @@ class TestApplicationStatus(TestWithUser, WebTest):
|
||||||
self.user.status = "ineligible"
|
self.user.status = "ineligible"
|
||||||
self.user.save()
|
self.user.save()
|
||||||
|
|
||||||
application = completed_application(
|
application = completed_application(status=DomainApplication.SUBMITTED, user=self.user)
|
||||||
status=DomainApplication.SUBMITTED, user=self.user
|
|
||||||
)
|
|
||||||
application.save()
|
application.save()
|
||||||
|
|
||||||
home_page = self.app.get("/")
|
home_page = self.app.get("/")
|
||||||
|
@ -2093,9 +1935,7 @@ class TestApplicationStatus(TestWithUser, WebTest):
|
||||||
|
|
||||||
def test_application_withdraw(self):
|
def test_application_withdraw(self):
|
||||||
"""Checking application status page"""
|
"""Checking application status page"""
|
||||||
application = completed_application(
|
application = completed_application(status=DomainApplication.SUBMITTED, user=self.user)
|
||||||
status=DomainApplication.SUBMITTED, user=self.user
|
|
||||||
)
|
|
||||||
application.save()
|
application.save()
|
||||||
|
|
||||||
home_page = self.app.get("/")
|
home_page = self.app.get("/")
|
||||||
|
@ -2125,9 +1965,7 @@ class TestApplicationStatus(TestWithUser, WebTest):
|
||||||
|
|
||||||
def test_application_status_no_permissions(self):
|
def test_application_status_no_permissions(self):
|
||||||
"""Can't access applications without being the creator."""
|
"""Can't access applications without being the creator."""
|
||||||
application = completed_application(
|
application = completed_application(status=DomainApplication.SUBMITTED, user=self.user)
|
||||||
status=DomainApplication.SUBMITTED, user=self.user
|
|
||||||
)
|
|
||||||
other_user = User()
|
other_user = User()
|
||||||
other_user.save()
|
other_user.save()
|
||||||
application.creator = other_user
|
application.creator = other_user
|
||||||
|
@ -2141,17 +1979,13 @@ class TestApplicationStatus(TestWithUser, WebTest):
|
||||||
"application-withdrawn",
|
"application-withdrawn",
|
||||||
]:
|
]:
|
||||||
with self.subTest(url_name=url_name):
|
with self.subTest(url_name=url_name):
|
||||||
page = self.client.get(
|
page = self.client.get(reverse(url_name, kwargs={"pk": application.pk}))
|
||||||
reverse(url_name, kwargs={"pk": application.pk})
|
|
||||||
)
|
|
||||||
self.assertEqual(page.status_code, 403)
|
self.assertEqual(page.status_code, 403)
|
||||||
|
|
||||||
def test_approved_application_not_in_active_requests(self):
|
def test_approved_application_not_in_active_requests(self):
|
||||||
"""An approved application is not shown in the Active
|
"""An approved application is not shown in the Active
|
||||||
Requests table on home.html."""
|
Requests table on home.html."""
|
||||||
application = completed_application(
|
application = completed_application(status=DomainApplication.APPROVED, user=self.user)
|
||||||
status=DomainApplication.APPROVED, user=self.user
|
|
||||||
)
|
|
||||||
application.save()
|
application.save()
|
||||||
|
|
||||||
home_page = self.app.get("/")
|
home_page = self.app.get("/")
|
||||||
|
|
|
@ -10,37 +10,25 @@ def export_domains_to_writer(writer, columns, sort_fields, filter_condition):
|
||||||
# write columns headers to writer
|
# write columns headers to writer
|
||||||
writer.writerow(columns)
|
writer.writerow(columns)
|
||||||
|
|
||||||
domainInfos = DomainInformation.objects.filter(**filter_condition).order_by(
|
domainInfos = DomainInformation.objects.filter(**filter_condition).order_by(*sort_fields)
|
||||||
*sort_fields
|
|
||||||
)
|
|
||||||
for domainInfo in domainInfos:
|
for domainInfo in domainInfos:
|
||||||
security_contacts = domainInfo.domain.contacts.filter(
|
security_contacts = domainInfo.domain.contacts.filter(contact_type=PublicContact.ContactTypeChoices.SECURITY)
|
||||||
contact_type=PublicContact.ContactTypeChoices.SECURITY
|
|
||||||
)
|
|
||||||
|
|
||||||
# create a dictionary of fields which can be included in output
|
# create a dictionary of fields which can be included in output
|
||||||
FIELDS = {
|
FIELDS = {
|
||||||
"Domain name": domainInfo.domain.name,
|
"Domain name": domainInfo.domain.name,
|
||||||
"Domain type": domainInfo.get_organization_type_display()
|
"Domain type": domainInfo.get_organization_type_display() + " - " + domainInfo.get_federal_type_display()
|
||||||
+ " - "
|
|
||||||
+ domainInfo.get_federal_type_display()
|
|
||||||
if domainInfo.federal_type
|
if domainInfo.federal_type
|
||||||
else domainInfo.get_organization_type_display(),
|
else domainInfo.get_organization_type_display(),
|
||||||
"Agency": domainInfo.federal_agency,
|
"Agency": domainInfo.federal_agency,
|
||||||
"Organization name": domainInfo.organization_name,
|
"Organization name": domainInfo.organization_name,
|
||||||
"City": domainInfo.city,
|
"City": domainInfo.city,
|
||||||
"State": domainInfo.state_territory,
|
"State": domainInfo.state_territory,
|
||||||
"AO": domainInfo.authorizing_official.first_name
|
"AO": domainInfo.authorizing_official.first_name + " " + domainInfo.authorizing_official.last_name
|
||||||
+ " "
|
|
||||||
+ domainInfo.authorizing_official.last_name
|
|
||||||
if domainInfo.authorizing_official
|
if domainInfo.authorizing_official
|
||||||
else " ",
|
else " ",
|
||||||
"AO email": domainInfo.authorizing_official.email
|
"AO email": domainInfo.authorizing_official.email if domainInfo.authorizing_official else " ",
|
||||||
if domainInfo.authorizing_official
|
"Security Contact Email": security_contacts[0].email if security_contacts else " ",
|
||||||
else " ",
|
|
||||||
"Security Contact Email": security_contacts[0].email
|
|
||||||
if security_contacts
|
|
||||||
else " ",
|
|
||||||
"Status": domainInfo.domain.state,
|
"Status": domainInfo.domain.state,
|
||||||
"Expiration Date": domainInfo.domain.expiration_date,
|
"Expiration Date": domainInfo.domain.expiration_date,
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,7 @@ class EmailSendingError(RuntimeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def send_templated_email(
|
def send_templated_email(template_name: str, subject_template_name: str, to_address: str, context={}):
|
||||||
template_name: str, subject_template_name: str, to_address: str, context={}
|
|
||||||
):
|
|
||||||
"""Send an email built from a template to one email address.
|
"""Send an email built from a template to one email address.
|
||||||
|
|
||||||
template_name and subject_template_name are relative to the same template
|
template_name and subject_template_name are relative to the same template
|
||||||
|
|
|
@ -87,28 +87,15 @@ class NameserverError(Exception):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_error_mapping = {
|
_error_mapping = {
|
||||||
NameserverErrorCodes.MISSING_IP: (
|
NameserverErrorCodes.MISSING_IP: ("Using your domain for a name server requires an IP address"),
|
||||||
"Using your domain for a name server requires an IP address"
|
NameserverErrorCodes.GLUE_RECORD_NOT_ALLOWED: ("Name server address does not match domain name"),
|
||||||
),
|
NameserverErrorCodes.INVALID_IP: ("{}: Enter an IP address in the required format."),
|
||||||
NameserverErrorCodes.GLUE_RECORD_NOT_ALLOWED: (
|
NameserverErrorCodes.TOO_MANY_HOSTS: ("Too many hosts provided, you may not have more than 13 nameservers."),
|
||||||
"Name server address does not match domain name"
|
|
||||||
),
|
|
||||||
NameserverErrorCodes.INVALID_IP: (
|
|
||||||
"{}: Enter an IP address in the required format."
|
|
||||||
),
|
|
||||||
NameserverErrorCodes.TOO_MANY_HOSTS: (
|
|
||||||
"Too many hosts provided, you may not have more than 13 nameservers."
|
|
||||||
),
|
|
||||||
NameserverErrorCodes.UNABLE_TO_UPDATE_DOMAIN: (
|
NameserverErrorCodes.UNABLE_TO_UPDATE_DOMAIN: (
|
||||||
"Unable to update domain, changes were not applied."
|
"Unable to update domain, changes were not applied. Check logs as a Registry Error is the likely cause"
|
||||||
"Check logs as a Registry Error is the likely cause"
|
|
||||||
),
|
|
||||||
NameserverErrorCodes.MISSING_HOST: (
|
|
||||||
"Name server must be provided to enter IP address."
|
|
||||||
),
|
|
||||||
NameserverErrorCodes.INVALID_HOST: (
|
|
||||||
"Enter a name server in the required format, like ns1.example.com"
|
|
||||||
),
|
),
|
||||||
|
NameserverErrorCodes.MISSING_HOST: ("Name server must be provided to enter IP address."),
|
||||||
|
NameserverErrorCodes.INVALID_HOST: ("Enter a name server in the required format, like ns1.example.com"),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, code=None, nameserver=None, ip=None, **kwargs):
|
def __init__(self, *args, code=None, nameserver=None, ip=None, **kwargs):
|
||||||
|
|
|
@ -93,19 +93,11 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
||||||
# We can use a dictionary with step names and callables that return booleans
|
# We can use a dictionary with step names and callables that return booleans
|
||||||
# to show or hide particular steps based on the state of the process.
|
# to show or hide particular steps based on the state of the process.
|
||||||
WIZARD_CONDITIONS = {
|
WIZARD_CONDITIONS = {
|
||||||
Step.ORGANIZATION_FEDERAL: lambda w: w.from_model(
|
Step.ORGANIZATION_FEDERAL: lambda w: w.from_model("show_organization_federal", False),
|
||||||
"show_organization_federal", False
|
|
||||||
),
|
|
||||||
Step.TRIBAL_GOVERNMENT: lambda w: w.from_model("show_tribal_government", False),
|
Step.TRIBAL_GOVERNMENT: lambda w: w.from_model("show_tribal_government", False),
|
||||||
Step.ORGANIZATION_ELECTION: lambda w: w.from_model(
|
Step.ORGANIZATION_ELECTION: lambda w: w.from_model("show_organization_election", False),
|
||||||
"show_organization_election", False
|
Step.ABOUT_YOUR_ORGANIZATION: lambda w: w.from_model("show_about_your_organization", False),
|
||||||
),
|
Step.NO_OTHER_CONTACTS: lambda w: w.from_model("show_no_other_contacts_rationale", False),
|
||||||
Step.ABOUT_YOUR_ORGANIZATION: lambda w: w.from_model(
|
|
||||||
"show_about_your_organization", False
|
|
||||||
),
|
|
||||||
Step.NO_OTHER_CONTACTS: lambda w: w.from_model(
|
|
||||||
"show_no_other_contacts_rationale", False
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
@ -170,9 +170,7 @@ class DomainOrgNameAddressView(DomainFormBaseView):
|
||||||
"""The form is valid, save the organization name and mailing address."""
|
"""The form is valid, save the organization name and mailing address."""
|
||||||
form.save()
|
form.save()
|
||||||
|
|
||||||
messages.success(
|
messages.success(self.request, "The organization name and mailing address has been updated.")
|
||||||
self.request, "The organization name and mailing address has been updated."
|
|
||||||
)
|
|
||||||
|
|
||||||
# superclass has the redirect
|
# superclass has the redirect
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
@ -200,9 +198,7 @@ class DomainAuthorizingOfficialView(DomainFormBaseView):
|
||||||
"""The form is valid, save the authorizing official."""
|
"""The form is valid, save the authorizing official."""
|
||||||
form.save()
|
form.save()
|
||||||
|
|
||||||
messages.success(
|
messages.success(self.request, "The authorizing official for this domain has been updated.")
|
||||||
self.request, "The authorizing official for this domain has been updated."
|
|
||||||
)
|
|
||||||
|
|
||||||
# superclass has the redirect
|
# superclass has the redirect
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
@ -228,9 +224,7 @@ class DomainNameserversView(DomainFormBaseView):
|
||||||
|
|
||||||
if nameservers is not None:
|
if nameservers is not None:
|
||||||
# Add existing nameservers as initial data
|
# Add existing nameservers as initial data
|
||||||
initial_data.extend(
|
initial_data.extend({"server": name, "ip": ",".join(ip)} for name, ip in nameservers)
|
||||||
{"server": name, "ip": ",".join(ip)} for name, ip in nameservers
|
|
||||||
)
|
|
||||||
|
|
||||||
# Ensure at least 3 fields, filled or empty
|
# Ensure at least 3 fields, filled or empty
|
||||||
while len(initial_data) < 2:
|
while len(initial_data) < 2:
|
||||||
|
@ -310,9 +304,7 @@ class DomainNameserversView(DomainFormBaseView):
|
||||||
except NameserverError as Err:
|
except NameserverError as Err:
|
||||||
# NamserverErrors *should* be caught in form; if reached here,
|
# NamserverErrors *should* be caught in form; if reached here,
|
||||||
# there was an uncaught error in submission (through EPP)
|
# there was an uncaught error in submission (through EPP)
|
||||||
messages.error(
|
messages.error(self.request, NameserverError(code=nsErrorCodes.UNABLE_TO_UPDATE_DOMAIN))
|
||||||
self.request, NameserverError(code=nsErrorCodes.UNABLE_TO_UPDATE_DOMAIN)
|
|
||||||
)
|
|
||||||
logger.error(f"Nameservers error: {Err}")
|
logger.error(f"Nameservers error: {Err}")
|
||||||
# TODO: registry is not throwing an error when no connection
|
# TODO: registry is not throwing an error when no connection
|
||||||
except RegistryError as Err:
|
except RegistryError as Err:
|
||||||
|
@ -323,9 +315,7 @@ class DomainNameserversView(DomainFormBaseView):
|
||||||
)
|
)
|
||||||
logger.error(f"Registry connection error: {Err}")
|
logger.error(f"Registry connection error: {Err}")
|
||||||
else:
|
else:
|
||||||
messages.error(
|
messages.error(self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR))
|
||||||
self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR)
|
|
||||||
)
|
|
||||||
logger.error(f"Registry error: {Err}")
|
logger.error(f"Registry error: {Err}")
|
||||||
else:
|
else:
|
||||||
messages.success(
|
messages.success(
|
||||||
|
@ -501,15 +491,11 @@ class DomainDsDataView(DomainFormBaseView):
|
||||||
)
|
)
|
||||||
logger.error(f"Registry connection error: {err}")
|
logger.error(f"Registry connection error: {err}")
|
||||||
else:
|
else:
|
||||||
messages.error(
|
messages.error(self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR))
|
||||||
self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR)
|
|
||||||
)
|
|
||||||
logger.error(f"Registry error: {err}")
|
logger.error(f"Registry error: {err}")
|
||||||
return self.form_invalid(formset)
|
return self.form_invalid(formset)
|
||||||
else:
|
else:
|
||||||
messages.success(
|
messages.success(self.request, "The DS Data records for this domain have been updated.")
|
||||||
self.request, "The DS Data records for this domain have been updated."
|
|
||||||
)
|
|
||||||
# superclass has the redirect
|
# superclass has the redirect
|
||||||
return super().form_valid(formset)
|
return super().form_valid(formset)
|
||||||
|
|
||||||
|
@ -536,9 +522,7 @@ class DomainYourContactInformationView(DomainFormBaseView):
|
||||||
# Post to DB using values from the form
|
# Post to DB using values from the form
|
||||||
form.save()
|
form.save()
|
||||||
|
|
||||||
messages.success(
|
messages.success(self.request, "Your contact information for this domain has been updated.")
|
||||||
self.request, "Your contact information for this domain has been updated."
|
|
||||||
)
|
|
||||||
|
|
||||||
# superclass has the redirect
|
# superclass has the redirect
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
@ -597,19 +581,13 @@ class DomainSecurityEmailView(DomainFormBaseView):
|
||||||
)
|
)
|
||||||
logger.error(f"Registry connection error: {Err}")
|
logger.error(f"Registry connection error: {Err}")
|
||||||
else:
|
else:
|
||||||
messages.error(
|
messages.error(self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR))
|
||||||
self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR)
|
|
||||||
)
|
|
||||||
logger.error(f"Registry error: {Err}")
|
logger.error(f"Registry error: {Err}")
|
||||||
except ContactError as Err:
|
except ContactError as Err:
|
||||||
messages.error(
|
messages.error(self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR))
|
||||||
self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR)
|
|
||||||
)
|
|
||||||
logger.error(f"Generic registry error: {Err}")
|
logger.error(f"Generic registry error: {Err}")
|
||||||
else:
|
else:
|
||||||
messages.success(
|
messages.success(self.request, "The security email for this domain has been updated.")
|
||||||
self.request, "The security email for this domain has been updated."
|
|
||||||
)
|
|
||||||
|
|
||||||
# superclass has the redirect
|
# superclass has the redirect
|
||||||
return redirect(self.get_success_url())
|
return redirect(self.get_success_url())
|
||||||
|
@ -636,15 +614,11 @@ class DomainAddUserView(DomainFormBaseView):
|
||||||
|
|
||||||
def _domain_abs_url(self):
|
def _domain_abs_url(self):
|
||||||
"""Get an absolute URL for this domain."""
|
"""Get an absolute URL for this domain."""
|
||||||
return self.request.build_absolute_uri(
|
return self.request.build_absolute_uri(reverse("domain", kwargs={"pk": self.object.id}))
|
||||||
reverse("domain", kwargs={"pk": self.object.id})
|
|
||||||
)
|
|
||||||
|
|
||||||
def _make_invitation(self, email_address):
|
def _make_invitation(self, email_address):
|
||||||
"""Make a Domain invitation for this email and redirect with a message."""
|
"""Make a Domain invitation for this email and redirect with a message."""
|
||||||
invitation, created = DomainInvitation.objects.get_or_create(
|
invitation, created = DomainInvitation.objects.get_or_create(email=email_address, domain=self.object)
|
||||||
email=email_address, domain=self.object
|
|
||||||
)
|
|
||||||
if not created:
|
if not created:
|
||||||
# that invitation already existed
|
# that invitation already existed
|
||||||
messages.warning(
|
messages.warning(
|
||||||
|
@ -678,9 +652,7 @@ class DomainAddUserView(DomainFormBaseView):
|
||||||
exc_info=True,
|
exc_info=True,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
messages.success(
|
messages.success(self.request, f"Invited {email_address} to this domain.")
|
||||||
self.request, f"Invited {email_address} to this domain."
|
|
||||||
)
|
|
||||||
|
|
||||||
return redirect(self.get_success_url())
|
return redirect(self.get_success_url())
|
||||||
|
|
||||||
|
@ -709,9 +681,7 @@ class DomainAddUserView(DomainFormBaseView):
|
||||||
return redirect(self.get_success_url())
|
return redirect(self.get_success_url())
|
||||||
|
|
||||||
|
|
||||||
class DomainInvitationDeleteView(
|
class DomainInvitationDeleteView(DomainInvitationPermissionDeleteView, SuccessMessageMixin):
|
||||||
DomainInvitationPermissionDeleteView, SuccessMessageMixin
|
|
||||||
):
|
|
||||||
object: DomainInvitation # workaround for type mismatch in DeleteView
|
object: DomainInvitation # workaround for type mismatch in DeleteView
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
|
|
|
@ -7,6 +7,4 @@ from login_required import login_not_required
|
||||||
# PaaS orchestrator can make sure the app has come up properly
|
# PaaS orchestrator can make sure the app has come up properly
|
||||||
@login_not_required
|
@login_not_required
|
||||||
def health(request):
|
def health(request):
|
||||||
return HttpResponse(
|
return HttpResponse('<html lang="en"><head><title>OK - Get.gov</title></head><body>OK</body>')
|
||||||
'<html lang="en"><head><title>OK - Get.gov</title></head><body>OK</body>'
|
|
||||||
)
|
|
||||||
|
|
|
@ -49,9 +49,7 @@ class DomainPermission(PermissionsLoginMixin):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# user needs to have a role on the domain
|
# user needs to have a role on the domain
|
||||||
if not UserDomainRole.objects.filter(
|
if not UserDomainRole.objects.filter(user=self.request.user, domain__id=pk).exists():
|
||||||
user=self.request.user, domain__id=pk
|
|
||||||
).exists():
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# if we need to check more about the nature of role, do it here.
|
# if we need to check more about the nature of role, do it here.
|
||||||
|
@ -133,9 +131,7 @@ class DomainApplicationPermission(PermissionsLoginMixin):
|
||||||
# user needs to be the creator of the application
|
# user needs to be the creator of the application
|
||||||
# this query is empty if there isn't a domain application with this
|
# this query is empty if there isn't a domain application with this
|
||||||
# id and this user as creator
|
# id and this user as creator
|
||||||
if not DomainApplication.objects.filter(
|
if not DomainApplication.objects.filter(creator=self.request.user, id=self.kwargs["pk"]).exists():
|
||||||
creator=self.request.user, id=self.kwargs["pk"]
|
|
||||||
).exists():
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -33,9 +33,9 @@ class DomainPermissionView(DomainPermission, DetailView, abc.ABC):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
context["is_analyst_or_superuser"] = user.has_perm(
|
context["is_analyst_or_superuser"] = user.has_perm("registrar.analyst_access_permission") or user.has_perm(
|
||||||
"registrar.analyst_access_permission"
|
"registrar.full_access_permission"
|
||||||
) or user.has_perm("registrar.full_access_permission")
|
)
|
||||||
# Stored in a variable for the linter
|
# Stored in a variable for the linter
|
||||||
action = "analyst_action"
|
action = "analyst_action"
|
||||||
action_location = "analyst_action_location"
|
action_location = "analyst_action_location"
|
||||||
|
@ -74,9 +74,7 @@ class DomainApplicationPermissionView(DomainApplicationPermission, DetailView, a
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class ApplicationWizardPermissionView(
|
class ApplicationWizardPermissionView(ApplicationWizardPermission, TemplateView, abc.ABC):
|
||||||
ApplicationWizardPermission, TemplateView, abc.ABC
|
|
||||||
):
|
|
||||||
|
|
||||||
"""Abstract base view for the application form that enforces permissions
|
"""Abstract base view for the application form that enforces permissions
|
||||||
|
|
||||||
|
@ -91,9 +89,7 @@ class ApplicationWizardPermissionView(
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class DomainInvitationPermissionDeleteView(
|
class DomainInvitationPermissionDeleteView(DomainInvitationPermission, DeleteView, abc.ABC):
|
||||||
DomainInvitationPermission, DeleteView, abc.ABC
|
|
||||||
):
|
|
||||||
|
|
||||||
"""Abstract view for deleting a domain invitation.
|
"""Abstract view for deleting a domain invitation.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue