Check BSA block status in CheckApi (#2271)

* Check BSA block status in CheckApi

Checks for and reports BSA block status if the name is not registered or
reserved.

Also moves CheckApiActionTest to standardTest. Whatever problem forcing
it to another suite has apparently disappeared.
This commit is contained in:
Weimin Yu 2024-01-09 13:19:07 -05:00 committed by GitHub
parent e56e751652
commit f8ac7afc33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 9 deletions

View file

@ -38,7 +38,6 @@ def jsDir = "${project.projectDir}/src/main/javascript"
def outcastTestPatterns = [
// Problem seems to lie with AppEngine TaskQueue for test.
"google/registry/batch/RefreshDnsOnHostRenameActionTest.*",
"google/registry/flows/CheckApiActionTest.*",
"google/registry/flows/EppLifecycleHostTest.*",
"google/registry/flows/domain/DomainCreateFlowTest.*",
"google/registry/flows/domain/DomainUpdateFlowTest.*",

View file

@ -16,12 +16,14 @@ package google.registry.flows;
import static com.google.common.base.Strings.nullToEmpty;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
import static google.registry.flows.domain.DomainFlowUtils.isBlockedByBsa;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainNameWithIdnTables;
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation;
import static google.registry.model.tld.label.ReservationType.getTypeOfHighestSeverity;
import static google.registry.model.tld.label.ReservedList.getReservationTypes;
import static google.registry.monitoring.whitebox.CheckApiMetric.Availability.AVAILABLE;
import static google.registry.monitoring.whitebox.CheckApiMetric.Availability.BSA_BLOCKED;
import static google.registry.monitoring.whitebox.CheckApiMetric.Availability.REGISTERED;
import static google.registry.monitoring.whitebox.CheckApiMetric.Availability.RESERVED;
import static google.registry.monitoring.whitebox.CheckApiMetric.Status.INVALID_NAME;
@ -30,6 +32,7 @@ import static google.registry.monitoring.whitebox.CheckApiMetric.Status.SUCCESS;
import static google.registry.monitoring.whitebox.CheckApiMetric.Status.UNKNOWN_ERROR;
import static google.registry.monitoring.whitebox.CheckApiMetric.Tier.PREMIUM;
import static google.registry.monitoring.whitebox.CheckApiMetric.Tier.STANDARD;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static org.json.simple.JSONValue.toJSONString;
@ -55,7 +58,6 @@ import google.registry.request.Parameter;
import google.registry.request.RequestParameters;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
@ -79,7 +81,6 @@ public class CheckApiAction implements Runnable {
String domain;
@Inject Response response;
@Inject Clock clock;
@Inject CheckApiMetric.Builder metricBuilder;
@Inject CheckApiMetrics checkApiMetrics;
@ -104,6 +105,20 @@ public class CheckApiAction implements Runnable {
private Map<String, Object> doCheck() {
String domainString;
InternetDomainName domainName;
try {
domainString = canonicalizeHostname(nullToEmpty(domain));
domainName = validateDomainName(domainString);
return tm().transact(() -> checkDomainName(domainName));
} catch (IllegalArgumentException | EppException e) {
metricBuilder.status(INVALID_NAME);
return fail("Must supply a valid domain name on an authoritative TLD");
}
}
private Map<String, Object> checkDomainName(InternetDomainName domainName) {
tm().assertInTransaction();
String domainString;
try {
domainString = canonicalizeHostname(nullToEmpty(domain));
domainName = validateDomainName(domainString);
@ -115,7 +130,7 @@ public class CheckApiAction implements Runnable {
// Throws an EppException with a reasonable error message which will be sent back to caller.
validateDomainNameWithIdnTables(domainName);
DateTime now = clock.nowUtc();
DateTime now = tm().getTransactionTime();
Tld tld = Tld.get(domainName.parent().toString());
try {
verifyNotInPredelegation(tld, now);
@ -126,13 +141,25 @@ public class CheckApiAction implements Runnable {
boolean isRegistered = checkExists(domainString, now);
Optional<String> reservedError = Optional.empty();
boolean isBsaBlocked = false;
boolean isReserved = false;
if (!isRegistered) {
reservedError = checkReserved(domainName);
isReserved = reservedError.isPresent();
}
Availability availability = isRegistered ? REGISTERED : (isReserved ? RESERVED : AVAILABLE);
String errorMsg = isRegistered ? "In use" : (isReserved ? reservedError.get() : null);
if (!isRegistered && !isReserved) {
isBsaBlocked = isBlockedByBsa(domainName.parts().get(0), tld, now);
}
Availability availability =
isRegistered
? REGISTERED
: (isReserved ? RESERVED : (isBsaBlocked ? BSA_BLOCKED : AVAILABLE));
String errorMsg =
isRegistered
? "In use"
: (isReserved
? reservedError.get()
: (isBsaBlocked ? "Blocked by the Brand Safety Alliance" : null));
ImmutableMap.Builder<String, Object> responseBuilder = new ImmutableMap.Builder<>();
metricBuilder.status(SUCCESS).availability(availability);

View file

@ -45,6 +45,7 @@ public abstract class CheckApiMetric {
public enum Availability {
RESERVED("reserved"),
REGISTERED("registered"),
BSA_BLOCKED("blocked"),
AVAILABLE("available");
private final String displayLabel;

View file

@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static google.registry.model.tld.Tld.TldState.PREDELEGATION;
import static google.registry.monitoring.whitebox.CheckApiMetric.Availability.AVAILABLE;
import static google.registry.monitoring.whitebox.CheckApiMetric.Availability.BSA_BLOCKED;
import static google.registry.monitoring.whitebox.CheckApiMetric.Availability.REGISTERED;
import static google.registry.monitoring.whitebox.CheckApiMetric.Availability.RESERVED;
import static google.registry.monitoring.whitebox.CheckApiMetric.Tier.PREMIUM;
@ -26,8 +27,10 @@ import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistReservedList;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.mockito.Mockito.verify;
import google.registry.bsa.persistence.BsaLabelTestingUtils;
import google.registry.model.tld.Tld;
import google.registry.monitoring.whitebox.CheckApiMetric;
import google.registry.monitoring.whitebox.CheckApiMetric.Availability;
@ -38,6 +41,7 @@ import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationT
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import java.util.Map;
import java.util.Optional;
import org.joda.time.DateTime;
import org.json.simple.JSONValue;
import org.junit.jupiter.api.BeforeEach;
@ -54,10 +58,11 @@ import org.mockito.junit.jupiter.MockitoExtension;
class CheckApiActionTest {
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
private final FakeClock fakeClock = new FakeClock(START_TIME);
@RegisterExtension
final JpaIntegrationTestExtension jpa =
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationTestExtension();
@Mock private CheckApiMetrics checkApiMetrics;
@Captor private ArgumentCaptor<CheckApiMetric> metricCaptor;
@ -84,8 +89,6 @@ class CheckApiActionTest {
CheckApiAction action = new CheckApiAction();
action.domain = domain;
action.response = new FakeResponse();
FakeClock fakeClock = new FakeClock(START_TIME);
action.clock = fakeClock;
action.metricBuilder = CheckApiMetric.builder(fakeClock);
action.checkApiMetrics = checkApiMetrics;
fakeClock.advanceOneMilli();
@ -283,6 +286,21 @@ class CheckApiActionTest {
verifySuccessMetric(PREMIUM, RESERVED);
}
@Test
void testSuccess_blockedByBsa() {
BsaLabelTestingUtils.persistBsaLabel("rich", START_OF_TIME);
persistResource(
Tld.get("example").asBuilder().setBsaEnrollStartTime(Optional.of(START_OF_TIME)).build());
assertThat(getCheckResponse("rich.example"))
.containsExactly(
"tier", "premium",
"status", "success",
"available", false,
"reason", "Blocked by the Brand Safety Alliance");
verifySuccessMetric(PREMIUM, BSA_BLOCKED);
}
private void verifySuccessMetric(Tier tier, Availability availability) {
verify(checkApiMetrics).incrementCheckApiRequest(metricCaptor.capture());
CheckApiMetric metric = metricCaptor.getValue();