From 628f133e3a504427165b99f867cace6ecdd0dc0e Mon Sep 17 00:00:00 2001 From: mherran Date: Thu, 21 Dec 2023 13:40:31 +0100 Subject: [PATCH 1/3] feat: put geofeed as a link to meet RFC draft-ietf-regext-rdap-geofeed-01 --- .../db/whois/api/rdap/RdapConformance.java | 2 +- .../db/whois/api/rdap/RdapObjectMapper.java | 13 ++- .../net/ripe/db/whois/api/rdap/domain/Ip.java | 16 +--- .../api/rdap/RdapServiceTestIntegration.java | 96 +++++++++++++++---- 4 files changed, 87 insertions(+), 40 deletions(-) diff --git a/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapConformance.java b/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapConformance.java index 797d1f1ce4..a0bc012db3 100644 --- a/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapConformance.java +++ b/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapConformance.java @@ -6,7 +6,7 @@ public enum RdapConformance { NRO_PROFILE_0("nro_rdap_profile_0"), FLAT_MODEL("nro_rdap_profile_asn_flat_0"), REDACTED("redacted"), - GEO_FEED_V1("geofeedv1"); + GEO_FEED_1("geofeed1"); private final String value; diff --git a/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapObjectMapper.java b/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapObjectMapper.java index ebd6696f5b..f4cee497a7 100644 --- a/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapObjectMapper.java +++ b/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapObjectMapper.java @@ -72,7 +72,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static net.ripe.db.whois.api.rdap.RdapConformance.GEO_FEED_V1; +import static net.ripe.db.whois.api.rdap.RdapConformance.GEO_FEED_1; import static net.ripe.db.whois.api.rdap.RedactionObjectMapper.RDAP_VCARD_REDACTED_ATTRIBUTES; import static net.ripe.db.whois.api.rdap.RedactionObjectMapper.mapRedactions; import static net.ripe.db.whois.api.rdap.domain.Status.ACTIVE; @@ -375,7 +375,7 @@ private Ip createIp(final RpslObject rpslObject, final String requestUrl) { ip.setLang(language); } - setGeoFeed(rpslObject, ip); + setGeoFeed(rpslObject, ip, requestUrl); this.mapContactEntities(ip, rpslObject, requestUrl); return ip; @@ -693,11 +693,11 @@ private static String getAndHandleMultipleAttributes(final RpslObject rpslObject return attributes.get(0).getCleanValue().toString(); } - private static void setGeoFeed(final RpslObject rpslObject, final Ip ip) { - ip.getRdapConformance().add(GEO_FEED_V1.getValue()); + private static void setGeoFeed(final RpslObject rpslObject, final Ip ip, final String requestUrl) { + ip.getRdapConformance().add(GEO_FEED_1.getValue()); if(rpslObject.containsAttribute(GEOFEED)) { - ip.setGeofeedv1_geofeed(rpslObject.getValueForAttribute(GEOFEED).toString()); + ip.getLinks().add(new Link(requestUrl, "geo", rpslObject.getValueForAttribute(GEOFEED).toString(), null, "application/geofeed+csv")); return; } @@ -709,8 +709,7 @@ private static void setGeoFeed(final RpslObject rpslObject, final Ip ip) { LOGGER.warn("Seems like geo feed is not set properly for object {}", rpslObject.getKey()); return; } - - ip.setGeofeedv1_geofeed(geoFeed[1]); + ip.getLinks().add(new Link(requestUrl, "geo", geoFeed[1], null, "application/geofeed+csv")); }); } } diff --git a/whois-api/src/main/java/net/ripe/db/whois/api/rdap/domain/Ip.java b/whois-api/src/main/java/net/ripe/db/whois/api/rdap/domain/Ip.java index ffdfba5bd9..fc7b726cbd 100644 --- a/whois-api/src/main/java/net/ripe/db/whois/api/rdap/domain/Ip.java +++ b/whois-api/src/main/java/net/ripe/db/whois/api/rdap/domain/Ip.java @@ -1,12 +1,12 @@ package net.ripe.db.whois.api.rdap.domain; import com.fasterxml.jackson.annotation.JsonInclude; - import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.XmlType; + import java.io.Serializable; import java.util.List; @@ -20,8 +20,7 @@ "type", "country", "parentHandle", - "cidr0_cidrs", - "geofeedv1_geofeed" + "cidr0_cidrs" }) @XmlRootElement(name = "ip") @JsonInclude(JsonInclude.Include.NON_EMPTY) @@ -45,9 +44,6 @@ public class Ip extends RdapObject implements Serializable { @XmlElement(required = true) protected List cidr0_cidrs; - @XmlElement(required = false) - protected String geofeedv1_geofeed; - public Ip() { super(); super.setObjectClassName("ip network"); @@ -81,14 +77,6 @@ public String getEndAddress() { return endAddress; } - public void setGeofeedv1_geofeed(final String geofeedv1_geofeed) { - this.geofeedv1_geofeed = geofeedv1_geofeed; - } - - public String getGeofeedv1_geofeed() { - return geofeedv1_geofeed; - } - public void setEndAddress(String value) { this.endAddress = value; } diff --git a/whois-api/src/test/java/net/ripe/db/whois/api/rdap/RdapServiceTestIntegration.java b/whois-api/src/test/java/net/ripe/db/whois/api/rdap/RdapServiceTestIntegration.java index f9d84192ea..b3325eee58 100644 --- a/whois-api/src/test/java/net/ripe/db/whois/api/rdap/RdapServiceTestIntegration.java +++ b/whois-api/src/test/java/net/ripe/db/whois/api/rdap/RdapServiceTestIntegration.java @@ -40,6 +40,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import static net.ripe.db.whois.api.rdap.domain.vcard.VCardType.TEXT; import static net.ripe.db.whois.common.rpsl.AttributeType.COUNTRY; @@ -238,7 +239,7 @@ public void lookup_inetnum_range_reserved() { assertThat(ip.getPort43(), is("whois.ripe.net")); assertThat(ip.getRdapConformance(), hasSize(5)); - assertThat(ip.getRdapConformance(), containsInAnyOrder("rdap_level_0", "cidr0", "nro_rdap_profile_0", "redacted", "geofeedv1")); + assertThat(ip.getRdapConformance(), containsInAnyOrder("rdap_level_0", "cidr0", "nro_rdap_profile_0", "redacted", "geofeed1")); final List remarks = ip.getRemarks(); @@ -262,6 +263,30 @@ public void lookup_inetnum_range_reserved() { assertCopyrightLink(ip.getLinks(), "https://rdap.db.ripe.net/ip/192.0.2.0/24"); } + @Test + public void lookup_inetnum_without_geofeed_conformance() { + databaseHelper.addObject("" + + "inetnum: 192.0.2.0 - 192.0.2.255\n" + + "netname: TEST-NET-NAME\n" + + "descr: TEST network\n" + + "country: NL\n" + + "language: en\n" + + "tech-c: TP1-TEST\n" + + "status: OTHER\n" + + "mnt-by: OWNER-MNT\n" + + "created: 2022-08-14T11:48:28Z\n" + + "last-modified: 2022-10-25T12:22:39Z\n" + + "source: TEST"); + ipTreeUpdater.rebuild(); + + final Ip ip = createResource("ip/192.0.2.0/24") + .request(MediaType.APPLICATION_JSON_TYPE) + .get(Ip.class); + + assertThat(ip.getHandle(), is("192.0.2.0 - 192.0.2.255")); + assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_1.getValue())); + } + @Test public void lookup_inetnum_geoFeed_attribute() { databaseHelper.addObject("" + @@ -284,8 +309,8 @@ public void lookup_inetnum_geoFeed_attribute() { .get(Ip.class); assertThat(ip.getHandle(), is("192.0.2.0 - 192.0.2.255")); - assertThat(ip.getGeofeedv1_geofeed(), is("https://test.net/geo/test.csv")); - assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_V1.getValue())); + assertGeoFeedLink(ip.getLinks(), "https://rdap.db.ripe.net/ip/192.0.2.0/24"); + assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_1.getValue())); } @Test @@ -310,8 +335,8 @@ public void lookup_inetnum_geoFeed_descr() { .get(Ip.class); assertThat(ip.getHandle(), is("192.0.2.0 - 192.0.2.255")); - assertThat(ip.getGeofeedv1_geofeed(), is("https://test.net/geo/test.csv")); - assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_V1.getValue())); + assertGeoFeedLink(ip.getLinks(), "https://rdap.db.ripe.net/ip/192.0.2.0/24"); + assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_1.getValue())); } @Test @@ -336,8 +361,8 @@ public void lookup_inetnum_geoFeed_remarks() { .get(Ip.class); assertThat(ip.getHandle(), is("192.0.2.0 - 192.0.2.255")); - assertThat(ip.getGeofeedv1_geofeed(), is("https://test.net/geo/test.csv")); - assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_V1.getValue())); + assertGeoFeedLink(ip.getLinks(), "https://rdap.db.ripe.net/ip/192.0.2.0/24"); + assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_1.getValue())); } @Test @@ -690,7 +715,7 @@ public void lookup_inetnum() { assertThat(ip.getCidr0_cidrs().get(1).getLength(), is(23)); assertThat(ip.getRdapConformance(), containsInAnyOrder("cidr0", "rdap_level_0", "nro_rdap_profile_0", - "redacted", "geofeedv1")); + "redacted", "geofeed1")); var notices = ip.getNotices(); var inaccuracyNotice = notices.get(1); @@ -827,7 +852,7 @@ public void lookup_inet6num_with_prefix_length() { assertThat(ip.getPort43(), is("whois.ripe.net")); assertThat(ip.getRdapConformance(), hasSize(5)); - assertThat(ip.getRdapConformance(), containsInAnyOrder("rdap_level_0", "cidr0", "nro_rdap_profile_0", "redacted", "geofeedv1")); + assertThat(ip.getRdapConformance(), containsInAnyOrder("rdap_level_0", "cidr0", "nro_rdap_profile_0", "redacted", "geofeed1")); final List remarks = ip.getRemarks(); assertThat(remarks, hasSize(1)); @@ -847,6 +872,31 @@ public void lookup_inet6num_with_prefix_length() { assertCopyrightLink(ip.getLinks(), "https://rdap.db.ripe.net/ip/2001:2002:2003::/48"); } + @Test + public void lookup_inet6num_without_geoFeed_conformance() { + databaseHelper.addObject("" + + "inet6num: 2001:2002:2003::/48\n" + + "netname: RIPE-NCC\n" + + "geofeed: https://test.net/geo/test.csv\n" + + "descr: Private Network\n" + + "country: NL\n" + + "language: EN\n" + + "tech-c: TP1-TEST\n" + + "status: ASSIGNED PA\n" + + "mnt-by: OWNER-MNT\n" + + "mnt-lower: OWNER-MNT\n" + + "created: 2022-08-14T11:48:28Z\n" + + "last-modified: 2022-10-25T12:22:39Z\n" + + "source: TEST"); + ipTreeUpdater.rebuild(); + + final Ip ip = createResource("ip/2001:2002:2003::/48") + .request(MediaType.APPLICATION_JSON_TYPE) + .get(Ip.class); + + assertThat(ip.getHandle(), is("2001:2002:2003::/48")); + assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_1.getValue())); + } @Test public void lookup_inet6num_geoFeed_attribute() { databaseHelper.addObject("" + @@ -870,8 +920,8 @@ public void lookup_inet6num_geoFeed_attribute() { .get(Ip.class); assertThat(ip.getHandle(), is("2001:2002:2003::/48")); - assertThat(ip.getGeofeedv1_geofeed(), is("https://test.net/geo/test.csv")); - assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_V1.getValue())); + assertGeoFeedLink(ip.getLinks(), "https://rdap.db.ripe.net/ip/2001:2002:2003::/48"); + assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_1.getValue())); } @Test @@ -897,8 +947,8 @@ public void lookup_inet6num_geoFeed_remarks() { .get(Ip.class); assertThat(ip.getHandle(), is("2001:2002:2003::/48")); - assertThat(ip.getGeofeedv1_geofeed(), is("https://test.net/geo/test.csv")); - assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_V1.getValue())); + assertGeoFeedLink(ip.getLinks(), "https://rdap.db.ripe.net/ip/2001:2002:2003::/48"); + assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_1.getValue())); } @Test @@ -924,8 +974,8 @@ public void lookup_inet6num_geoFeed_remarks_case_insensitive() { .get(Ip.class); assertThat(ip.getHandle(), is("2001:2002:2003::/48")); - assertThat(ip.getGeofeedv1_geofeed(), is("https://test.net/geo/test.csv")); - assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_V1.getValue())); + assertGeoFeedLink(ip.getLinks(), "https://rdap.db.ripe.net/ip/2001:2002:2003::/48"); + assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_1.getValue())); } @Test @@ -951,8 +1001,8 @@ public void lookup_inet6num_geoFeed_descr() { .get(Ip.class); assertThat(ip.getHandle(), is("2001:2002:2003::/48")); - assertThat(ip.getGeofeedv1_geofeed(), is("https://test.net/geo/test.csv")); - assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_V1.getValue())); + assertGeoFeedLink(ip.getLinks(), "https://rdap.db.ripe.net/ip/2001:2002:2003::/48"); + assertThat(ip.getRdapConformance(), hasItem(RdapConformance.GEO_FEED_1.getValue())); } @Test @@ -3115,7 +3165,7 @@ public void get_help_response() { assertThat(help.getPort43(), is("whois.ripe.net")); assertThat(help.getRdapConformance(), hasSize(6)); assertThat(help.getRdapConformance(), containsInAnyOrder("cidr0", "rdap_level_0", "nro_rdap_profile_0", - "nro_rdap_profile_asn_flat_0", "redacted", "geofeedv1")); + "nro_rdap_profile_asn_flat_0", "redacted", "geofeed1")); final List notices = help.getNotices(); assertThat(notices, hasSize(1)); @@ -3130,6 +3180,16 @@ private void assertCommon(RdapObject object) { assertThat(object.getRdapConformance(), containsInAnyOrder("rdap_level_0", "cidr0", "nro_rdap_profile_0", "redacted")); } + private void assertGeoFeedLink(final List links, final String value) { + assertThat(links, hasSize(3)); + + final Optional geoFeedLink = links.stream().filter(link -> link.getRel().equals("geo")).findFirst(); + assertThat(geoFeedLink.isPresent(), is(true)); + assertThat(geoFeedLink.get().getValue(), is(value)); + assertThat(geoFeedLink.get().getHref(), is("https://test.net/geo/test.csv")); + assertThat(geoFeedLink.get().getType(), is("application/geofeed+csv")); + } + private void assertCopyrightLink(final List links, final String value) { assertThat(links, hasSize(2)); Collections.sort(links); From 3f3cf6d2e05843451d5d50fa5b98ca51750d87ac Mon Sep 17 00:00:00 2001 From: mherran Date: Thu, 21 Dec 2023 15:13:29 +0100 Subject: [PATCH 2/3] feat: use better name for new tests cases --- .../ripe/db/whois/api/rdap/RdapServiceTestIntegration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/whois-api/src/test/java/net/ripe/db/whois/api/rdap/RdapServiceTestIntegration.java b/whois-api/src/test/java/net/ripe/db/whois/api/rdap/RdapServiceTestIntegration.java index b3325eee58..b727a39703 100644 --- a/whois-api/src/test/java/net/ripe/db/whois/api/rdap/RdapServiceTestIntegration.java +++ b/whois-api/src/test/java/net/ripe/db/whois/api/rdap/RdapServiceTestIntegration.java @@ -264,7 +264,7 @@ public void lookup_inetnum_range_reserved() { } @Test - public void lookup_inetnum_without_geofeed_conformance() { + public void lookup_inetnum_without_geofeed_then_conformance() { databaseHelper.addObject("" + "inetnum: 192.0.2.0 - 192.0.2.255\n" + "netname: TEST-NET-NAME\n" + @@ -873,7 +873,7 @@ public void lookup_inet6num_with_prefix_length() { } @Test - public void lookup_inet6num_without_geoFeed_conformance() { + public void lookup_inet6num_without_geoFeed_then_conformance() { databaseHelper.addObject("" + "inet6num: 2001:2002:2003::/48\n" + "netname: RIPE-NCC\n" + From d071d2ac2e50895e99291b56dc5e43b5816b4989 Mon Sep 17 00:00:00 2001 From: mherran Date: Fri, 22 Dec 2023 13:36:31 +0100 Subject: [PATCH 3/3] feat: put the content type as static field --- .../java/net/ripe/db/whois/api/rdap/RdapObjectMapper.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapObjectMapper.java b/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapObjectMapper.java index f4cee497a7..29ada73141 100644 --- a/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapObjectMapper.java +++ b/whois-api/src/main/java/net/ripe/db/whois/api/rdap/RdapObjectMapper.java @@ -108,6 +108,8 @@ class RdapObjectMapper { private static final String TERMS_AND_CONDITIONS = "http://www.ripe.net/data-tools/support/documentation/terms"; + + private static final String GEOFEED_CONTENT_TYPE = "application/geofeed+csv"; private static final Link COPYRIGHT_LINK = new Link(TERMS_AND_CONDITIONS, "copyright", TERMS_AND_CONDITIONS, null, null); private static final Logger LOGGER = LoggerFactory.getLogger(RdapObjectMapper.class); @@ -697,7 +699,7 @@ private static void setGeoFeed(final RpslObject rpslObject, final Ip ip, final S ip.getRdapConformance().add(GEO_FEED_1.getValue()); if(rpslObject.containsAttribute(GEOFEED)) { - ip.getLinks().add(new Link(requestUrl, "geo", rpslObject.getValueForAttribute(GEOFEED).toString(), null, "application/geofeed+csv")); + ip.getLinks().add(new Link(requestUrl, "geo", rpslObject.getValueForAttribute(GEOFEED).toString(), null, GEOFEED_CONTENT_TYPE)); return; } @@ -709,7 +711,7 @@ private static void setGeoFeed(final RpslObject rpslObject, final Ip ip, final S LOGGER.warn("Seems like geo feed is not set properly for object {}", rpslObject.getKey()); return; } - ip.getLinks().add(new Link(requestUrl, "geo", geoFeed[1], null, "application/geofeed+csv")); + ip.getLinks().add(new Link(requestUrl, "geo", geoFeed[1], null, GEOFEED_CONTENT_TYPE)); }); } }