mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-03 09:43:33 +02:00
Simplify logic
This commit is contained in:
parent
795a4d71a2
commit
20161fe7f6
2 changed files with 65 additions and 71 deletions
|
@ -1,9 +1,9 @@
|
||||||
"""Forms for domain management."""
|
"""Forms for domain management."""
|
||||||
|
import logging
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator
|
from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator
|
||||||
from django.forms import formset_factory
|
from django.forms import formset_factory
|
||||||
|
from registrar.models import DomainApplication
|
||||||
from phonenumber_field.widgets import RegionalPhoneNumberWidget
|
from phonenumber_field.widgets import RegionalPhoneNumberWidget
|
||||||
from registrar.utility.errors import (
|
from registrar.utility.errors import (
|
||||||
NameserverError,
|
NameserverError,
|
||||||
|
@ -23,6 +23,9 @@ from .common import (
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DomainAddUserForm(forms.Form):
|
class DomainAddUserForm(forms.Form):
|
||||||
"""Form for adding a user to a domain."""
|
"""Form for adding a user to a domain."""
|
||||||
|
|
||||||
|
@ -205,6 +208,13 @@ class ContactForm(forms.ModelForm):
|
||||||
"required": "Enter your email address in the required format, like name@example.com."
|
"required": "Enter your email address in the required format, like name@example.com."
|
||||||
}
|
}
|
||||||
self.fields["phone"].error_messages["required"] = "Enter your phone number."
|
self.fields["phone"].error_messages["required"] = "Enter your phone number."
|
||||||
|
self.domainInfo = None
|
||||||
|
|
||||||
|
def set_domain_info(self, domainInfo):
|
||||||
|
"""Set the domain information for the form.
|
||||||
|
The form instance is associated with the contact itself. In order to access the associated
|
||||||
|
domain information object, this needs to be set in the form by the view."""
|
||||||
|
self.domainInfo = domainInfo
|
||||||
|
|
||||||
|
|
||||||
class AuthorizingOfficialContactForm(ContactForm):
|
class AuthorizingOfficialContactForm(ContactForm):
|
||||||
|
@ -232,20 +242,32 @@ class AuthorizingOfficialContactForm(ContactForm):
|
||||||
self.fields["email"].error_messages = {
|
self.fields["email"].error_messages = {
|
||||||
"required": "Enter an email address in the required format, like name@example.com."
|
"required": "Enter an email address in the required format, like name@example.com."
|
||||||
}
|
}
|
||||||
self.domainInfo = None
|
|
||||||
|
|
||||||
def set_domain_info(self, domainInfo):
|
|
||||||
"""Set the domain information for the form.
|
|
||||||
The form instance is associated with the contact itself. In order to access the associated
|
|
||||||
domain information object, this needs to be set in the form by the view."""
|
|
||||||
self.domainInfo = domainInfo
|
|
||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
"""Override the save() method of the BaseModelForm."""
|
"""
|
||||||
|
Override the save() method of the BaseModelForm.
|
||||||
|
Used to perform checks on the underlying domain_information object.
|
||||||
|
If this doesn't exist, we just save as normal.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# If the underlying Domain doesn't have a domainInfo object,
|
||||||
|
# just let the default super handle it.
|
||||||
|
if not self.domainInfo:
|
||||||
|
return super().save()
|
||||||
|
|
||||||
|
# Determine if the domain is federal or tribal
|
||||||
|
is_federal = self.domainInfo.organization_type == DomainApplication.OrganizationChoices.FEDERAL
|
||||||
|
is_tribal = self.domainInfo.organization_type == DomainApplication.OrganizationChoices.TRIBAL
|
||||||
|
|
||||||
# Get the Contact object from the db for the Authorizing Official
|
# Get the Contact object from the db for the Authorizing Official
|
||||||
db_ao = Contact.objects.get(id=self.instance.id)
|
db_ao = Contact.objects.get(id=self.instance.id)
|
||||||
if self.domainInfo and db_ao.has_more_than_one_join("information_authorizing_official"):
|
|
||||||
|
if (is_federal or is_tribal) and self.has_changed():
|
||||||
|
# This action should be blocked by the UI, as the text fields are readonly.
|
||||||
|
# If they get past this point, we forbid it this way.
|
||||||
|
# This could be malicious, so lets reserve information for the backend only.
|
||||||
|
raise ValueError("Authorizing Official cannot be modified for federal or tribal domains.")
|
||||||
|
elif db_ao.has_more_than_one_join("information_authorizing_official"):
|
||||||
# Handle the case where the domain information object is available and the AO Contact
|
# Handle the case where the domain information object is available and the AO Contact
|
||||||
# has more than one joined object.
|
# has more than one joined object.
|
||||||
# In this case, create a new Contact, and update the new Contact with form data.
|
# In this case, create a new Contact, and update the new Contact with form data.
|
||||||
|
@ -254,6 +276,7 @@ class AuthorizingOfficialContactForm(ContactForm):
|
||||||
self.domainInfo.authorizing_official = Contact.objects.create(**data)
|
self.domainInfo.authorizing_official = Contact.objects.create(**data)
|
||||||
self.domainInfo.save()
|
self.domainInfo.save()
|
||||||
else:
|
else:
|
||||||
|
# If all checks pass, just save normally
|
||||||
super().save()
|
super().save()
|
||||||
|
|
||||||
|
|
||||||
|
@ -334,6 +357,36 @@ class DomainOrgNameAddressForm(forms.ModelForm):
|
||||||
self.fields["state_territory"].widget.attrs.pop("maxlength", None)
|
self.fields["state_territory"].widget.attrs.pop("maxlength", None)
|
||||||
self.fields["zipcode"].widget.attrs.pop("maxlength", None)
|
self.fields["zipcode"].widget.attrs.pop("maxlength", None)
|
||||||
|
|
||||||
|
def save(self, commit=True):
|
||||||
|
"""Override the save() method of the BaseModelForm."""
|
||||||
|
if self.has_changed():
|
||||||
|
is_federal = self.instance.organization_type == DomainApplication.OrganizationChoices.FEDERAL
|
||||||
|
is_tribal = self.instance.organization_type == DomainApplication.OrganizationChoices.TRIBAL
|
||||||
|
|
||||||
|
# This action should be blocked by the UI, as the text fields are readonly.
|
||||||
|
# If they get past this point, we forbid it this way.
|
||||||
|
# This could be malicious, so lets reserve information for the backend only.
|
||||||
|
if is_federal and not self._field_unchanged("federal_agency"):
|
||||||
|
raise ValueError("federal_agency cannot be modified when the organization_type is federal")
|
||||||
|
elif is_tribal and not self._field_unchanged("organization_name"):
|
||||||
|
raise ValueError("organization_name cannot be modified when the organization_type is tribal")
|
||||||
|
|
||||||
|
else:
|
||||||
|
super().save()
|
||||||
|
|
||||||
|
def _field_unchanged(self, field_name) -> bool:
|
||||||
|
"""
|
||||||
|
Checks if a specified field has not changed between the old value
|
||||||
|
and the new value.
|
||||||
|
|
||||||
|
The old value is grabbed from self.initial.
|
||||||
|
The new value is grabbed from self.cleaned_data.
|
||||||
|
"""
|
||||||
|
old_value = self.initial.get(field_name, None)
|
||||||
|
new_value = self.cleaned_data.get(field_name, None)
|
||||||
|
return old_value == new_value
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DomainDnssecForm(forms.Form):
|
class DomainDnssecForm(forms.Form):
|
||||||
"""Form for enabling and disabling dnssec"""
|
"""Form for enabling and disabling dnssec"""
|
||||||
|
|
|
@ -213,43 +213,6 @@ class DomainOrgNameAddressView(DomainFormBaseView):
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
"""The form is valid, save the organization name and mailing address."""
|
"""The form is valid, save the organization name and mailing address."""
|
||||||
|
|
||||||
current_domain_info = self.get_domain_info_from_domain()
|
|
||||||
if current_domain_info is None:
|
|
||||||
messages.error(self.request, "Something went wrong when attempting to save.")
|
|
||||||
return self.form_invalid(form)
|
|
||||||
|
|
||||||
# Get the old and new values to see if a change is occuring
|
|
||||||
old_org_info = form.initial
|
|
||||||
new_org_info = form.cleaned_data
|
|
||||||
|
|
||||||
if old_org_info != new_org_info:
|
|
||||||
|
|
||||||
error_message = None
|
|
||||||
# These actions, aside from the default, should be blocked by the UI, as the field is readonly.
|
|
||||||
# If they get past this point, we forbid it this way.
|
|
||||||
# This could be malicious, but it won't always be.
|
|
||||||
match current_domain_info.organization_type:
|
|
||||||
case DomainApplication.OrganizationChoices.FEDERAL:
|
|
||||||
old_fed_agency = old_org_info.get("federal_agency", None)
|
|
||||||
new_fed_agency = new_org_info.get("federal_agency", None)
|
|
||||||
if old_fed_agency != new_fed_agency:
|
|
||||||
error_message = "You cannot modify Federal Agency"
|
|
||||||
case DomainApplication.OrganizationChoices.TRIBAL:
|
|
||||||
old_org_name = old_org_info.get("organization_name", None)
|
|
||||||
new_org_name = new_org_info.get("organization_name", None)
|
|
||||||
if old_org_name != new_org_name:
|
|
||||||
error_message = "You cannot modify Organization Name."
|
|
||||||
case _:
|
|
||||||
# Do nothing
|
|
||||||
pass
|
|
||||||
|
|
||||||
# If we encounter an error, forbid this action.
|
|
||||||
if error_message is not None:
|
|
||||||
logger.warning(f"User {self.request.user} attempted to change org info on {self.object.name}")
|
|
||||||
messages.error(self.request, "You cannot modify the Authorizing Official.")
|
|
||||||
return self.form_invalid(form)
|
|
||||||
|
|
||||||
form.save()
|
form.save()
|
||||||
|
|
||||||
messages.success(self.request, "The organization information for this domain has been updated.")
|
messages.success(self.request, "The organization information for this domain has been updated.")
|
||||||
|
@ -278,31 +241,9 @@ class DomainAuthorizingOfficialView(DomainFormBaseView):
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
"""The form is valid, save the authorizing official."""
|
"""The form is valid, save the authorizing official."""
|
||||||
# if not self.request.user.is_staff:
|
|
||||||
|
|
||||||
current_domain_info = self.get_domain_info_from_domain()
|
|
||||||
if current_domain_info is None:
|
|
||||||
messages.error(self.request, "Something went wrong when attempting to save.")
|
|
||||||
return self.form_invalid(form)
|
|
||||||
|
|
||||||
# Determine if the domain is federal or tribal
|
|
||||||
is_federal = current_domain_info.organization_type == DomainApplication.OrganizationChoices.FEDERAL
|
|
||||||
is_tribal = current_domain_info.organization_type == DomainApplication.OrganizationChoices.TRIBAL
|
|
||||||
|
|
||||||
# Get the old and new ao values
|
|
||||||
old_authorizing_official = form.initial
|
|
||||||
new_authorizing_official = form.cleaned_data
|
|
||||||
|
|
||||||
# This action should be blocked by the UI, as the text fields are readonly.
|
|
||||||
# If they get past this point, we forbid it this way.
|
|
||||||
# This could be malicious, but it won't always be.
|
|
||||||
if (is_federal or is_tribal) and old_authorizing_official != new_authorizing_official:
|
|
||||||
logger.warning(f"User {self.request.user} attempted to change AO on {self.object.name}")
|
|
||||||
messages.error(self.request, "You cannot modify the Authorizing Official.")
|
|
||||||
return self.form_invalid(form)
|
|
||||||
|
|
||||||
# Set the domain information in the form so that it can be accessible
|
# Set the domain information in the form so that it can be accessible
|
||||||
# to associate a new Contact as authorizing official, if new Contact is needed
|
# to associate a new Contact, if a new Contact is needed
|
||||||
# in the save() method
|
# in the save() method
|
||||||
form.set_domain_info(self.object.domain_info)
|
form.set_domain_info(self.object.domain_info)
|
||||||
form.save()
|
form.save()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue