From 5b2e190db5ac9bb5a01b7aa5cdc6668b121d9e86 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 26 Sep 2023 08:44:45 -0400 Subject: [PATCH 01/11] updates to epplib for dnssec --- src/Pipfile.lock | 2 +- src/epplibwrapper/__init__.py | 2 ++ src/requirements.txt | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Pipfile.lock b/src/Pipfile.lock index d13ed6382..ca912a9ac 100644 --- a/src/Pipfile.lock +++ b/src/Pipfile.lock @@ -353,7 +353,7 @@ }, "fred-epplib": { "git": "https://github.com/cisagov/epplib.git", - "ref": "f818cbf0b069a12f03e1d72e4b9f4900924b832d" + "ref": "62966d4d48dadd657ec97e8383437ce77b626a1b" }, "furl": { "hashes": [ diff --git a/src/epplibwrapper/__init__.py b/src/epplibwrapper/__init__.py index b306dbd0e..4b6241884 100644 --- a/src/epplibwrapper/__init__.py +++ b/src/epplibwrapper/__init__.py @@ -11,6 +11,7 @@ logger = logging.getLogger(__name__) NAMESPACE = SimpleNamespace( EPP="urn:ietf:params:xml:ns:epp-1.0", + SEC_DNS="urn:ietf:params:xml:ns:secDNS-1.1", XSI="http://www.w3.org/2001/XMLSchema-instance", FRED="noop", NIC_CONTACT="urn:ietf:params:xml:ns:contact-1.0", @@ -25,6 +26,7 @@ NAMESPACE = SimpleNamespace( SCHEMA_LOCATION = SimpleNamespace( XSI="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd", FRED="noop fred-1.5.0.xsd", + SEC_DNS="urn:ietf:params:xml:ns:secDNS-1.1 secDNS-1.1.xsd", NIC_CONTACT="urn:ietf:params:xml:ns:contact-1.0 contact-1.0.xsd", NIC_DOMAIN="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd", NIC_ENUMVAL="noop enumval-1.2.0.xsd", diff --git a/src/requirements.txt b/src/requirements.txt index 52ded59fc..1d11396f7 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -22,7 +22,7 @@ django-phonenumber-field[phonenumberslite]==7.1.0 django-widget-tweaks==1.4.12 environs[django]==9.5.0 faker==18.10.0 -git+https://github.com/cisagov/epplib.git@f818cbf0b069a12f03e1d72e4b9f4900924b832d#egg=fred-epplib +git+https://github.com/cisagov/epplib.git@62966d4d48dadd657ec97e8383437ce77b626a1b#egg=fred-epplib furl==2.1.3 future==0.18.3 ; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3' gunicorn==20.1.0 From 6df2a65a90c4efc4fd26ebe19abd807cdd94998b Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 28 Sep 2023 10:10:48 -0400 Subject: [PATCH 02/11] getter and setter added for dnssecdata; dnssecdata added to cache --- src/epplibwrapper/__init__.py | 2 ++ src/registrar/models/domain.py | 48 +++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/epplibwrapper/__init__.py b/src/epplibwrapper/__init__.py index 4b6241884..996e840ce 100644 --- a/src/epplibwrapper/__init__.py +++ b/src/epplibwrapper/__init__.py @@ -47,6 +47,7 @@ try: from .client import CLIENT, commands from .errors import RegistryError, ErrorCode from epplib.models import common + from epplib.responses import extensions except ImportError: pass @@ -54,6 +55,7 @@ __all__ = [ "CLIENT", "commands", "common", + "extensions", "ErrorCode", "RegistryError", ] diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index 2c7f8703c..2b0e7e9ab 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -10,6 +10,7 @@ from epplibwrapper import ( CLIENT as registry, commands, common as epp, + extensions, RegistryError, ErrorCode, ) @@ -279,6 +280,36 @@ class Domain(TimeStampedModel, DomainHelper): logger.error("Error _create_host, code was %s error was %s" % (e.code, e)) return e.code + @Cache + def dnssecdata(self) -> extensions.DNSSECExtension: + return self._get_property("dnssecdata") + + @dnssecdata.setter + def dnssecdata( + self, + _dnssecdata: extensions.DNSSECExtension + ): + updateParams = { + "maxSigLife": _dnssecdata.maxSigLife, + "dsData": _dnssecdata.dsData, + "keyData": _dnssecdata.keyData, + "remAllDsKeyData": True, + } + request = commands.UpdateDomain( + name=self.name + ) + extension = commands.UpdateDomainDNSSECExtension(**updateParams) + request.add_extension(extension) + + try: + registry.send(request, cleaned=True) + except RegistryError as e: + logger.error( + "Error adding DNSSEC, code was %s error was %s" + % (e.code, e) + ) + raise e + @nameservers.setter # type: ignore def nameservers(self, hosts: list[tuple[str]]): """host should be a tuple of type str, str,... where the elements are @@ -725,9 +756,9 @@ class Domain(TimeStampedModel, DomainHelper): try: logger.info("Getting domain info from epp") req = commands.InfoDomain(name=self.name) - domainInfo = registry.send(req, cleaned=True).res_data[0] + domainInfoResponse = registry.send(req, cleaned=True) exitEarly = True - return domainInfo + return domainInfoResponse except RegistryError as e: count += 1 @@ -952,7 +983,8 @@ class Domain(TimeStampedModel, DomainHelper): """Contact registry for info about a domain.""" try: # get info from registry - data = self._get_or_create_domain() + dataResponse = self._get_or_create_domain() + data = dataResponse.res_data[0] # extract properties from response # (Ellipsis is used to mean "null") cache = { @@ -974,6 +1006,16 @@ class Domain(TimeStampedModel, DomainHelper): # statuses can just be a list no need to keep the epp object if "statuses" in cleaned.keys(): cleaned["statuses"] = [status.state for status in cleaned["statuses"]] + + # get extensions info, if there is any + # DNSSECExtension is one possible extension, make sure to handle + # only DNSSECExtension and not other type extensions + extensions = dataResponse.extensions + cleaned["dnssecdata"] = None + for extension in extensions: + if isinstance(extension,extensions.DNSSECExtension): + cleaned["dnssecdata"] = extension + # get contact info, if there are any if ( # fetch_contacts and From b43901d675e575735a3902f95ad4e930898d274b Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 28 Sep 2023 22:53:15 -0400 Subject: [PATCH 03/11] added test cases for DNSSEC --- src/registrar/models/domain.py | 29 +- src/registrar/tests/test_models_domain.py | 343 +++++++++++++++++++++- 2 files changed, 339 insertions(+), 33 deletions(-) diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index 2b0e7e9ab..6265a5b95 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -284,30 +284,21 @@ class Domain(TimeStampedModel, DomainHelper): def dnssecdata(self) -> extensions.DNSSECExtension: return self._get_property("dnssecdata") - @dnssecdata.setter - def dnssecdata( - self, - _dnssecdata: extensions.DNSSECExtension - ): + @dnssecdata.setter # type: ignore + def dnssecdata(self, _dnssecdata: extensions.DNSSECExtension): updateParams = { - "maxSigLife": _dnssecdata.maxSigLife, - "dsData": _dnssecdata.dsData, - "keyData": _dnssecdata.keyData, + "maxSigLife": _dnssecdata.get("maxSigLife", None), + "dsData": _dnssecdata.get("dsData", None), + "keyData": _dnssecdata.get("keyData", None), "remAllDsKeyData": True, } - request = commands.UpdateDomain( - name=self.name - ) + request = commands.UpdateDomain(name=self.name) extension = commands.UpdateDomainDNSSECExtension(**updateParams) request.add_extension(extension) - try: registry.send(request, cleaned=True) except RegistryError as e: - logger.error( - "Error adding DNSSEC, code was %s error was %s" - % (e.code, e) - ) + logger.error("Error adding DNSSEC, code was %s error was %s" % (e.code, e)) raise e @nameservers.setter # type: ignore @@ -1010,10 +1001,10 @@ class Domain(TimeStampedModel, DomainHelper): # get extensions info, if there is any # DNSSECExtension is one possible extension, make sure to handle # only DNSSECExtension and not other type extensions - extensions = dataResponse.extensions + returned_extensions = dataResponse.extensions cleaned["dnssecdata"] = None - for extension in extensions: - if isinstance(extension,extensions.DNSSECExtension): + for extension in returned_extensions: + if isinstance(extension, extensions.DNSSECExtension): cleaned["dnssecdata"] = extension # get contact info, if there are any diff --git a/src/registrar/tests/test_models_domain.py b/src/registrar/tests/test_models_domain.py index 54045bb32..e32cc2d42 100644 --- a/src/registrar/tests/test_models_domain.py +++ b/src/registrar/tests/test_models_domain.py @@ -3,9 +3,10 @@ Feature being tested: Registry Integration This file tests the various ways in which the registrar interacts with the registry. """ +from typing import Mapping, Any from django.test import TestCase from django.db.utils import IntegrityError -from unittest.mock import patch, call +from unittest.mock import MagicMock, patch, call import datetime from registrar.models import Domain @@ -20,6 +21,7 @@ from .common import MockEppLib from epplibwrapper import ( commands, common, + extensions, RegistryError, ErrorCode, ) @@ -664,44 +666,357 @@ class TestRegistrantNameservers(TestCase): raise -class TestRegistrantDNSSEC(TestCase): +class TestRegistrantDNSSEC(MockEppLib): """Rule: Registrants may modify their secure DNS data""" + # helper function to create UpdateDomainDNSSECExtention object for verification + def createUpdateExtension(self, dnssecdata: extensions.DNSSECExtension): + return commands.UpdateDomainDNSSECExtension( + maxSigLife=dnssecdata.maxSigLife, + dsData=dnssecdata.dsData, + keyData=dnssecdata.keyData, + remDsData=None, + remKeyData=None, + remAllDsKeyData=True, + ) + def setUp(self): """ Background: - Given the registrant is logged in - And the registrant is the admin on a domain + Given the analyst is logged in + And a domain exists in the registry """ - pass + super().setUp() + # for the tests, need a domain in the unknown state + self.domain, _ = Domain.objects.get_or_create(name="fake.gov") + self.addDsData1 = { + "keyTag": 1234, + "alg": 3, + "digestType": 1, + "digest": "ec0bdd990b39feead889f0ba613db4adec0bdd99", + } + self.addDsData2 = { + "keyTag": 2345, + "alg": 3, + "digestType": 1, + "digest": "ec0bdd990b39feead889f0ba613db4adecb4adec", + } + self.keyDataDict = { + "flags": 257, + "protocol": 3, + "alg": 1, + "pubKey": "AQPJ////4Q==", + } + self.dnssecExtensionWithDsData: Mapping[str, Any] = { + "dsData": [common.DSData(**self.addDsData1)] + } + self.dnssecExtensionWithMultDsData: Mapping[str, Any] = { + "dsData": [ + common.DSData(**self.addDsData1), + common.DSData(**self.addDsData2), + ], + } + self.dnssecExtensionWithKeyData: Mapping[str, Any] = { + "maxSigLife": 3215, + "keyData": [common.DNSSECKeyData(**self.keyDataDict)], + } - @skip("not implemented yet") - def test_user_adds_dns_data(self): + def tearDown(self): + Domain.objects.all().delete() + super().tearDown() + + def test_user_adds_dnssec_data(self): """ - Scenario: Registrant adds DNS data + Scenario: Registrant adds DNSSEC data. + Verify that both the setter and getter are functioning properly + + This test verifies: + 1 - setter calls UpdateDomain command + 2 - setter adds the UpdateDNSSECExtension extension to the command + 3 - setter causes the getter to call info domain on next get from cache + 4 - getter properly parses dnssecdata from InfoDomain response and sets to cache """ - raise - @skip("not implemented yet") + def side_effect(_request, cleaned): + return MagicMock( + res_data=[self.mockDataInfoDomain], + extensions=[ + extensions.DNSSECExtension(**self.dnssecExtensionWithDsData) + ], + ) + + patcher = patch("registrar.models.domain.registry.send") + mocked_send = patcher.start() + mocked_send.side_effect = side_effect + + self.domain.dnssecdata = self.dnssecExtensionWithDsData + # get the DNS SEC extension added to the UpdateDomain command and + # verify that it is properly sent + # args[0] is the _request sent to registry + args, _ = mocked_send.call_args + # assert that the extension matches + self.assertEquals( + args[0].extensions[0], + self.createUpdateExtension( + extensions.DNSSECExtension(**self.dnssecExtensionWithDsData) + ), + ) + # test that the dnssecdata getter is functioning properly + dnssecdata_get = self.domain.dnssecdata + mocked_send.assert_has_calls( + [ + call( + commands.UpdateDomain( + name="fake.gov", + nsset=None, + keyset=None, + registrant=None, + auth_info=None, + ), + cleaned=True, + ), + call( + commands.InfoDomain( + name="fake.gov", + ), + cleaned=True, + ), + ] + ) + + self.assertEquals( + dnssecdata_get.dsData, self.dnssecExtensionWithDsData["dsData"] + ) + + patcher.stop() + def test_dnssec_is_idempotent(self): """ Scenario: Registrant adds DNS data twice, due to a UI glitch - """ # implementation note: this requires seeing what happens when these are actually # sent like this, and then implementing appropriate mocks for any errors the # registry normally sends in this case - raise - @skip("not implemented yet") + This test verifies: + 1 - UpdateDomain command called twice + 2 - setter causes the getter to call info domain on next get from cache + 3 - getter properly parses dnssecdata from InfoDomain response and sets to cache + + """ + + def side_effect(_request, cleaned): + return MagicMock( + res_data=[self.mockDataInfoDomain], + extensions=[ + extensions.DNSSECExtension(**self.dnssecExtensionWithDsData) + ], + ) + + patcher = patch("registrar.models.domain.registry.send") + mocked_send = patcher.start() + mocked_send.side_effect = side_effect + + # set the dnssecdata once + self.domain.dnssecdata = self.dnssecExtensionWithDsData + # set the dnssecdata again + self.domain.dnssecdata = self.dnssecExtensionWithDsData + # test that the dnssecdata getter is functioning properly + dnssecdata_get = self.domain.dnssecdata + mocked_send.assert_has_calls( + [ + call( + commands.UpdateDomain( + name="fake.gov", + nsset=None, + keyset=None, + registrant=None, + auth_info=None, + ), + cleaned=True, + ), + call( + commands.UpdateDomain( + name="fake.gov", + nsset=None, + keyset=None, + registrant=None, + auth_info=None, + ), + cleaned=True, + ), + call( + commands.InfoDomain( + name="fake.gov", + ), + cleaned=True, + ), + ] + ) + + self.assertEquals( + dnssecdata_get.dsData, self.dnssecExtensionWithDsData["dsData"] + ) + + patcher.stop() + + def test_user_adds_dnssec_data_multiple_dsdata(self): + """ + Scenario: Registrant adds DNSSEC data with multiple DSData. + Verify that both the setter and getter are functioning properly + + This test verifies: + 1 - setter calls UpdateDomain command + 2 - setter adds the UpdateDNSSECExtension extension to the command + 3 - setter causes the getter to call info domain on next get from cache + 4 - getter properly parses dnssecdata from InfoDomain response and sets to cache + + """ + + def side_effect(_request, cleaned): + return MagicMock( + res_data=[self.mockDataInfoDomain], + extensions=[ + extensions.DNSSECExtension(**self.dnssecExtensionWithMultDsData) + ], + ) + + patcher = patch("registrar.models.domain.registry.send") + mocked_send = patcher.start() + mocked_send.side_effect = side_effect + + self.domain.dnssecdata = self.dnssecExtensionWithMultDsData + # get the DNS SEC extension added to the UpdateDomain command + # and verify that it is properly sent + # args[0] is the _request sent to registry + args, _ = mocked_send.call_args + # assert that the extension matches + self.assertEquals( + args[0].extensions[0], + self.createUpdateExtension( + extensions.DNSSECExtension(**self.dnssecExtensionWithMultDsData) + ), + ) + # test that the dnssecdata getter is functioning properly + dnssecdata_get = self.domain.dnssecdata + mocked_send.assert_has_calls( + [ + call( + commands.UpdateDomain( + name="fake.gov", + nsset=None, + keyset=None, + registrant=None, + auth_info=None, + ), + cleaned=True, + ), + call( + commands.InfoDomain( + name="fake.gov", + ), + cleaned=True, + ), + ] + ) + + self.assertEquals( + dnssecdata_get.dsData, self.dnssecExtensionWithMultDsData["dsData"] + ) + + patcher.stop() + + def test_user_adds_dnssec_keydata(self): + """ + Scenario: Registrant adds DNSSEC data. + Verify that both the setter and getter are functioning properly + + This test verifies: + 1 - setter calls UpdateDomain command + 2 - setter adds the UpdateDNSSECExtension extension to the command + 3 - setter causes the getter to call info domain on next get from cache + 4 - getter properly parses dnssecdata from InfoDomain response and sets to cache + + """ + + def side_effect(_request, cleaned): + return MagicMock( + res_data=[self.mockDataInfoDomain], + extensions=[ + extensions.DNSSECExtension(**self.dnssecExtensionWithKeyData) + ], + ) + + patcher = patch("registrar.models.domain.registry.send") + mocked_send = patcher.start() + mocked_send.side_effect = side_effect + + self.domain.dnssecdata = self.dnssecExtensionWithKeyData + # get the DNS SEC extension added to the UpdateDomain command + # and verify that it is properly sent + # args[0] is the _request sent to registry + args, _ = mocked_send.call_args + # assert that the extension matches + self.assertEquals( + args[0].extensions[0], + self.createUpdateExtension( + extensions.DNSSECExtension(**self.dnssecExtensionWithKeyData) + ), + ) + # test that the dnssecdata getter is functioning properly + dnssecdata_get = self.domain.dnssecdata + mocked_send.assert_has_calls( + [ + call( + commands.UpdateDomain( + name="fake.gov", + nsset=None, + keyset=None, + registrant=None, + auth_info=None, + ), + cleaned=True, + ), + call( + commands.InfoDomain( + name="fake.gov", + ), + cleaned=True, + ), + ] + ) + + self.assertEquals( + dnssecdata_get.keyData, self.dnssecExtensionWithKeyData["keyData"] + ) + + patcher.stop() + def test_update_is_unsuccessful(self): """ Scenario: An update to the dns data is unsuccessful When an error is returned from epplibwrapper Then a user-friendly error message is returned for displaying on the web """ - raise + + def side_effect(_request, cleaned): + raise RegistryError(code=ErrorCode.PARAMETER_VALUE_RANGE_ERROR) + + patcher = patch("registrar.models.domain.registry.send") + mocked_send = patcher.start() + mocked_send.side_effect = side_effect + + # if RegistryError is raised, view formats user-friendly + # error message if error is_client_error, is_session_error, or + # is_server_error; so test for those conditions + with self.assertRaises(RegistryError) as err: + self.domain.dnssecdata = self.dnssecExtensionWithDsData + self.assertTrue( + err.is_client_error() or err.is_session_error() or err.is_server_error() + ) + + patcher.stop() class TestAnalystClientHold(MockEppLib): From b836088ccddacb4093882c3ba158c43477f161fe Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Fri, 29 Sep 2023 18:35:06 -0400 Subject: [PATCH 04/11] committed updated epplib --- src/Pipfile.lock | 2 +- src/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Pipfile.lock b/src/Pipfile.lock index ca912a9ac..3e7ae367d 100644 --- a/src/Pipfile.lock +++ b/src/Pipfile.lock @@ -353,7 +353,7 @@ }, "fred-epplib": { "git": "https://github.com/cisagov/epplib.git", - "ref": "62966d4d48dadd657ec97e8383437ce77b626a1b" + "ref": "d56d183f1664f34c40ca9716a3a9a345f0ef561c" }, "furl": { "hashes": [ diff --git a/src/requirements.txt b/src/requirements.txt index 1d11396f7..ae584de43 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -22,7 +22,7 @@ django-phonenumber-field[phonenumberslite]==7.1.0 django-widget-tweaks==1.4.12 environs[django]==9.5.0 faker==18.10.0 -git+https://github.com/cisagov/epplib.git@62966d4d48dadd657ec97e8383437ce77b626a1b#egg=fred-epplib +git+https://github.com/cisagov/epplib.git@d56d183f1664f34c40ca9716a3a9a345f0ef561c#egg=fred-epplib furl==2.1.3 future==0.18.3 ; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3' gunicorn==20.1.0 From 201431caeaebf6b5d324aa3248882ff586f8ea6a Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:12:36 -0700 Subject: [PATCH 05/11] Rename admin role to manager --- src/registrar/models/user_domain_role.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/models/user_domain_role.py b/src/registrar/models/user_domain_role.py index 5a5219543..e5cb01cc1 100644 --- a/src/registrar/models/user_domain_role.py +++ b/src/registrar/models/user_domain_role.py @@ -15,7 +15,7 @@ class UserDomainRole(TimeStampedModel): elsewhere. """ - ADMIN = "admin" + ADMIN = "manager" user = models.ForeignKey( "registrar.User", From fc8da5c012a9fc0b014407ae9cb3a2d66e70cce9 Mon Sep 17 00:00:00 2001 From: Erin <121973038+erinysong@users.noreply.github.com> Date: Mon, 2 Oct 2023 15:10:34 -0700 Subject: [PATCH 06/11] Add migration to alter user domain role name --- .../0033_alter_userdomainrole_role.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/registrar/migrations/0033_alter_userdomainrole_role.py diff --git a/src/registrar/migrations/0033_alter_userdomainrole_role.py b/src/registrar/migrations/0033_alter_userdomainrole_role.py new file mode 100644 index 000000000..bdfcb6257 --- /dev/null +++ b/src/registrar/migrations/0033_alter_userdomainrole_role.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.1 on 2023-10-02 22:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("registrar", "0032_alter_transitiondomain_status"), + ] + + operations = [ + migrations.AlterField( + model_name="userdomainrole", + name="role", + field=models.TextField(choices=[("manager", "Admin")]), + ), + ] From 2015434bdbead439bf00a06d6d782ab909d0b67c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 03:40:46 +0000 Subject: [PATCH 07/11] Bump urllib3 from 1.26.16 to 1.26.17 in /src Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.16 to 1.26.17. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.16...1.26.17) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/requirements.txt b/src/requirements.txt index a5972c4dc..c61b5ccf9 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -49,5 +49,5 @@ setuptools==67.8.0 ; python_version >= '3.7' six==1.16.0 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' sqlparse==0.4.4 ; python_version >= '3.5' typing-extensions==4.6.3 -urllib3==1.26.16 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' +urllib3==1.26.17 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' whitenoise==6.4.0 From fbe584d85783385267a89704b35a6db8f8e9e059 Mon Sep 17 00:00:00 2001 From: Alysia Broddrick Date: Tue, 3 Oct 2023 13:25:12 -0700 Subject: [PATCH 08/11] adding kristina as admin --- src/registrar/fixtures.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/registrar/fixtures.py b/src/registrar/fixtures.py index 521d632d6..3c7efdab2 100644 --- a/src/registrar/fixtures.py +++ b/src/registrar/fixtures.py @@ -87,6 +87,11 @@ class UserFixture: "first_name": "Erin", "last_name": "Song", }, + { + "username": "e0ea8b94-6e53-4430-814a-849a7ca45f21", + "first_name": "Kristina", + "last_name": "Yin", + }, ] STAFF = [ From e69128c74a8f8d133b44b6df0b2abc65c5d70e6f Mon Sep 17 00:00:00 2001 From: Alysia Broddrick Date: Tue, 3 Oct 2023 13:52:43 -0700 Subject: [PATCH 09/11] add kristina as analyst --- src/registrar/fixtures.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/registrar/fixtures.py b/src/registrar/fixtures.py index 3c7efdab2..f6b8b7be0 100644 --- a/src/registrar/fixtures.py +++ b/src/registrar/fixtures.py @@ -150,6 +150,12 @@ class UserFixture: "last_name": "Song-Analyst", "email": "erin.song+1@gsa.gov", }, + { + "username": "9a98e4c9-9409-479d-964e-4aec7799107f", + "first_name": "Kristina-Analyst", + "last_name": "Yin-Analyst", + "email": "kristina.yin+1@gsa.gov", + }, ] STAFF_PERMISSIONS = [ From 475f1ef11c600dafe256a51f56504f575230cb22 Mon Sep 17 00:00:00 2001 From: Alysia Broddrick Date: Tue, 3 Oct 2023 14:07:57 -0700 Subject: [PATCH 10/11] fix linting --- src/registrar/fixtures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/registrar/fixtures.py b/src/registrar/fixtures.py index f6b8b7be0..e1db054b1 100644 --- a/src/registrar/fixtures.py +++ b/src/registrar/fixtures.py @@ -87,7 +87,7 @@ class UserFixture: "first_name": "Erin", "last_name": "Song", }, - { + { "username": "e0ea8b94-6e53-4430-814a-849a7ca45f21", "first_name": "Kristina", "last_name": "Yin", @@ -150,7 +150,7 @@ class UserFixture: "last_name": "Song-Analyst", "email": "erin.song+1@gsa.gov", }, - { + { "username": "9a98e4c9-9409-479d-964e-4aec7799107f", "first_name": "Kristina-Analyst", "last_name": "Yin-Analyst", From a24fd3cdac07ff324756d4741497549a9afec6ac Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 3 Oct 2023 17:24:10 -0400 Subject: [PATCH 11/11] changes to test_domain_model to stop addtl pathcer from running concurrently --- src/registrar/tests/test_models_domain.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/registrar/tests/test_models_domain.py b/src/registrar/tests/test_models_domain.py index b0a9b097e..16dd30017 100644 --- a/src/registrar/tests/test_models_domain.py +++ b/src/registrar/tests/test_models_domain.py @@ -852,6 +852,9 @@ class TestRegistrantDNSSEC(MockEppLib): """ + # make sure to stop any other patcher so there are no conflicts + self.mockSendPatch.stop() + def side_effect(_request, cleaned): return MagicMock( res_data=[self.mockDataInfoDomain], @@ -920,6 +923,9 @@ class TestRegistrantDNSSEC(MockEppLib): """ + # make sure to stop any other patcher so there are no conflicts + self.mockSendPatch.stop() + def side_effect(_request, cleaned): return MagicMock( res_data=[self.mockDataInfoDomain], @@ -988,6 +994,9 @@ class TestRegistrantDNSSEC(MockEppLib): """ + # make sure to stop any other patcher so there are no conflicts + self.mockSendPatch.stop() + def side_effect(_request, cleaned): return MagicMock( res_data=[self.mockDataInfoDomain], @@ -1054,6 +1063,9 @@ class TestRegistrantDNSSEC(MockEppLib): """ + # make sure to stop any other patcher so there are no conflicts + self.mockSendPatch.stop() + def side_effect(_request, cleaned): return MagicMock( res_data=[self.mockDataInfoDomain], @@ -1114,6 +1126,9 @@ class TestRegistrantDNSSEC(MockEppLib): Then a user-friendly error message is returned for displaying on the web """ + # make sure to stop any other patcher so there are no conflicts + self.mockSendPatch.stop() + def side_effect(_request, cleaned): raise RegistryError(code=ErrorCode.PARAMETER_VALUE_RANGE_ERROR)