Merge pull request #654 from cisagov/sspj/public-contact-update

Update fields and help text for Public Contact
This commit is contained in:
Seamus Johnston 2023-05-30 18:55:27 +00:00 committed by GitHub
commit 265e506643
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 259 additions and 30 deletions

View file

@ -0,0 +1,5 @@
# How to change the default contact data
The defaults are located in [src/registrar/models/public_contact.py](../../src/registrar/models/public_contact.py). Change them in the source code and re-deploy.
The choice of which fields to disclose is hardcoded in [src/registrar/models/domain.py](../../src/registrar/models/domain.py) (May 23) but in the future this may become customizable by registrants.

View file

@ -0,0 +1,122 @@
# Generated by Django 4.2.1 on 2023-05-25 15:03
from django.db import migrations, models
import django.db.models.deletion
import registrar.models.public_contact
class Migration(migrations.Migration):
dependencies = [
("registrar", "0020_remove_domaininformation_security_email"),
]
operations = [
migrations.AddField(
model_name="publiccontact",
name="domain",
field=models.ForeignKey(
default=1,
on_delete=django.db.models.deletion.PROTECT,
related_name="contacts",
to="registrar.domain",
),
preserve_default=False,
),
migrations.AddField(
model_name="publiccontact",
name="registry_id",
field=models.CharField(
default=registrar.models.public_contact.get_id,
help_text="Auto generated ID to track this contact in the registry",
max_length=16,
),
),
migrations.AlterField(
model_name="publiccontact",
name="cc",
field=models.TextField(help_text="Contact's country code"),
),
migrations.AlterField(
model_name="publiccontact",
name="city",
field=models.TextField(help_text="Contact's city"),
),
migrations.AlterField(
model_name="publiccontact",
name="contact_type",
field=models.CharField(
choices=[
("registrant", "Registrant"),
("administrative", "Administrative"),
("technical", "Technical"),
("security", "Security"),
],
help_text="For which type of WHOIS contact",
max_length=14,
),
),
migrations.AlterField(
model_name="publiccontact",
name="email",
field=models.TextField(help_text="Contact's email address"),
),
migrations.AlterField(
model_name="publiccontact",
name="fax",
field=models.TextField(
help_text="Contact's fax number (null ok). Must be in ITU.E164.2005 format.",
null=True,
),
),
migrations.AlterField(
model_name="publiccontact",
name="name",
field=models.TextField(help_text="Contact's full name"),
),
migrations.AlterField(
model_name="publiccontact",
name="org",
field=models.TextField(
help_text="Contact's organization (null ok)", null=True
),
),
migrations.AlterField(
model_name="publiccontact",
name="pc",
field=models.TextField(help_text="Contact's postal code"),
),
migrations.AlterField(
model_name="publiccontact",
name="pw",
field=models.TextField(
help_text="Contact's authorization code. 16 characters minimum."
),
),
migrations.AlterField(
model_name="publiccontact",
name="sp",
field=models.TextField(help_text="Contact's state or province"),
),
migrations.AlterField(
model_name="publiccontact",
name="street1",
field=models.TextField(help_text="Contact's street"),
),
migrations.AlterField(
model_name="publiccontact",
name="street2",
field=models.TextField(help_text="Contact's street (null ok)", null=True),
),
migrations.AlterField(
model_name="publiccontact",
name="street3",
field=models.TextField(help_text="Contact's street (null ok)", null=True),
),
migrations.AlterField(
model_name="publiccontact",
name="voice",
field=models.TextField(
help_text="Contact's phone number. Must be in ITU.E164.2005 format"
),
),
]

View file

@ -1,8 +1,21 @@
from datetime import datetime
from random import choices
from string import ascii_uppercase, ascii_lowercase, digits
from django.db import models from django.db import models
from .utility.time_stamped_model import TimeStampedModel from .utility.time_stamped_model import TimeStampedModel
def get_id():
"""Generate a 16 character registry ID with a low probability of collision."""
day = datetime.today().strftime("%A")[:2]
rand = "".join(
choices(ascii_uppercase + ascii_lowercase + digits, k=14) # nosec B311
)
return f"{day}{rand}"
class PublicContact(TimeStampedModel): class PublicContact(TimeStampedModel):
"""Contact information intended to be published in WHOIS.""" """Contact information intended to be published in WHOIS."""
@ -14,37 +27,126 @@ class PublicContact(TimeStampedModel):
TECHNICAL = "technical", "Technical" TECHNICAL = "technical", "Technical"
SECURITY = "security", "Security" SECURITY = "security", "Security"
contact_type = models.CharField(max_length=14, choices=ContactTypeChoices.choices) def save(self, *args, **kwargs):
"""Save to the registry and also locally in the registrar database."""
if hasattr(self, "domain"):
match self.contact_type:
case PublicContact.ContactTypeChoices.REGISTRANT:
self.domain.registrant = self
case PublicContact.ContactTypeChoices.ADMINISTRATIVE:
self.domain.administrative_contact = self
case PublicContact.ContactTypeChoices.TECHNICAL:
self.domain.technical_contact = self
case PublicContact.ContactTypeChoices.SECURITY:
self.domain.security_contact = self
super().save(*args, **kwargs)
# contact's full name contact_type = models.CharField(
name = models.TextField(null=False) max_length=14,
# contact's organization (null ok) choices=ContactTypeChoices.choices,
org = models.TextField(null=True) help_text="For which type of WHOIS contact",
# contact's street )
street1 = models.TextField(null=False) registry_id = models.CharField(
# contact's street (null ok) max_length=16,
street2 = models.TextField(null=True) default=get_id,
# contact's street (null ok) null=False,
street3 = models.TextField(null=True) help_text="Auto generated ID to track this contact in the registry",
# contact's city )
city = models.TextField(null=False) domain = models.ForeignKey(
# contact's state or province "registrar.Domain",
sp = models.TextField(null=False) on_delete=models.PROTECT,
# contact's postal code related_name="contacts",
pc = models.TextField(null=False) )
# contact's country code
cc = models.TextField(null=False) name = models.TextField(null=False, help_text="Contact's full name")
# contact's email address org = models.TextField(null=True, help_text="Contact's organization (null ok)")
email = models.TextField(null=False) street1 = models.TextField(null=False, help_text="Contact's street")
# contact's phone number street2 = models.TextField(null=True, help_text="Contact's street (null ok)")
# Must be in ITU.E164.2005 format street3 = models.TextField(null=True, help_text="Contact's street (null ok)")
voice = models.TextField(null=False) city = models.TextField(null=False, help_text="Contact's city")
# contact's fax number (null ok) sp = models.TextField(null=False, help_text="Contact's state or province")
# Must be in ITU.E164.2005 format pc = models.TextField(null=False, help_text="Contact's postal code")
fax = models.TextField(null=True) cc = models.TextField(null=False, help_text="Contact's country code")
# contact's authorization code email = models.TextField(null=False, help_text="Contact's email address")
# 16 characters minium voice = models.TextField(
pw = models.TextField(null=False) null=False, help_text="Contact's phone number. Must be in ITU.E164.2005 format"
)
fax = models.TextField(
null=True,
help_text="Contact's fax number (null ok). Must be in ITU.E164.2005 format.",
)
pw = models.TextField(
null=False, help_text="Contact's authorization code. 16 characters minimum."
)
@classmethod
def get_default_registrant(cls):
return cls(
contact_type=PublicContact.ContactTypeChoices.REGISTRANT,
registry_id=get_id(),
name="CSD/CB Attn: Cameron Dixon",
org="Cybersecurity and Infrastructure Security Agency",
street1="CISA NGR STOP 0645",
street2="1110 N. Glebe Rd.",
city="Arlington",
sp="VA",
pc="20598-0645",
cc="US",
email="dotgov@cisa.dhs.gov",
voice="+1.8882820870",
pw="thisisnotapassword",
)
@classmethod
def get_default_administrative(cls):
return cls(
contact_type=PublicContact.ContactTypeChoices.ADMINISTRATIVE,
registry_id=get_id(),
name="Program Manager",
org="Cybersecurity and Infrastructure Security Agency",
street1="4200 Wilson Blvd.",
city="Arlington",
sp="VA",
pc="22201",
cc="US",
email="dotgov@cisa.dhs.gov",
voice="+1.8882820870",
pw="thisisnotapassword",
)
@classmethod
def get_default_technical(cls):
return cls(
contact_type=PublicContact.ContactTypeChoices.TECHNICAL,
registry_id=get_id(),
name="Registry Customer Service",
org="Cybersecurity and Infrastructure Security Agency",
street1="4200 Wilson Blvd.",
city="Arlington",
sp="VA",
pc="22201",
cc="US",
email="dotgov@cisa.dhs.gov",
voice="+1.8882820870",
pw="thisisnotapassword",
)
@classmethod
def get_default_security(cls):
return cls(
contact_type=PublicContact.ContactTypeChoices.SECURITY,
registry_id=get_id(),
name="Registry Customer Service",
org="Cybersecurity and Infrastructure Security Agency",
street1="4200 Wilson Blvd.",
city="Arlington",
sp="VA",
pc="22201",
cc="US",
email="dotgov@cisa.dhs.gov",
voice="+1.8882820870",
pw="thisisnotapassword",
)
def __str__(self): def __str__(self):
return f"{self.name} <{self.email}>" return f"{self.name} <{self.email}>"