Remove email-editing footgun (#503)

* Remove email-editing footgun

Email address is used as the primary key so we should be very careful
about changing it. This will have even more importance when this is the
location to which we will be sending registry lock confirmation emails.

Note: we allow addition or removal of contacts through the UI (and don't
want to disable that) and because all edits are performed by saving the
entire list of contacts, we can't explicitly prevent all possible edits
of email address in the backend. So this doesn't technically prevent
anything security-wise, but it makes it much more difficult to
accidentally edit an email when you shouldn't.

* Enforce non-deletion of registry-lock-enabled contacts

* Fix tests

* Specify contact
This commit is contained in:
gbrodman
2020-04-29 11:44:51 -04:00
committed by GitHub
parent aa0dcea537
commit c361c9e601
10 changed files with 132 additions and 52 deletions
@@ -391,7 +391,8 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
* @throws FormException if the checks fail.
*/
void checkContactRequirements(
Set<RegistrarContact> existingContacts, Set<RegistrarContact> updatedContacts) {
ImmutableSet<RegistrarContact> existingContacts,
ImmutableSet<RegistrarContact> updatedContacts) {
// Check that no two contacts use the same email address.
Set<String> emails = new HashSet<>();
for (RegistrarContact contact : updatedContacts) {
@@ -435,7 +436,12 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
throw new ContactRequirementException(
"An abuse contact visible in domain WHOIS query must be designated");
}
checkContactRegistryLockRequirements(existingContacts, updatedContacts);
}
private static void checkContactRegistryLockRequirements(
ImmutableSet<RegistrarContact> existingContacts,
ImmutableSet<RegistrarContact> updatedContacts) {
// Any contact(s) with new passwords must be allowed to set them
for (RegistrarContact updatedContact : updatedContacts) {
if (updatedContact.isRegistryLockAllowed()
@@ -463,6 +469,31 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
}
}
}
// Any previously-existing contacts with registry lock enabled cannot be deleted
existingContacts.stream()
.filter(RegistrarContact::isRegistryLockAllowed)
.forEach(
contact -> {
Optional<RegistrarContact> updatedContactOptional =
updatedContacts.stream()
.filter(
updatedContact ->
updatedContact.getEmailAddress().equals(contact.getEmailAddress()))
.findFirst();
if (!updatedContactOptional.isPresent()) {
throw new FormException(
String.format(
"Cannot delete the contact %s that has registry lock enabled",
contact.getEmailAddress()));
}
if (!updatedContactOptional.get().isRegistryLockAllowed()) {
throw new FormException(
String.format(
"Cannot remove the ability to use registry lock on the contact %s",
contact.getEmailAddress()));
}
});
}
/**
@@ -145,6 +145,7 @@
{param label: 'Email' /}
{param namePrefix: $namePrefix /}
{param name: 'emailAddress' /}
{param disabled: not $readonly and $item['emailAddress'] != null /}
{/call}
{call registry.soy.forms.inputFieldRow data="all"}
{param label: 'Phone' /}