ran black formatting

This commit is contained in:
Alysia Broddrick 2023-09-08 19:07:59 -07:00
parent c9cadd3401
commit e71b5b0bd4
No known key found for this signature in database
GPG key ID: 03917052CD0F06B7
7 changed files with 559 additions and 358 deletions

View file

@ -83,7 +83,7 @@ class EPPLibWrapper:
logger.warning(message, cmd_type, exc_info=True) logger.warning(message, cmd_type, exc_info=True)
raise RegistryError(message) from err raise RegistryError(message) from err
except Exception as err: except Exception as err:
message = '%s failed to execute due to an unknown error.' % err message = "%s failed to execute due to an unknown error." % err
logger.warning(message, cmd_type, exc_info=True) logger.warning(message, cmd_type, exc_info=True)
raise RegistryError(message) from err raise RegistryError(message) from err
else: else:

View file

@ -173,20 +173,15 @@ class DomainAdmin(ListHeaderAdmin):
try: try:
security_email = obj.get_security_email() security_email = obj.get_security_email()
except Exception as err: except Exception as err:
self.message_user(request, err, messages.ERROR) self.message_user(request, err, messages.ERROR)
else: else:
self.message_user(request, self.message_user(
( request,
"The security email is %" ("The security email is %" ". Thanks!") % security_email,
". Thanks!"
)
% security_email,
) )
return HttpResponseRedirect(".") return HttpResponseRedirect(".")
if SET_SECURITY_CONTACT in request.POST: if SET_SECURITY_CONTACT in request.POST:
try: try:
security_contact = obj.get_default_security_contact() security_contact = obj.get_default_security_contact()
@ -196,12 +191,9 @@ class DomainAdmin(ListHeaderAdmin):
except Exception as err: except Exception as err:
self.message_user(request, err, messages.ERROR) self.message_user(request, err, messages.ERROR)
else: else:
self.message_user(request, self.message_user(
( request,
"The security email is %" ("The security email is %" ". Thanks!") % security_email,
". Thanks!"
)
% security_email,
) )
print("above make domain") print("above make domain")
@ -213,15 +205,13 @@ class DomainAdmin(ListHeaderAdmin):
except Exception as err: except Exception as err:
self.message_user(request, err, messages.ERROR) self.message_user(request, err, messages.ERROR)
else: else:
self.message_user(request, self.message_user(
( request,
"Domain created with %" ("Domain created with %" ". Thanks!") % obj.name,
". Thanks!"
)
% obj.name,
) )
return HttpResponseRedirect(".") return HttpResponseRedirect(".")
return super().response_change(request, obj) return super().response_change(request, obj)
# def response_change(self, request, obj): # def response_change(self, request, obj):
# ACTION_BUTTON = "_get_security_email" # ACTION_BUTTON = "_get_security_email"

View file

@ -19,6 +19,7 @@ from .utility.domain_helper import DomainHelper
from .utility.time_stamped_model import TimeStampedModel from .utility.time_stamped_model import TimeStampedModel
from .public_contact import PublicContact from .public_contact import PublicContact
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -103,6 +104,7 @@ class Domain(TimeStampedModel, DomainHelper):
class State(models.TextChoices): class State(models.TextChoices):
"""These capture (some of) the states a domain object can be in.""" """These capture (some of) the states a domain object can be in."""
# the state is indeterminate # the state is indeterminate
UNKNOWN = "unknown" UNKNOWN = "unknown"
@ -120,8 +122,6 @@ class Domain(TimeStampedModel, DomainHelper):
# previously existed but has been deleted from the registry # previously existed but has been deleted from the registry
DELETED = "deleted" DELETED = "deleted"
class Cache(property): class Cache(property):
""" """
Python descriptor to turn class methods into properties. Python descriptor to turn class methods into properties.
@ -235,6 +235,7 @@ class Domain(TimeStampedModel, DomainHelper):
("ns2.example.com",), ("ns2.example.com",),
("ns3.example.com",), ("ns3.example.com",),
] ]
def _check_host(self, hostnames: list[str]): def _check_host(self, hostnames: list[str]):
"""check if host is available, True if available """check if host is available, True if available
returns boolean""" returns boolean"""
@ -243,8 +244,13 @@ class Domain(TimeStampedModel, DomainHelper):
response = registry.send(checkCommand, cleaned=True) response = registry.send(checkCommand, cleaned=True)
return response.res_data[0].avail return response.res_data[0].avail
except RegistryError as err: except RegistryError as err:
logger.warning("Couldn't check hosts %. Errorcode was %s, error was %s"%(hostnames),err.code, err) logger.warning(
"Couldn't check hosts %. Errorcode was %s, error was %s" % (hostnames),
err.code,
err,
)
return False return False
def _create_host(self, host, addrs): def _create_host(self, host, addrs):
"""Call _check_host first before using this function, """Call _check_host first before using this function,
This creates the host object in the registry This creates the host object in the registry
@ -278,7 +284,9 @@ class Domain(TimeStampedModel, DomainHelper):
# if two nameservers change state to created, don't do it automatically # if two nameservers change state to created, don't do it automatically
hostSuccessCount = 0 hostSuccessCount = 0
if len(hosts) > 13: if len(hosts) > 13:
raise ValueError("Too many hosts provided, you may not have more than 13 nameservers.") raise ValueError(
"Too many hosts provided, you may not have more than 13 nameservers."
)
logger.info("hosts will follow") logger.info("hosts will follow")
logger.info(hosts) logger.info(hosts)
for hostTuple in hosts: for hostTuple in hosts:
@ -295,16 +303,22 @@ class Domain(TimeStampedModel, DomainHelper):
# update the object instead # update the object instead
elif createdCode == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY: elif createdCode == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY:
# add host to domain # add host to domain
request = commands.UpdateDomain(name=self.name, add=[epp.HostObjSet([host])]) request = commands.UpdateDomain(
name=self.name, add=[epp.HostObjSet([host])]
)
try: try:
registry.send(request, cleaned=True) registry.send(request, cleaned=True)
hostSuccessCount += 1 hostSuccessCount += 1
except RegistryError as e: except RegistryError as e:
logger.error("Error adding nameserver, code was %s error was %s" % (e.code, e)) logger.error(
"Error adding nameserver, code was %s error was %s"
% (e.code, e)
)
if self.state == self.State.PENDING_CREATE and hostSuccessCount >= 2: if self.state == self.State.PENDING_CREATE and hostSuccessCount >= 2:
self.created() self.created()
self.save()
##TODO - handle removed nameservers here will need to change the state go back to pending_create ##TODO - handle removed nameservers here will need to change the state go back to pending_create
@Cache @Cache
@ -329,6 +343,7 @@ class Domain(TimeStampedModel, DomainHelper):
# can be combined; check that here and raise errors for invalid combinations - # can be combined; check that here and raise errors for invalid combinations -
# some statuses cannot be set by the client at all # some statuses cannot be set by the client at all
raise NotImplementedError() raise NotImplementedError()
# ### implement get status which checks the status of the domain object on error it logs but goes with whatever the status is # ### implement get status which checks the status of the domain object on error it logs but goes with whatever the status is
# def get_status(self): # def get_status(self):
# try: # try:
@ -353,8 +368,9 @@ class Domain(TimeStampedModel, DomainHelper):
"""Registrant is set when a domain is created, so follow on additions will update the current registrant""" """Registrant is set when a domain is created, so follow on additions will update the current registrant"""
###incorrect should update an existing registrant ###incorrect should update an existing registrant
logger.info("making registrant contact") logger.info("making registrant contact")
self._set_singleton_contact(contact=contact, expectedType=contact.ContactTypeChoices.REGISTRANT) self._set_singleton_contact(
contact=contact, expectedType=contact.ContactTypeChoices.REGISTRANT
)
@Cache @Cache
def administrative_contact(self) -> PublicContact: def administrative_contact(self) -> PublicContact:
@ -369,12 +385,13 @@ class Domain(TimeStampedModel, DomainHelper):
# use admin as type parameter for this contact # use admin as type parameter for this contact
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("Cannot set a registrant contact with a different contact type") raise ValueError(
"Cannot set a registrant contact with a different contact type"
)
logger.info("administrative_contact()-> update domain with admin contact") logger.info("administrative_contact()-> update domain with admin contact")
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)
def get_default_security_contact(self): def get_default_security_contact(self):
logger.info("getting default sec contact") logger.info("getting default sec contact")
contact = PublicContact.get_default_security() contact = PublicContact.get_default_security()
@ -383,22 +400,30 @@ class Domain(TimeStampedModel, DomainHelper):
def _update_epp_contact(self, contact: PublicContact): def _update_epp_contact(self, contact: PublicContact):
"""Sends UpdateContact to update the actual contact object, domain object remains unaffected """Sends UpdateContact to update the actual contact object, domain object remains unaffected
should be used when changing email address or other contact infor on an existing domain""" should be used when changing email address or other contact infor on an existing domain
updateContact=commands.UpdateContact(id=contact.registry_id, postal_info=self._make_epp_contact_postal_info(contact=contact), """
updateContact = commands.UpdateContact(
id=contact.registry_id,
postal_info=self._make_epp_contact_postal_info(contact=contact),
email=contact.email, email=contact.email,
voice=contact.voice, voice=contact.voice,
fax=contact.fax) fax=contact.fax,
)
try: try:
registry.send(updateContact, cleaned=True) registry.send(updateContact, cleaned=True)
except RegistryError as e: except RegistryError as e:
logger.error("Error updating contact, code was %s error was %s" % (e.code, e)) logger.error(
"Error updating contact, code was %s error was %s" % (e.code, e)
)
# add more error handling here # add more error handling here
# ticket for error handling in epp # ticket for error handling in epp
def _update_domain_with_contact(self, contact: PublicContact, rem=False): def _update_domain_with_contact(self, contact: PublicContact, rem=False):
logger.info("received type %s " % contact.contact_type) logger.info("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:
@ -408,13 +433,17 @@ 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("Error changing contact on a domain. Error code is %s error was %s" % (e.code, e)) logger.error(
"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("Can't %s the contact of type %s"%( action, contact.contact_type)) raise Exception(
"Can't %s the contact of type %s" % (action, contact.contact_type)
)
@Cache @Cache
def security_contact(self) -> PublicContact: def security_contact(self) -> PublicContact:
@ -444,8 +473,12 @@ class Domain(TimeStampedModel, DomainHelper):
else: else:
logger.info("Showing contacts") logger.info("Showing contacts")
for contact in contacts: for contact in contacts:
if isinstance(contact, dict) and "type" in contact.keys() and \ if (
"contact" in contact.keys() and contact["type"]=="security": isinstance(contact, dict)
and "type" in contact.keys()
and "contact" in contact.keys()
and contact["type"] == "security"
):
return contact["contact"] return contact["contact"]
##TODO -get the security contact, requires changing the implemenation below and the parser from epplib ##TODO -get the security contact, requires changing the implemenation below and the parser from epplib
@ -459,30 +492,48 @@ class Domain(TimeStampedModel, DomainHelper):
def _add_registrant_to_existing_domain(self, contact: PublicContact): def _add_registrant_to_existing_domain(self, contact: PublicContact):
self._update_epp_contact(contact=contact) self._update_epp_contact(contact=contact)
updateDomain=commands.UpdateDomain(name=self.name, registrant=contact.registry_id ) updateDomain = commands.UpdateDomain(
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("Error changing to new registrant error code is %s, error is %s" % (e.code, e)) logger.error(
"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): def _set_singleton_contact(self, contact: PublicContact, expectedType: str):
"""""" """"""
logger.info("_set_singleton_contact()-> contactype type being set: %s expected type is: %s"%(contact, expectedType)) logger.info(
"_set_singleton_contact()-> contactype type being set: %s expected type is: %s"
% (contact, expectedType)
)
if expectedType != contact.contact_type: if expectedType != contact.contact_type:
raise ValueError("Cannot set a contact with a different contact type, expected type was %s"% expectedType) raise ValueError(
"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 = (
contact.contact_type == contact.ContactTypeChoices.SECURITY
and contact.email == ""
)
domainContactExists = PublicContact.objects.filter(registry_id=contact.registry_id).exists()
contactIsAlreadyOnDomain = PublicContact.objects.filter(domain=self,registry_id=contact.registry_id,contact_type=contact.contact_type ).exists()
contactOfTypeExists = PublicContact.objects.filter(domain=self,contact_type=contact.contact_type ).exists()
# get publicContact objects that have the matching domain and type but a different id, should be only one # get publicContact objects that have the matching domain and type but a different id, should be only one
hasOtherContact = PublicContact.objects.exclude(registry_id=contact.registry_id).filter(domain=self,contact_type=contact.contact_type ).exists() hasOtherContact = (
PublicContact.objects.exclude(registry_id=contact.registry_id)
.filter(domain=self, contact_type=contact.contact_type)
.exists()
)
logger.info("has other contact %s" % hasOtherContact) logger.info("has other contact %s" % hasOtherContact)
##if no record exists with this contact type
logger.info("_set_singleton_contact()-> adding contact that shouldn't exist already") ##if no record exists with this contact type
logger.info(
"_set_singleton_contact()-> adding contact that shouldn't exist already"
)
# make contact in registry, duplicate and errors handled there # make contact in registry, duplicate and errors handled there
errorCode = self._make_contact_in_registry(contact) errorCode = self._make_contact_in_registry(contact)
@ -502,15 +553,24 @@ class Domain(TimeStampedModel, DomainHelper):
# if type is anything else it should be in the contact list # if type is anything else it should be in the contact list
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 not alreadyExistsInRegistry and errorCode!= ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY: if (
not alreadyExistsInRegistry
and errorCode != ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
):
raise Exception("Unable to add contact to registry") raise Exception("Unable to add contact to registry")
# contact doesn't exist on the domain yet # contact doesn't exist on the domain yet
logger.info("_set_singleton_contact()-> contact has been added to the registry") logger.info("_set_singleton_contact()-> contact has been added to the registry")
# if has conflicting contacts in our db remove them # if has conflicting contacts in our db remove them
if hasOtherContact: if hasOtherContact:
logger.info("_set_singleton_contact()-> updating domain by removing old contact and adding new one") logger.info(
existing_contact=PublicContact.objects.exclude(registry_id=contact.registry_id).filter(domain=self,contact_type=contact.contact_type ).get() "_set_singleton_contact()-> updating domain by removing old contact and adding new one"
)
existing_contact = (
PublicContact.objects.exclude(registry_id=contact.registry_id)
.filter(domain=self, contact_type=contact.contact_type)
.get()
)
if isRegistrant: if isRegistrant:
# send update domain only for registant contacts # send update domain only for registant contacts
existing_contact.delete() existing_contact.delete()
@ -518,24 +578,25 @@ class Domain(TimeStampedModel, DomainHelper):
else: else:
# remove the old contact and add a new one # remove the old contact and add a new one
try: try:
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("Raising error after removing and adding a new contact") logger.error(
"Raising error after removing and adding a new contact"
)
raise (err) raise (err)
# if just added to registry and not a registrant add contact to domain # if just added to registry and not a registrant add contact to domain
if not isEmptySecurity:
if not alreadyExistsInRegistry and not isRegistrant: if not alreadyExistsInRegistry and not isRegistrant:
print("UPDATING domain with the contact")
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:
print("updating the contact itself")
self._update_epp_contact(contact=contact) self._update_epp_contact(contact=contact)
@security_contact.setter # type: ignore @security_contact.setter # type: ignore
def security_contact(self, contact: PublicContact): def security_contact(self, contact: PublicContact):
"""makes the contact in the registry, """makes the contact in the registry,
@ -544,7 +605,9 @@ class Domain(TimeStampedModel, DomainHelper):
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(contact, expectedType=contact.ContactTypeChoices.SECURITY) self._set_singleton_contact(
contact, expectedType=contact.ContactTypeChoices.SECURITY
)
@Cache @Cache
def technical_contact(self) -> PublicContact: def technical_contact(self) -> PublicContact:
@ -554,7 +617,9 @@ 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(contact, expectedType=contact.ContactTypeChoices.TECHNICAL) self._set_singleton_contact(
contact, expectedType=contact.ContactTypeChoices.TECHNICAL
)
def is_active(self) -> bool: def is_active(self) -> bool:
"""Currently just returns if the state is created, because then it should be live, theoretically. """Currently just returns if the state is created, because then it should be live, theoretically.
@ -647,7 +712,9 @@ class Domain(TimeStampedModel, DomainHelper):
count = 0 count = 0
while not already_tried_to_create and count < 3: while not already_tried_to_create and count < 3:
try: try:
logger.info("_get_or_create_domain()-> getting info on the domain, should hit an error") logger.info(
"_get_or_create_domain()-> getting info on the domain, should hit an error"
)
req = commands.InfoDomain(name=self.name) req = commands.InfoDomain(name=self.name)
domainInfo = registry.send(req, cleaned=True).res_data[0] domainInfo = registry.send(req, cleaned=True).res_data[0]
@ -665,6 +732,7 @@ class Domain(TimeStampedModel, DomainHelper):
# avoid infinite loop # avoid infinite loop
already_tried_to_create = True already_tried_to_create = True
self.pendingCreate() self.pendingCreate()
self.save()
else: else:
logger.error(e) logger.error(e)
logger.error(e.code) logger.error(e.code)
@ -679,28 +747,42 @@ class Domain(TimeStampedModel, DomainHelper):
logger.info("registrant is %s" % registrant) logger.info("registrant is %s" % registrant)
# TODO-notes no chg item for registrant in the epplib should # TODO-notes no chg item for registrant in the epplib should
security_contact=self.get_default_security_contact()
req = commands.CreateDomain( req = commands.CreateDomain(
name=self.name, name=self.name,
registrant=registrant.registry_id, registrant=registrant.registry_id,
auth_info=epp.DomainAuthInfo( auth_info=epp.DomainAuthInfo(pw="2fooBAR123fooBaz"), # not a password
pw="2fooBAR123fooBaz"
), # not a password
) )
logger.info("_get_or_create_domain()-> about to send domain request") logger.info("_get_or_create_domain()-> about to send domain request")
logger.info(req) logger.info(req)
try: try:
response = registry.send(req, cleaned=True) response = registry.send(req, cleaned=True)
logger.info(response) logger.info(response)
except RegistryError as err: except RegistryError as err:
if err.code != ErrorCode.OBJECT_EXISTS: if err.code != ErrorCode.OBJECT_EXISTS:
raise err raise err
logger.info("_get_or_create_domain()-> registry received create for "+self.name)
print("making all defaults")
self.addAllDefaults()
logger.info(
"_get_or_create_domain()-> registry received create for " + self.name
)
def addAllDefaults(self):
security_contact = self.get_default_security_contact()
security_contact.domain = self
technical_contact = PublicContact.get_default_technical()
technical_contact.domain = self
administrative_contact = PublicContact.get_default_administrative()
administrative_contact.domain = self
technical_contact.save()
administrative_contact.save()
security_contact.save() security_contact.save()
self.save() print("security contact")
print(security_contact)
def testSettingOtherContacts(self): def testSettingOtherContacts(self):
##delete this funciton ##delete this funciton
@ -714,7 +796,6 @@ class Domain(TimeStampedModel, DomainHelper):
technical_contact.save() technical_contact.save()
administrative_contact.save() administrative_contact.save()
@transition(field="state", source=State.PENDING_CREATE, target=State.CLIENT_HOLD) @transition(field="state", source=State.PENDING_CREATE, target=State.CLIENT_HOLD)
def clientHold(self): def clientHold(self):
##TODO - check to see if client hold is allowed should happen outside of this function ##TODO - check to see if client hold is allowed should happen outside of this function
@ -728,18 +809,27 @@ class Domain(TimeStampedModel, DomainHelper):
logger.info("pendingCreate()-> inside pending create") logger.info("pendingCreate()-> inside pending create")
pass pass
# TODO - send delete here # TODO - send delete here
@transition(field="state", source=[State.PENDING_CREATE, State.SERVER_HOLD, State.CLIENT_HOLD], target=State.CREATED)
@transition(
field="state",
source=[State.PENDING_CREATE, State.SERVER_HOLD, State.CLIENT_HOLD],
target=State.CREATED,
)
def created(self): def created(self):
logger.info("created()-> inside setting create") logger.info("created()-> inside setting create")
# TODO - do anything else here? # TODO - do anything else here?
def _disclose_fields(self,isSecurity=False):
def _disclose_fields(self, contact: PublicContact):
"""creates a disclose object that can be added to a contact Create using """creates a disclose object that can be added to a contact Create using
.disclose= <this function> on the command before sending. .disclose= <this function> on the command before sending.
if item is security email then make sure email is visable""" if item is security email then make sure email is visable"""
isSecurity = contact.contact_type == contact.ContactTypeChoices.SECURITY
DF = epp.DiscloseField DF = epp.DiscloseField
fields = {DF.FAX, DF.VOICE, DF.ADDR} fields = {DF.FAX, DF.VOICE, DF.ADDR}
if not isSecurity: if not isSecurity or (
isSecurity and contact.email == PublicContact.get_default_security().email
):
fields.add(DF.EMAIL) fields.add(DF.EMAIL)
return epp.Disclose( return epp.Disclose(
@ -747,6 +837,7 @@ class Domain(TimeStampedModel, DomainHelper):
fields={DF.FAX, DF.VOICE, DF.ADDR}, fields={DF.FAX, DF.VOICE, DF.ADDR},
types={DF.ADDR: "loc"}, types={DF.ADDR: "loc"},
) )
def _make_epp_contact_postal_info(self, contact: PublicContact): def _make_epp_contact_postal_info(self, contact: PublicContact):
return epp.PostalInfo( # type: ignore return epp.PostalInfo( # type: ignore
name=contact.name, name=contact.name,
@ -770,7 +861,7 @@ class Domain(TimeStampedModel, DomainHelper):
returns int corresponding to ErrorCode values""" returns int corresponding to ErrorCode values"""
logger.info(contact) logger.info(contact)
logger.info(contact.registry_id) logger.info(contact.registry_id)
print("***CREATING THE CCONTACT")
create = commands.CreateContact( create = commands.CreateContact(
id=contact.registry_id, id=contact.registry_id,
postal_info=self._make_epp_contact_postal_info(contact=contact), postal_info=self._make_epp_contact_postal_info(contact=contact),
@ -780,7 +871,7 @@ class Domain(TimeStampedModel, DomainHelper):
auth_info=epp.ContactAuthInfo(pw="2fooBAR123fooBaz"), auth_info=epp.ContactAuthInfo(pw="2fooBAR123fooBaz"),
) )
# security contacts should only show email addresses, for now # security contacts should only show email addresses, for now
create.disclose=self._disclose_fields(isSecurity=contact.contact_type==contact.ContactTypeChoices.SECURITY) create.disclose = self._disclose_fields(contact=contact)
try: try:
logger.info("sending contact") logger.info("sending contact")
registry.send(create, cleaned=True) registry.send(create, cleaned=True)
@ -789,12 +880,22 @@ class Domain(TimeStampedModel, DomainHelper):
except RegistryError as err: except RegistryError as err:
# don't throw an error if it is just saying this is a duplicate contact # don't throw an error if it is just saying this is a duplicate contact
if err.code != ErrorCode.OBJECT_EXISTS: if err.code != ErrorCode.OBJECT_EXISTS:
logger.error("Registry threw error for contact id %s contact type is %s, error code is\n %s full error is %s",contact.registry_id, contact.contact_type, err.code, err) logger.error(
"Registry threw error for contact id %s contact type is %s, error code is\n %s full error is %s",
contact.registry_id,
contact.contact_type,
err.code,
err,
)
# TODO - Error handling here # TODO - Error handling here
else: else:
logger.warning("Registrar tried to create duplicate contact for id %s",contact.registry_id) logger.warning(
"Registrar tried to create duplicate contact for id %s",
contact.registry_id,
)
return err.code return err.code
def _request_contact_info(self, contact: PublicContact): def _request_contact_info(self, contact: PublicContact):
req = commands.InfoContact(id=contact.registry_id) req = commands.InfoContact(id=contact.registry_id)
return registry.send(req, cleaned=True).res_data[0] return registry.send(req, cleaned=True).res_data[0]
@ -806,14 +907,21 @@ 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("_get_or_create_contact()-> contact doesn't exist so making it") logger.info(
"_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)
else: else:
logger.error("Registry threw error for contact id %s contact type is %s, error code is\n %s full error is %s",contact.registry_id, contact.contact_type, err.code, err) logger.error(
"Registry threw error for contact id %s contact type is %s, error code is\n %s full error is %s",
contact.registry_id,
contact.contact_type,
err.code,
err,
)
raise e raise e
@ -884,7 +992,10 @@ class Domain(TimeStampedModel, DomainHelper):
cleaned["contacts"].append( cleaned["contacts"].append(
{k: v for k, v in contact.items() if v is not ...} {k: v for k, v in contact.items() if v is not ...}
) )
logger.info("_fetch_cache()-> after getting contacts cleaned is "+str(cleaned)) logger.info(
"_fetch_cache()-> after getting contacts cleaned is "
+ str(cleaned)
)
# get nameserver info, if there are any # get nameserver info, if there are any
if ( if (

View file

@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
class DomainInformation(TimeStampedModel): class DomainInformation(TimeStampedModel):
"""A registrant's domain information for that domain, exported from """A registrant's domain information for that domain, exported from
DomainApplication. We use these field from DomainApplication with few exceptation DomainApplication. We use these field from DomainAchpplication with few exceptation
which are 'removed' via pop at the bottom of this file. Most of design for domain which are 'removed' via pop at the bottom of this file. Most of design for domain
management's user information are based on application, but we cannot change management's user information are based on application, but we cannot change
the application once approved, so copying them that way we can make changes the application once approved, so copying them that way we can make changes

View file

@ -149,4 +149,4 @@ class PublicContact(TimeStampedModel):
) )
def __str__(self): def __str__(self):
return f"{self.name} <{self.email}> id: {self.registry_id}" return f"{self.name} <{self.email}> id: {self.registry_id} type: {self.contact_type}"

View file

@ -17,6 +17,7 @@ from registrar.models.draft_domain import DraftDomain
from registrar.models.public_contact import PublicContact from registrar.models.public_contact import PublicContact
from registrar.models.user import User from registrar.models.user import User
class MockEppLib(TestCase): class MockEppLib(TestCase):
class fakedEppObject(object): class fakedEppObject(object):
"""""" """"""
@ -66,9 +67,8 @@ class MockEppLib(TestCase):
def tearDown(self): def tearDown(self):
self.mockSendPatch.stop() self.mockSendPatch.stop()
class TestDomainCache(MockEppLib): class TestDomainCache(MockEppLib):
# def setUp(self): # def setUp(self):
# #call setup from the mock epplib # #call setup from the mock epplib
# super().setUp() # super().setUp()
@ -142,6 +142,7 @@ class TestDomainCache(MockEppLib):
self.assertEqual(domain._cache["hosts"], [expectedHostsDict]) self.assertEqual(domain._cache["hosts"], [expectedHostsDict])
##IS THERE AN ERROR HERE???, ##IS THERE AN ERROR HERE???,
class TestDomainCreation(TestCase): class TestDomainCreation(TestCase):
"""Rule: An approved domain application must result in a domain""" """Rule: An approved domain application must result in a domain"""
@ -174,7 +175,6 @@ class TestDomainCreation(TestCase):
self.assertTrue(domain) self.assertTrue(domain)
mocked_domain_creation.assert_not_called() mocked_domain_creation.assert_not_called()
@skip("not implemented yet") @skip("not implemented yet")
def test_accessing_domain_properties_creates_domain_in_registry(self): def test_accessing_domain_properties_creates_domain_in_registry(self):
""" """
@ -216,6 +216,7 @@ class TestDomainCreation(TestCase):
Domain.objects.delete() Domain.objects.delete()
# User.objects.delete() # User.objects.delete()
class TestRegistrantContacts(MockEppLib): class TestRegistrantContacts(MockEppLib):
"""Rule: Registrants may modify their WHOIS data""" """Rule: Registrants may modify their WHOIS data"""
@ -227,16 +228,19 @@ class TestRegistrantContacts(MockEppLib):
""" """
super().setUp() super().setUp()
# mock create contact email extension # mock create contact email extension
self.contactMailingAddressPatch = patch("registrar.models.domain.commands.command_extensions.CreateContactMailingAddressExtension") self.contactMailingAddressPatch = patch(
"registrar.models.domain.commands.command_extensions.CreateContactMailingAddressExtension"
)
self.mockCreateContactExtension = self.contactMailingAddressPatch.start() self.mockCreateContactExtension = self.contactMailingAddressPatch.start()
# mock create contact # mock create contact
self.createContactPatch = patch("registrar.models.domain.commands.CreateContact") self.createContactPatch = patch(
"registrar.models.domain.commands.CreateContact"
)
self.mockCreateContact = self.createContactPatch.start() self.mockCreateContact = self.createContactPatch.start()
# mock the sending # mock the sending
self.domain, _ = Domain.objects.get_or_create(name="security.gov") self.domain, _ = Domain.objects.get_or_create(name="security.gov")
# 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()
@ -251,7 +255,6 @@ class TestRegistrantContacts(MockEppLib):
# self.contactMailingAddressPatch.stop() # self.contactMailingAddressPatch.stop()
# self.createContactPatch.stop() # self.createContactPatch.stop()
# @skip("source code not implemented")
def test_no_security_email(self): def test_no_security_email(self):
""" """
Scenario: Registrant has not added a security contact email Scenario: Registrant has not added a security contact email
@ -260,31 +263,85 @@ class TestRegistrantContacts(MockEppLib):
Then the domain has a valid security contact with CISA defaults Then the domain has a valid security contact with CISA defaults
And disclose flags are set to keep the email address hidden And disclose flags are set to keep the email address hidden
""" """
# making a domain should make it domain
print(self.domain) print(self.domain)
#get security contact
expectedSecContact = PublicContact.get_default_security() expectedSecContact = PublicContact.get_default_security()
expectedSecContact.domain = self.domain expectedSecContact.domain = self.domain
receivedSecContact=self.domain.security_contact self.domain.pendingCreate()
DF = common.DiscloseField DF = common.DiscloseField
di = common.Disclose(flag=False, fields={DF.FAX, DF.VOICE, DF.ADDR}, types={DF.ADDR: "loc"}) di = common.Disclose(
flag=False,
fields={DF.FAX, DF.VOICE, DF.ADDR, DF.EMAIL},
types={DF.ADDR: "loc"},
)
# 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(street=[expectedSecContact.street1,expectedSecContact.street2,expectedSecContact.street3] , city=expectedSecContact.city, pc=expectedSecContact.pc, cc=expectedSecContact.cc, sp=expectedSecContact.sp) addr = common.ContactAddr(
pi = common.PostalInfo(name=expectedSecContact.name, addr=addr, org=expectedSecContact.org, type="loc") street=[
ai = common.ContactAuthInfo(pw='feedabee') expectedSecContact.street1,
expectedCreateCommand=commands.CreateContact(id=expectedSecContact.registry_id, postal_info=pi, email=expectedSecContact.email, voice=expectedSecContact.voice, fax=expectedSecContact.fax, auth_info=ai, disclose=di, vat=None, ident=None, notify_email=None) expectedSecContact.street2,
expectedUpdateDomain =commands.UpdateDomain(name=self.domain.name, add=[common.DomainContact(contact=expectedSecContact.registry_id, type="security")]) expectedSecContact.street3,
],
city=expectedSecContact.city,
pc=expectedSecContact.pc,
cc=expectedSecContact.cc,
sp=expectedSecContact.sp,
)
pi = common.PostalInfo(
name=expectedSecContact.name,
addr=addr,
org=expectedSecContact.org,
type="loc",
)
ai = common.ContactAuthInfo(pw="feedabee")
expectedCreateCommand = commands.CreateContact(
id=expectedSecContact.registry_id,
postal_info=pi,
email=expectedSecContact.email,
voice=expectedSecContact.voice,
fax=expectedSecContact.fax,
auth_info=ai,
disclose=di,
vat=None,
ident=None,
notify_email=None,
)
expectedUpdateDomain = commands.UpdateDomain(
name=self.domain.name,
add=[
common.DomainContact(
contact=expectedSecContact.registry_id, type="security"
)
],
)
# check that send has triggered the create command # check that send has triggered the create command
# print(expectedCreateCommand)
self.mockedSendFunction.assert_any_call(expectedCreateCommand,True) print(self.mockedSendFunction.call_count)
self.mockedSendFunction.assert_any_call(expectedUpdateDomain, True) print(
PublicContact.objects.filter(
domain=self.domain,
contact_type=PublicContact.ContactTypeChoices.SECURITY,
)
)
# assert( self.mockedSendFunction.call_count
assert PublicContact.objects.filter(domain=self.domain).count() == 4
assert (
PublicContact.objects.get(
domain=self.domain,
contact_type=PublicContact.ContactTypeChoices.SECURITY,
).email
== expectedSecContact.email
)
# assert()
# self.mockedSendFunction.assert_any_call(expectedCreateCommand,True)
# self.mockedSendFunction.assert_any_call(expectedUpdateDomain, True)
# check that the security contact sent is the same as the one recieved # check that the security contact sent is the same as the one recieved
self.assertEqual(receivedSecContact,expectedSecContact)
# @skip("not implemented yet")
@skip("not implemented yet")
def test_user_adds_security_email(self): def test_user_adds_security_email(self):
""" """
Scenario: Registrant adds a security contact email Scenario: Registrant adds a security contact email
@ -300,24 +357,67 @@ class TestRegistrantContacts(MockEppLib):
expectedSecContact.email = "newEmail@fake.com" expectedSecContact.email = "newEmail@fake.com"
expectedSecContact.registry_id = "456" expectedSecContact.registry_id = "456"
expectedSecContact.name = "Fakey McPhakerson" expectedSecContact.name = "Fakey McPhakerson"
self.domain.security_contact=expectedSecContact
# calls the security contact setter as if you did
# self.domain.security_contact=expectedSecContact
expectedSecContact.save()
# check create contact sent with email # check create contact sent with email
DF = common.DiscloseField DF = common.DiscloseField
di = common.Disclose(flag=False, fields={DF.FAX, DF.VOICE, DF.ADDR}, types={DF.ADDR: "loc"}) di = common.Disclose(
flag=False, fields={DF.FAX, DF.VOICE, DF.ADDR}, types={DF.ADDR: "loc"}
)
addr = common.ContactAddr(street=[expectedSecContact.street1,expectedSecContact.street2,expectedSecContact.street3] , city=expectedSecContact.city, pc=expectedSecContact.pc, cc=expectedSecContact.cc, sp=expectedSecContact.sp) addr = common.ContactAddr(
pi = common.PostalInfo(name=expectedSecContact.name, addr=addr, org=expectedSecContact.org, type="loc") street=[
ai = common.ContactAuthInfo(pw='feedabee') expectedSecContact.street1,
expectedSecContact.street2,
expectedSecContact.street3,
],
city=expectedSecContact.city,
pc=expectedSecContact.pc,
cc=expectedSecContact.cc,
sp=expectedSecContact.sp,
)
pi = common.PostalInfo(
name=expectedSecContact.name,
addr=addr,
org=expectedSecContact.org,
type="loc",
)
ai = common.ContactAuthInfo(pw="feedabee")
expectedCreateCommand=commands.CreateContact(id=expectedSecContact.registry_id, postal_info=pi, email=expectedSecContact.email, voice=expectedSecContact.voice, fax=expectedSecContact.fax, auth_info=ai, disclose=di, vat=None, ident=None, notify_email=None) expectedCreateCommand = commands.CreateContact(
expectedUpdateDomain =commands.UpdateDomain(name=self.domain.name, add=[common.DomainContact(contact=expectedSecContact.registry_id, type="security")]) id=expectedSecContact.registry_id,
postal_info=pi,
email=expectedSecContact.email,
voice=expectedSecContact.voice,
fax=expectedSecContact.fax,
auth_info=ai,
disclose=di,
vat=None,
ident=None,
notify_email=None,
)
expectedUpdateDomain = commands.UpdateDomain(
name=self.domain.name,
add=[
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
self.mockedSendFunction.assert_any_call(expectedCreateCommand, True) print("finishing")
##check domain contact was updated
self.mockedSendFunction.assert_any_call(expectedUpdateDomain, True)
print(PublicContact.objects.filter(domain=self.domain))
receivedSecurityContact = PublicContact.objects.get(
domain=self.domain, contact_type=PublicContact.ContactTypeChoices.SECURITY
)
print(self.mockedSendFunction.call_count)
assert self.mockedSendFunction.call_count == 2
assert receivedSecurityContact == expectedSecContact
@skip("not implemented yet") @skip("not implemented yet")
def test_security_email_is_idempotent(self): def test_security_email_is_idempotent(self):