From 2846f9c6b9e7dc450590e815cab7fbfc2a06fbcc Mon Sep 17 00:00:00 2001 From: jianglai Date: Sat, 6 May 2017 10:10:10 -0700 Subject: [PATCH] This CL include changes in the registrar console that makes it possible to designate an abuse contact in domain WHOIS record, per ICANN's CL&D requirement. Frontend validation: ensures that only one WHOIS abuse contact exist per registrar. Any existing WHOIS abuse contact will be overridden when a new one is designated. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=155289097 --- java/google/registry/ui/externs/json.js | 1 + .../ui/js/registrar/contact_settings.js | 10 ++++ .../registrar/RegistrarSettingsAction.java | 38 +++++++++++++- .../ui/soy/registrar/ContactSettings.soy | 37 +++++++++++--- .../ui/js/registrar/contact_settings_test.js | 34 ++++++++++++- .../server/registrar/ContactSettingsTest.java | 51 +++++++++++++++++++ 6 files changed, 162 insertions(+), 9 deletions(-) diff --git a/java/google/registry/ui/externs/json.js b/java/google/registry/ui/externs/json.js index cc47052ab..837b07432 100644 --- a/java/google/registry/ui/externs/json.js +++ b/java/google/registry/ui/externs/json.js @@ -108,6 +108,7 @@ registry.json.RegistrarAddress; * emailAddress: string, * visibleInWhoisAsAdmin: boolean, * visibleInWhoisAsTech: boolean, + * visibleInDomainWhoisAsAbuse: boolean, * phoneNumber: (string?|undefined), * faxNumber: (string?|undefined), * types: (string?|undefined) diff --git a/java/google/registry/ui/js/registrar/contact_settings.js b/java/google/registry/ui/js/registrar/contact_settings.js index c5daf2844..ae3591fab 100644 --- a/java/google/registry/ui/js/registrar/contact_settings.js +++ b/java/google/registry/ui/js/registrar/contact_settings.js @@ -196,6 +196,8 @@ registry.registrar.ContactSettings.prototype.prepareUpdate = } contact.visibleInWhoisAsAdmin = contact.visibleInWhoisAsAdmin == 'true'; contact.visibleInWhoisAsTech = contact.visibleInWhoisAsTech == 'true'; + contact.visibleInDomainWhoisAsAbuse = + contact.visibleInDomainWhoisAsAbuse == 'true'; contact.types = ''; for (var tNdx in contact.type) { if (contact.type[tNdx]) { @@ -206,6 +208,14 @@ registry.registrar.ContactSettings.prototype.prepareUpdate = } } delete contact['type']; + // Override previous domain WHOIS abuse contact. + if (contact.visibleInDomainWhoisAsAbuse) { + for (var c in modelCopy.contacts) { + if (modelCopy.contacts[c].emailAddress != contact.emailAddress) { + modelCopy.contacts[c].visibleInDomainWhoisAsAbuse = false; + } + } + } this.nextId = contact.emailAddress; }; diff --git a/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java b/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java index 022125e60..2cbb5b6ab 100644 --- a/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java +++ b/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java @@ -29,6 +29,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; import com.googlecode.objectify.Work; import google.registry.config.RegistryConfig.Config; @@ -52,6 +53,7 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import javax.annotation.Nullable; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; @@ -270,11 +272,25 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA } } ensurePhoneNumberNotRemovedForContactTypes(oldContactsByType, newContactsByType, Type.TECH); + Optional domainWhoisAbuseContact = + getDomainWhoisVisibleAbuseContact(updatedContacts); + // If the new set has a domain WHOIS abuse contact, it must have a phone number. + if (domainWhoisAbuseContact.isPresent() + && domainWhoisAbuseContact.get().getPhoneNumber() == null) { + throw new ContactRequirementException( + "The abuse contact visible in domain WHOIS query must have a phone number"); + } + // If there was a domain WHOIS abuse contact in the old set, the new set must have one. + if (getDomainWhoisVisibleAbuseContact(existingContacts).isPresent() + && !domainWhoisAbuseContact.isPresent()) { + throw new ContactRequirementException( + "An abuse contact visible in domain WHOIS query must be designated"); + } } /** - * Ensure that for each given registrar type, a phone number is present after update, if there - * was one before. + * Ensure that for each given registrar type, a phone number is present after update, if there was + * one before. */ private static void ensurePhoneNumberNotRemovedForContactTypes( Multimap oldContactsByType, @@ -291,6 +307,24 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA } } + /** + * Retrieves the registrar contact whose phone number and email address is visible in domain WHOIS + * query as abuse contact (if any). + * + *

Frontend processing ensures that only one contact can be set as abuse contact in domain + * WHOIS record. Therefore it is possible to return inside the loop once one such contact is + * found. + */ + private static Optional getDomainWhoisVisibleAbuseContact( + Set contacts) { + return Iterables.tryFind(contacts, new Predicate() { + @Override + public boolean apply(@Nullable RegistrarContact contact) { + return contact.getVisibleInDomainWhoisAsAbuse(); + } + }); + } + /** * Determines if any changes were made to the registrar besides the lastUpdateTime, and if so, * sends an email with a diff of the changes to the configured notification email address and diff --git a/java/google/registry/ui/soy/registrar/ContactSettings.soy b/java/google/registry/ui/soy/registrar/ContactSettings.soy index 2edb2d69f..4f98c7673 100644 --- a/java/google/registry/ui/soy/registrar/ContactSettings.soy +++ b/java/google/registry/ui/soy/registrar/ContactSettings.soy @@ -46,7 +46,9 @@ {param name: $c['name'] /} {param emailAddress: $c['emailAddress'] /} {param visibleInWhois: - ($c['visibleInWhoisAsAdmin'] or $c['visibleInWhoisAsTech']) /} + ($c['visibleInWhoisAsAdmin'] + or $c['visibleInWhoisAsTech'] + or $c['visibleInDomainWhoisAsAbuse']) /} {param phoneNumber: $c['phoneNumber'] /} {param faxNumber: $c['faxNumber'] /} {/call} @@ -199,12 +201,17 @@

{let $visibleAsAdmin: $item['visibleInWhoisAsAdmin'] == true /} {let $visibleAsTech: $item['visibleInWhoisAsTech'] == true /} - {if (not $visibleAsAdmin) and (not $visibleAsTech)} + {let $visibleAsDomainAbuse: $item['visibleInDomainWhoisAsAbuse'] == true /} + {if (not $visibleAsAdmin) and (not $visibleAsTech) and (not $visibleAsDomainAbuse)} Not visible in WHOIS {else} - {if $visibleAsAdmin}Admin{/if} + {if $visibleAsAdmin}Registrar Admin{/if} {if $visibleAsAdmin and $visibleAsTech},{sp}{/if} - {if $visibleAsTech}Technical{/if} + {if $visibleAsTech}Registrar Technical{/if} + {if $visibleAsTech} + {if $visibleAsDomainAbuse},{sp}{/if} + {elseif $visibleAsAdmin and $visibleAsDomainAbuse},{sp}{/if} + {if $visibleAsDomainAbuse}Domain Abuse{/if} {/if} {/template} @@ -231,31 +238,48 @@


{call .whoisVisibleRadios_} - {param description: 'Show in WHOIS as Admin contact' /} + {param description: 'Show in Registrar WHOIS record as Admin contact' /} {param fieldName: $namePrefix + 'visibleInWhoisAsAdmin' /} {param visible: $item['visibleInWhoisAsAdmin'] == true /} {/call} {call .whoisVisibleRadios_} - {param description: 'Show in WHOIS as Technical contact' /} + {param description: 'Show in Registrar WHOIS record as Technical contact' /} {param fieldName: $namePrefix + 'visibleInWhoisAsTech' /} {param visible: $item['visibleInWhoisAsTech'] == true /} {/call} + {call .whoisVisibleRadios_} + {param description: + 'Show Phone and Email in Domain WHOIS Record as Registrar Abuse Contact' + + ' (Per CL&D Requirements)' + /} + {param note: + '*Can only apply to one contact. Selecting Yes for this contact will' + + ' force this setting for all other contacts to be No.' + /} + {param fieldName: $namePrefix + 'visibleInDomainWhoisAsAbuse' /} + {param visible: $item['visibleInDomainWhoisAsAbuse'] == true /} + {/call} {/template} /** @private */ {template .whoisVisibleRadios_ private="true"} {@param description: string} + {@param? note: string} {@param fieldName: string} {@param visible: bool} + {if $note} + {$note} + {/if}