1
0
mirror of https://github.com/google/nomulus synced 2026-06-05 14:32:51 +00:00

Remove contact entities from RDAP entirely when they don't exist in DB (#2497)

This is consistent with how other registries are handling RDAP and is also consistent
with overall behavior in WHOIS and domain info flows as implemented in my previous
PRs #2477 and #2490.
This commit is contained in:
Ben McIlwain
2024-07-18 15:33:52 -04:00
committed by GitHub
parent 0241937dee
commit c4e5bc913e
9 changed files with 274 additions and 186 deletions

View File

@@ -276,27 +276,23 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
}
@Test
void testValidDomain_notLoggedIn_noContacts() {
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_contacts_with_remark.json");
void testValidDomain_notLoggedIn_redactsAllContactInfo() {
assertProperResponseForCatLol("cat.lol", "rdap_domain_redacted_contacts_with_remark.json");
}
@Test
void testValidDomain_notLoggedIn_contactsShowRedacted_evenWhenRegistrantDoesntExist() {
// Even though the registrant is empty on this domain, it still shows a full set of REDACTED
// fields through RDAP.
void testValidDomain_notLoggedIn_showsNoRegistrant_whenRegistrantDoesntExist() {
persistResource(
loadByForeignKey(Domain.class, "cat.lol", clock.nowUtc())
.get()
.asBuilder()
.setRegistrant(Optional.empty())
.build());
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_contacts_with_remark.json");
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_registrant_with_remark.json");
}
@Test
void testValidDomain_notLoggedIn_contactsShowRedacted_whenNoContactsExist() {
// Even though the domain has no contacts, it still shows a full set of REDACTED fields through
// RDAP.
void testValidDomain_notLoggedIn_containsNoContactEntities_whenNoContactsExist() {
persistResource(
loadByForeignKey(Domain.class, "cat.lol", clock.nowUtc())
.get()
@@ -308,24 +304,38 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
}
@Test
void testValidDomain_loggedInAsOtherRegistrar_noContacts() {
void testValidDomain_loggedIn_containsNoContactEntities_whenNoContactsExist() {
login("evilregistrar");
persistResource(
loadByForeignKey(Domain.class, "cat.lol", clock.nowUtc())
.get()
.asBuilder()
.setRegistrant(Optional.empty())
.setContacts(ImmutableSet.of())
.build());
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_contacts_exist_with_remark.json");
}
@Test
void testValidDomain_loggedInAsOtherRegistrar_redactsAllContactInfo() {
login("idnregistrar");
assertProperResponseForCatLol("cat.lol", "rdap_domain_no_contacts_with_remark.json");
assertProperResponseForCatLol("cat.lol", "rdap_domain_redacted_contacts_with_remark.json");
}
@Test
void testUpperCase_ignored() {
assertProperResponseForCatLol("CaT.lOl", "rdap_domain_no_contacts_with_remark.json");
assertProperResponseForCatLol("CaT.lOl", "rdap_domain_redacted_contacts_with_remark.json");
}
@Test
void testTrailingDot_ignored() {
assertProperResponseForCatLol("cat.lol.", "rdap_domain_no_contacts_with_remark.json");
assertProperResponseForCatLol("cat.lol.", "rdap_domain_redacted_contacts_with_remark.json");
}
@Test
void testQueryParameter_ignored() {
assertProperResponseForCatLol("cat.lol?key=value", "rdap_domain_no_contacts_with_remark.json");
assertProperResponseForCatLol(
"cat.lol?key=value", "rdap_domain_redacted_contacts_with_remark.json");
}
@Test

View File

@@ -750,7 +750,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
void testDomainMatch_found_loggedInAsOtherRegistrar() {
login("otherregistrar");
runSuccessfulTestWithCatLol(
RequestType.NAME, "cat.lol", "rdap_domain_no_contacts_with_remark.json");
RequestType.NAME, "cat.lol", "rdap_domain_redacted_contacts_with_remark.json");
verifyMetrics(SearchType.BY_DOMAIN_NAME, Optional.of(1L));
}
@@ -782,7 +782,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
.addRegistrar("St. John Chrysostom")
.addNameserver("ns1.cat.lol", "8-ROID")
.addNameserver("ns2.external.tld", "1F-ROID")
.load("rdap_domain_no_contacts_with_remark.json"));
.load("rdap_domain_redacted_contacts_with_remark.json"));
verifyMetrics(SearchType.BY_DOMAIN_NAME, Optional.of(1L));
}
@@ -826,7 +826,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
.addRegistrar("1.test")
.addNameserver("ns1.cat.1.test", "35-ROID")
.addNameserver("ns2.cat.2.test", "37-ROID")
.load("rdap_domain_no_contacts_with_remark.json"));
.load("rdap_domain_redacted_contacts_with_remark.json"));
verifyMetrics(SearchType.BY_DOMAIN_NAME, Optional.of(1L));
}
@@ -840,7 +840,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
.addRegistrar("1.test")
.addNameserver("ns1.cat.1.test", "35-ROID")
.addNameserver("ns2.cat.2.test", "37-ROID")
.load("rdap_domain_no_contacts_with_remark.json"));
.load("rdap_domain_redacted_contacts_with_remark.json"));
verifyMetrics(SearchType.BY_DOMAIN_NAME, Optional.of(1L));
}
@@ -1378,7 +1378,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
.addRegistrar("1.test")
.addNameserver("ns1.cat.1.test", "35-ROID")
.addNameserver("ns2.cat.2.test", "37-ROID")
.load("rdap_domain_no_contacts_with_remark.json"));
.load("rdap_domain_redacted_contacts_with_remark.json"));
verifyMetrics(SearchType.BY_NAMESERVER_NAME, 1, 1);
}
@@ -1392,7 +1392,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
.addRegistrar("1.test")
.addNameserver("ns1.cat.1.test", "35-ROID")
.addNameserver("ns2.cat.2.test", "37-ROID")
.load("rdap_domain_no_contacts_with_remark.json"));
.load("rdap_domain_redacted_contacts_with_remark.json"));
verifyMetrics(SearchType.BY_NAMESERVER_NAME, 1, 1);
}
@@ -1675,7 +1675,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
runSuccessfulTestWithCatLol(
RequestType.NS_IP,
"bad:f00d:cafe:0:0:0:15:beef",
"rdap_domain_no_contacts_with_remark.json");
"rdap_domain_redacted_contacts_with_remark.json");
verifyMetrics(SearchType.BY_NAMESERVER_ADDRESS, 1, 1);
}

View File

@@ -52,7 +52,6 @@ import google.registry.rdap.RdapObjectClasses.ReplyPayloadBase;
import google.registry.rdap.RdapObjectClasses.TopLevelReplyObject;
import google.registry.testing.FakeClock;
import google.registry.testing.FullFieldsTestEntityHelper;
import java.util.Optional;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
@@ -373,7 +372,7 @@ class RdapJsonFormatterTest {
.that(
rdapJsonFormatter
.createRdapContactEntity(
Optional.of(contactRegistrant),
contactRegistrant,
ImmutableSet.of(RdapEntity.Role.REGISTRANT),
OutputDataType.FULL)
.toJson())
@@ -386,7 +385,7 @@ class RdapJsonFormatterTest {
.that(
rdapJsonFormatter
.createRdapContactEntity(
Optional.of(contactRegistrant),
contactRegistrant,
ImmutableSet.of(RdapEntity.Role.REGISTRANT),
OutputDataType.SUMMARY)
.toJson())
@@ -400,7 +399,7 @@ class RdapJsonFormatterTest {
.that(
rdapJsonFormatter
.createRdapContactEntity(
Optional.of(contactRegistrant),
contactRegistrant,
ImmutableSet.of(RdapEntity.Role.REGISTRANT),
OutputDataType.FULL)
.toJson())
@@ -420,7 +419,7 @@ class RdapJsonFormatterTest {
.that(
rdapJsonFormatter
.createRdapContactEntity(
Optional.of(contactRegistrant),
contactRegistrant,
ImmutableSet.of(RdapEntity.Role.REGISTRANT),
OutputDataType.FULL)
.toJson())
@@ -433,9 +432,7 @@ class RdapJsonFormatterTest {
.that(
rdapJsonFormatter
.createRdapContactEntity(
Optional.of(contactAdmin),
ImmutableSet.of(RdapEntity.Role.ADMIN),
OutputDataType.FULL)
contactAdmin, ImmutableSet.of(RdapEntity.Role.ADMIN), OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_admincontact.json"));
}
@@ -446,9 +443,7 @@ class RdapJsonFormatterTest {
.that(
rdapJsonFormatter
.createRdapContactEntity(
Optional.of(contactTech),
ImmutableSet.of(RdapEntity.Role.TECH),
OutputDataType.FULL)
contactTech, ImmutableSet.of(RdapEntity.Role.TECH), OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_techcontact.json"));
}
@@ -458,8 +453,7 @@ class RdapJsonFormatterTest {
assertAboutJson()
.that(
rdapJsonFormatter
.createRdapContactEntity(
Optional.of(contactTech), ImmutableSet.of(), OutputDataType.FULL)
.createRdapContactEntity(contactTech, ImmutableSet.of(), OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_rolelesscontact.json"));
}
@@ -469,8 +463,7 @@ class RdapJsonFormatterTest {
assertAboutJson()
.that(
rdapJsonFormatter
.createRdapContactEntity(
Optional.of(contactNotLinked), ImmutableSet.of(), OutputDataType.FULL)
.createRdapContactEntity(contactNotLinked, ImmutableSet.of(), OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_unlinkedcontact.json"));
}

View File

@@ -147,117 +147,6 @@
"type": "object truncated due to unexplainable reasons"
}
]
},
{
"objectClassName":"entity",
"handle":"",
"remarks":[
{
"title":"REDACTED FOR PRIVACY",
"type":"object redacted due to authorization",
"description":[
"Some of the data in this object has been removed.",
"Contact personal data is visible only to the owning registrar."
],
"links":[
{
"href":"https://github.com/google/nomulus/blob/master/docs/rdap.md#authentication",
"rel":"alternate",
"type":"text/html"
}
]
},
{
"title":"EMAIL REDACTED FOR PRIVACY",
"type":"object redacted due to authorization",
"description":[
"Please query the RDDS service of the Registrar of Record identifies in this output for information on how to contact the Registrant of the queried domain name."
]
}
],
"roles":["registrant"],
"vcardArray":[
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", ""]
]
]
},
{
"objectClassName": "entity",
"handle": "",
"roles":["administrative"],
"remarks": [
{
"title":"REDACTED FOR PRIVACY",
"type":"object redacted due to authorization",
"description": [
"Some of the data in this object has been removed.",
"Contact personal data is visible only to the owning registrar."
],
"links":[
{
"href":"https://github.com/google/nomulus/blob/master/docs/rdap.md#authentication",
"rel":"alternate",
"type":"text/html"
}
]
},
{
"title":"EMAIL REDACTED FOR PRIVACY",
"type":"object redacted due to authorization",
"description": [
"Please query the RDDS service of the Registrar of Record identifies in this output for information on how to contact the Registrant of the queried domain name."
]
}
],
"vcardArray":[
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", ""]
]
]
},
{
"objectClassName":"entity",
"handle":"",
"remarks":[
{
"title":"REDACTED FOR PRIVACY",
"type":"object redacted due to authorization",
"description":[
"Some of the data in this object has been removed.",
"Contact personal data is visible only to the owning registrar."
],
"links":[
{
"href":"https://github.com/google/nomulus/blob/master/docs/rdap.md#authentication",
"rel":"alternate",
"type":"text/html"
}
]
},
{
"description":[
"Please query the RDDS service of the Registrar of Record identifies in this output for information on how to contact the Registrant of the queried domain name."
],
"title":"EMAIL REDACTED FOR PRIVACY",
"type":"object redacted due to authorization"
}
],
"roles": ["technical"],
"vcardArray": [
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", ""]
]
]
}
]
}

View File

@@ -0,0 +1,225 @@
{
"rdapConformance": [
"rdap_level_0",
"icann_rdap_response_profile_0",
"icann_rdap_technical_implementation_guide_0"
],
"objectClassName": "domain",
"handle": "%DOMAIN_HANDLE_1%",
"ldhName": "%DOMAIN_PUNYCODE_NAME_1%",
"status": [
"client delete prohibited",
"client renew prohibited",
"client transfer prohibited",
"server update prohibited"
],
"links": [
{
"href": "https://example.tld/rdap/domain/%DOMAIN_PUNYCODE_NAME_1%",
"type": "application/rdap+json",
"rel": "self"
},
{
"href": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
"type": "application/rdap+json",
"rel": "related"
},
{
"href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
"type": "application/rdap+json",
"rel": "related"
}
],
"events": [
{
"eventAction": "registration",
"eventActor": "TheRegistrar",
"eventDate": "1997-01-01T00:00:00.000Z"
},
{
"eventAction": "expiration",
"eventDate": "2110-10-08T00:44:59.000Z"
},
{
"eventAction": "last update of RDAP database",
"eventDate": "2000-01-01T00:00:00.000Z"
},
{
"eventAction": "last changed",
"eventDate": "2009-05-29T20:13:00.000Z"
}
],
"nameservers": [
{
"objectClassName": "nameserver",
"handle": "%NAMESERVER_HANDLE_1%",
"ldhName": "%NAMESERVER_NAME_1%",
"links": [
{
"href": "https://example.tld/rdap/nameserver/%NAMESERVER_NAME_1%",
"type": "application/rdap+json",
"rel": "self"
}
],
"remarks": [
{
"title": "Incomplete Data",
"type": "object truncated due to unexplainable reasons",
"description": ["Summary data only. For complete data, send a specific query for the object."]
}
]
},
{
"objectClassName": "nameserver",
"handle": "%NAMESERVER_HANDLE_2%",
"ldhName": "%NAMESERVER_NAME_2%",
"links": [
{
"href": "https://example.tld/rdap/nameserver/%NAMESERVER_NAME_2%",
"type": "application/rdap+json",
"rel": "self"
}
],
"remarks": [
{
"title": "Incomplete Data",
"type": "object truncated due to unexplainable reasons",
"description": ["Summary data only. For complete data, send a specific query for the object."]
}
]
}
],
"secureDNS" : {
"delegationSigned": true,
"zoneSigned":true,
"dsData":[
{"algorithm":2,"digest":"DEADFACE","digestType":3,"keyTag":1}
]
},
"entities": [
{
"objectClassName" : "entity",
"handle" : "1",
"roles" : ["registrar"],
"links" : [
{
"rel" : "self",
"href" : "https://example.tld/rdap/entity/1",
"type" : "application/rdap+json"
}
],
"publicIds" : [
{
"type" : "IANA Registrar ID",
"identifier" : "1"
}
],
"vcardArray" : [
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", "%REGISTRAR_FULL_NAME_1%"]
]
],
"entities" : [
{
"objectClassName":"entity",
"roles":["abuse"],
"status":["active"],
"vcardArray": [
"vcard",
[
["version",{},"text","4.0"],
["fn",{},"text","Jake Doe"],
["tel",{"type":["voice"]},"uri","tel:+1.2125551216"],
["tel",{"type":["fax"]},"uri","tel:+1.2125551216"],
["email",{},"text","jakedoe@example.com"]
]
]
}
],
"remarks": [
{
"title": "Incomplete Data",
"description": [
"Summary data only. For complete data, send a specific query for the object."
],
"type": "object truncated due to unexplainable reasons"
}
]
},
{
"objectClassName": "entity",
"handle": "",
"roles":["administrative"],
"remarks": [
{
"title":"REDACTED FOR PRIVACY",
"type":"object redacted due to authorization",
"description": [
"Some of the data in this object has been removed.",
"Contact personal data is visible only to the owning registrar."
],
"links":[
{
"href":"https://github.com/google/nomulus/blob/master/docs/rdap.md#authentication",
"rel":"alternate",
"type":"text/html"
}
]
},
{
"title":"EMAIL REDACTED FOR PRIVACY",
"type":"object redacted due to authorization",
"description": [
"Please query the RDDS service of the Registrar of Record identifies in this output for information on how to contact the Registrant of the queried domain name."
]
}
],
"vcardArray":[
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", ""]
]
]
},
{
"objectClassName":"entity",
"handle":"",
"remarks":[
{
"title":"REDACTED FOR PRIVACY",
"type":"object redacted due to authorization",
"description":[
"Some of the data in this object has been removed.",
"Contact personal data is visible only to the owning registrar."
],
"links":[
{
"href":"https://github.com/google/nomulus/blob/master/docs/rdap.md#authentication",
"rel":"alternate",
"type":"text/html"
}
]
},
{
"description":[
"Please query the RDDS service of the Registrar of Record identifies in this output for information on how to contact the Registrant of the queried domain name."
],
"title":"EMAIL REDACTED FOR PRIVACY",
"type":"object redacted due to authorization"
}
],
"roles": ["technical"],
"vcardArray": [
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", ""]
]
]
}
]
}