mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 07:57:13 +02:00
Add support for RDAP retrieval of all registrars
This CL also fixes a bug. Registrars were returned in an arbitrary order. This caused cursor-based pagination to fail. Now we always sort by registrar name (even for handle searches), and use the registrar name in the cursor, to ensure proper behavior. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=182098187
This commit is contained in:
parent
c416b3892d
commit
e577d2f5e9
2 changed files with 89 additions and 13 deletions
|
@ -41,6 +41,7 @@ import google.registry.request.Parameter;
|
|||
import google.registry.request.auth.Auth;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
|
@ -194,6 +195,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
results =
|
||||
searchByHandle(
|
||||
recordWildcardType(RdapSearchPattern.create(handleParam.get(), false)),
|
||||
cursorType,
|
||||
cursorQueryString,
|
||||
subtype,
|
||||
now);
|
||||
|
@ -244,14 +246,17 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
Optional<String> cursorQueryString,
|
||||
Subtype subtype,
|
||||
DateTime now) {
|
||||
// For wildcard searches, make sure the initial string is long enough, and don't allow suffixes.
|
||||
// Don't allow wildcard suffixes when searching for entities.
|
||||
if (partialStringQuery.getHasWildcard() && (partialStringQuery.getSuffix() != null)) {
|
||||
throw new UnprocessableEntityException(
|
||||
partialStringQuery.getHasWildcard()
|
||||
? "Suffixes not allowed in wildcard entity name searches"
|
||||
: "Suffixes not allowed when searching for deleted entities");
|
||||
}
|
||||
// For wildcards, make sure the initial string is long enough, except in the special case of
|
||||
// searching for all registrars, where we aren't worried about inefficient searches.
|
||||
if (partialStringQuery.getHasWildcard()
|
||||
&& (subtype != Subtype.REGISTRARS)
|
||||
&& (partialStringQuery.getInitialString().length()
|
||||
< RdapSearchPattern.MIN_INITIAL_STRING_LENGTH)) {
|
||||
throw new UnprocessableEntityException(
|
||||
|
@ -267,6 +272,8 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
} else {
|
||||
registrars =
|
||||
Streams.stream(Registrar.loadAllCached())
|
||||
.sorted(
|
||||
Comparator.comparing(Registrar::getRegistrarName, String.CASE_INSENSITIVE_ORDER))
|
||||
.filter(
|
||||
registrar ->
|
||||
partialStringQuery.matches(registrar.getRegistrarName())
|
||||
|
@ -320,6 +327,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
*/
|
||||
private RdapSearchResults searchByHandle(
|
||||
final RdapSearchPattern partialStringQuery,
|
||||
CursorType cursorType,
|
||||
Optional<String> cursorQueryString,
|
||||
Subtype subtype,
|
||||
DateTime now) {
|
||||
|
@ -358,13 +366,34 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
now);
|
||||
// Handle queries with a wildcard (or including deleted), but no suffix. Because the handle
|
||||
// for registrars is the IANA identifier number, don't allow wildcard searches for registrars,
|
||||
// by simply not searching for registrars if a wildcard is present. Fetch an extra contact to
|
||||
// detect result set truncation.
|
||||
// by simply not searching for registrars if a wildcard is present (unless the request is for
|
||||
// all registrars, in which case we know what to do). Fetch an extra contact to detect result
|
||||
// set truncation.
|
||||
} else {
|
||||
ImmutableList<Registrar> registrars =
|
||||
((subtype == Subtype.CONTACTS) || partialStringQuery.getHasWildcard())
|
||||
? ImmutableList.of()
|
||||
: getMatchingRegistrars(partialStringQuery.getInitialString());
|
||||
ImmutableList<Registrar> registrars;
|
||||
if ((subtype == Subtype.REGISTRARS)
|
||||
&& partialStringQuery.getHasWildcard()
|
||||
&& partialStringQuery.getInitialString().isEmpty()) {
|
||||
// Even though we are searching by IANA identifier, we should still sort by name, because
|
||||
// the IANA identifier can by missing, and sorting on that would screw up our cursors.
|
||||
registrars =
|
||||
Streams.stream(Registrar.loadAllCached())
|
||||
.sorted(
|
||||
Comparator.comparing(
|
||||
Registrar::getRegistrarName, String.CASE_INSENSITIVE_ORDER))
|
||||
.filter(
|
||||
registrar ->
|
||||
((cursorType != CursorType.REGISTRAR)
|
||||
|| (registrar.getRegistrarName().compareTo(cursorQueryString.get())
|
||||
> 0))
|
||||
&& shouldBeVisible(registrar))
|
||||
.limit(rdapResultSetMaxSize + 1)
|
||||
.collect(toImmutableList());
|
||||
} else if ((subtype == Subtype.CONTACTS) || partialStringQuery.getHasWildcard()) {
|
||||
registrars = ImmutableList.of();
|
||||
} else {
|
||||
registrars = getMatchingRegistrars(partialStringQuery.getInitialString());
|
||||
}
|
||||
// Get the contact matches and return the results, fetching an additional contact to detect
|
||||
// truncation. If we are including deleted entries, we must fetch more entries, in case some
|
||||
// get excluded due to permissioning. Any cursor present must be a contact cursor, because we
|
||||
|
@ -500,12 +529,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
}
|
||||
jsonOutputList.add(rdapJsonFormatter.makeRdapJsonForRegistrar(
|
||||
registrar, false, fullServletPath, rdapWhoisServer, now, outputDataType));
|
||||
newCursor =
|
||||
Optional.of(
|
||||
REGISTRAR_CURSOR_PREFIX
|
||||
+ ((queryType == QueryType.FULL_NAME)
|
||||
? registrar.getRegistrarName()
|
||||
: registrar.getIanaIdentifier()));
|
||||
newCursor = Optional.of(REGISTRAR_CURSOR_PREFIX + registrar.getRegistrarName());
|
||||
}
|
||||
return RdapSearchResults.create(
|
||||
ImmutableList.copyOf(jsonOutputList),
|
||||
|
|
|
@ -851,6 +851,32 @@ public class RdapEntitySearchActionTest extends RdapSearchActionTestCase {
|
|||
"Entity 9"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchRegistrars_cursorNavigationThroughAll() throws Exception {
|
||||
createManyContactsAndRegistrars(0, 13, registrarTest);
|
||||
action.subtypeParam = Optional.of("registrars");
|
||||
checkCursorNavigation(
|
||||
QueryType.FULL_NAME,
|
||||
"*",
|
||||
ImmutableList.of(
|
||||
"Entity 1",
|
||||
"Entity 10",
|
||||
"Entity 11",
|
||||
"Entity 12",
|
||||
"Entity 13",
|
||||
"Entity 2",
|
||||
"Entity 3",
|
||||
"Entity 4",
|
||||
"Entity 5",
|
||||
"Entity 6",
|
||||
"Entity 7",
|
||||
"Entity 8",
|
||||
"Entity 9",
|
||||
"New Registrar",
|
||||
"The Registrar",
|
||||
"Yes Virginia <script>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchMix_truncated() throws Exception {
|
||||
login("2-RegistrarTest");
|
||||
|
@ -1241,6 +1267,32 @@ public class RdapEntitySearchActionTest extends RdapSearchActionTestCase {
|
|||
verifyErrorMetrics(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleMatchRegistrars_cursorNavigationThroughAll() throws Exception {
|
||||
createManyContactsAndRegistrars(0, 13, registrarTest);
|
||||
action.subtypeParam = Optional.of("registrars");
|
||||
checkCursorNavigation(
|
||||
QueryType.HANDLE,
|
||||
"*",
|
||||
ImmutableList.of(
|
||||
"Entity 1",
|
||||
"Entity 10",
|
||||
"Entity 11",
|
||||
"Entity 12",
|
||||
"Entity 13",
|
||||
"Entity 2",
|
||||
"Entity 3",
|
||||
"Entity 4",
|
||||
"Entity 5",
|
||||
"Entity 6",
|
||||
"Entity 7",
|
||||
"Entity 8",
|
||||
"Entity 9",
|
||||
"New Registrar",
|
||||
"The Registrar",
|
||||
"Yes Virginia <script>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleMatchMix_found_truncated() throws Exception {
|
||||
createManyContactsAndRegistrars(30, 0, registrarTest);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue