diff --git a/src/registrar/forms/__init__.py b/src/registrar/forms/__init__.py index 186b24362..e889405c9 100644 --- a/src/registrar/forms/__init__.py +++ b/src/registrar/forms/__init__.py @@ -5,5 +5,5 @@ from .domain import ( DomainSecurityEmailForm, DomainOrgNameAddressForm, ContactForm, - DNSSECDSDataFormset, + DomainDsdataFormset, ) diff --git a/src/registrar/forms/domain.py b/src/registrar/forms/domain.py index a1b7b57d7..ea74db467 100644 --- a/src/registrar/forms/domain.py +++ b/src/registrar/forms/domain.py @@ -141,24 +141,29 @@ class DomainOrgNameAddressForm(forms.ModelForm): self.fields["zipcode"].widget.attrs.pop("maxlength", None) -class DomainDNSSECDSDataForm(forms.Form): +class DomainDsdataForm(forms.Form): """Form for adding or editing a security email to a domain.""" # Q: What are the options? ALGORITHM_CHOICES = [ - ("ECC Ghost", "ECC Ghost"), + (1, "ERSA/MD5 [RSAMD5]"), + (2 , "Diffie-Hellman [DH]"), + (3 ,"DSA/SHA-1 [DSA]"), + (5 ,"RSA/SHA-1 [RSASHA1]"), ] # Q: What are the options? DIGEST_TYPE_CHOICES = [ - ("SHA-256", "SHA-256"), + (0, "Reserved"), + (1, "SHA-256"), ] - has_ds_key_data = forms.TypedChoiceField( - required=True, - label="DS Data record type", - choices=[(False, "DS Data"), (True, "DS Data with Key Data")], - ) + # TODO: ds key data + # has_ds_key_data = forms.TypedChoiceField( + # required=True, + # label="DS Data record type", + # choices=[(False, "DS Data"), (True, "DS Data with Key Data")], + # ) key_tag = forms.IntegerField( required=True, @@ -172,20 +177,21 @@ class DomainDNSSECDSDataForm(forms.Form): ) algorithm = forms.TypedChoiceField( + required=True, label="Algorithm", - choices=[("", "--Select--")] + ALGORITHM_CHOICES, + choices=[(-1, "--Select--")] + ALGORITHM_CHOICES, # Q: Is this even needed or is a required=True sufficient? - error_messages={ - "required": ( - "You must select an Algorithm" - ) - }, + # error_messages={ + # "required": ( + # "You must select an Algorithm" + # ) + # }, ) # Q: Is ChoiceFiled right? Or do we need to data types other than strings # (TypedChoiceField) digest_type = forms.TypedChoiceField( label="Digest Type", - choices=[("", "--Select--")] + DIGEST_TYPE_CHOICES, + choices=[(-1, "--Select--")] + DIGEST_TYPE_CHOICES, # Q: Is this even needed or is a required=True sufficient? error_messages={ "required": ( @@ -193,12 +199,28 @@ class DomainDNSSECDSDataForm(forms.Form): ) }, ) - digest = forms.CharField(label="Digest") + digest = forms.CharField( + required=True, + label="Digest", + # validators=[ + # RegexValidator( + # "^[0-9]{5}(?:-[0-9]{4})?$|^$", + # message="Accepted range 0-65535.", + # ) + # ], + ) - # Conditional DS Key Data fields + # TODO: Conditional DS Key Data fields + -DNSSECDSDataFormset = formset_factory( - DomainDNSSECDSDataForm, +DomainDsdataFormset = formset_factory( + DomainDsdataForm, extra=1, -) \ No newline at end of file +) + + +# TODO: +# class DomainKeyDataForm(forms.Form): + +# """""" \ No newline at end of file diff --git a/src/registrar/templates/domain_dsdata.html b/src/registrar/templates/domain_dsdata.html index 08a6bf74e..147fcde64 100644 --- a/src/registrar/templates/domain_dsdata.html +++ b/src/registrar/templates/domain_dsdata.html @@ -7,4 +7,40 @@

DS Data

+ {% include "includes/required_fields.html" %} + +
+ {% csrf_token %} + {{ formset.management_form }} + + {% for form in formset %} +
+ {% with attr_required=True %} + {% input_with_errors form.key_tag %} + {% endwith %} + {% with attr_required=True %} + {% input_with_errors form.algorithm %} + {% endwith %} + {% with attr_required=True %} + {% input_with_errors form.digest_type %} + {% endwith %} + {% with attr_required=True %} + {% input_with_errors form.digest %} + {% endwith %} +
+ {% endfor %} + + + + +
+ {% endblock %} {# domain_content #} diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 977a0fee3..ec940568a 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -28,7 +28,14 @@ from ..forms import ( DomainAddUserForm, DomainSecurityEmailForm, NameserverFormset, + DomainDsdataFormset, ) + +from epplibwrapper import ( + common, + extensions, +) + from ..utility.email import send_templated_email, EmailSendingError from .utility import DomainPermissionView, DomainInvitationPermissionDeleteView @@ -233,6 +240,73 @@ class DomainDsdataView(DomainPermissionView): """Domain DNSSEC ds data editing view.""" template_name = "domain_dsdata.html" + form_class = DomainDsdataFormset + + def get_initial(self): + """The initial value for the form (which is a formset here).""" + domain = self.get_object() + dnssecdata: extensions.DNSSECExtension = domain.dnssecdata + initial_data = [] + + if dnssecdata.keyData is not None: + # TODO: Throw an error + pass + + if dnssecdata.dsData is not None: + # Add existing nameservers as initial data + # TODO: create context for each element in the record + # key_tag + # algorithm + # digest_type + # digest + initial_data.extend({"dsrecord": record} for record in dnssecdata.dsData) + + return initial_data + + def get_success_url(self): + """Redirect to the DS Data page for the domain.""" + return reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.object.pk}) + + def get_context_data(self, **kwargs): + """Adjust context from FormMixin for formsets.""" + context = super().get_context_data(**kwargs) + # use "formset" instead of "form" for the key + context["formset"] = context.pop("form") + return context + + def post(self, request, *args, **kwargs): + """Formset submission posts to this view.""" + self.object = self.get_object() + formset = self.get_form() + + if formset.is_valid(): + return self.form_valid(formset) + else: + return self.form_invalid(formset) + + def form_valid(self, formset): + """The formset is valid, perform something with it.""" + + # Set the nameservers from the formset + dnssecdata = [] + for form in formset: + try: + # TODO: build the right list of dicts to be passed + dsrecord = (form.cleaned_data["dsrecord"],) + dnssecdata.append(dsrecord) + except KeyError: + # no server information in this field, skip it + pass + domain = self.get_object() + domain.dnssecdata = dnssecdata + + messages.success( + self.request, "The DS Data records for this domain have been updated." + ) + + # superclass has the redirect + return super().form_valid(formset) + class DomainKeydataView(DomainPermissionView):