mirror of
https://github.com/google/nomulus.git
synced 2025-07-22 18:55:58 +02:00
Report BSA block status in DomainCheckFlow (#2288)
- Registered names are not affected. - Reserved names are not affected. - Names that are none of the above and match some BSA labels are reported as blocked.
This commit is contained in:
parent
9273d2bf15
commit
1dcf34ccc2
5 changed files with 98 additions and 6 deletions
|
@ -14,6 +14,9 @@
|
|||
|
||||
package google.registry.bsa.persistence;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.config.RegistryConfig.getEppResourceCachingDuration;
|
||||
import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries;
|
||||
import static google.registry.model.CacheUtils.newCacheBuilder;
|
||||
|
@ -22,10 +25,15 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
|||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.apache.commons.lang3.stream.Streams;
|
||||
|
||||
/** Helpers for {@link BsaLabel}. */
|
||||
public final class BsaLabelUtils {
|
||||
|
@ -43,9 +51,11 @@ public final class BsaLabelUtils {
|
|||
@Override
|
||||
public Map<VKey<BsaLabel>, Optional<BsaLabel>> loadAll(
|
||||
Iterable<? extends VKey<BsaLabel>> keys) {
|
||||
// TODO(b/309173359): need this for DomainCheckFlow
|
||||
throw new UnsupportedOperationException(
|
||||
"LoadAll not supported by the BsaLabel cache loader.");
|
||||
ImmutableMap<VKey<? extends BsaLabel>, BsaLabel> existingLabels =
|
||||
replicaTm().reTransact(() -> replicaTm().loadByKeysIfPresent(keys));
|
||||
return Streams.of(keys)
|
||||
.collect(
|
||||
toImmutableMap(key -> key, key -> Optional.ofNullable(existingLabels.get(key))));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -84,4 +94,15 @@ public final class BsaLabelUtils {
|
|||
public static boolean isLabelBlocked(String domainLabel) {
|
||||
return cacheBsaLabels.get(BsaLabel.vKey(domainLabel)).isPresent();
|
||||
}
|
||||
|
||||
/** Returns the elements in {@code domainLabels} that are blocked by BSA. */
|
||||
public static ImmutableSet<String> getBlockedLabels(ImmutableCollection<String> domainLabels) {
|
||||
ImmutableList<VKey<BsaLabel>> queriedLabels =
|
||||
domainLabels.stream().map(BsaLabel::vKey).collect(toImmutableList());
|
||||
return cacheBsaLabels.getAll(queriedLabels).values().stream()
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.map(BsaLabel::getLabel)
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ public class CheckApiAction implements Runnable {
|
|||
? "In use"
|
||||
: (isReserved
|
||||
? reservedError.get()
|
||||
: (isBsaBlocked ? "Blocked by the Brand Safety Alliance" : null));
|
||||
: (isBsaBlocked ? "Blocked by a GlobalBlock service" : null));
|
||||
|
||||
ImmutableMap.Builder<String, Object> responseBuilder = new ImmutableMap.Builder<>();
|
||||
metricBuilder.status(SUCCESS).availability(availability);
|
||||
|
|
|
@ -18,6 +18,7 @@ import static com.google.common.base.Strings.emptyToNull;
|
|||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.bsa.persistence.BsaLabelUtils.getBlockedLabels;
|
||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||
|
@ -34,6 +35,7 @@ import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
|
|||
import static google.registry.model.tld.label.ReservationType.getTypeOfHighestSeverity;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -83,9 +85,12 @@ import google.registry.model.tld.label.ReservationType;
|
|||
import google.registry.persistence.VKey;
|
||||
import google.registry.pricing.PricingEngineProxy;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
|
@ -177,6 +182,12 @@ public final class DomainCheckFlow implements TransactionalFlow {
|
|||
.build());
|
||||
ImmutableMap<String, VKey<Domain>> existingDomains =
|
||||
ForeignKeyUtils.load(Domain.class, domainNames, now);
|
||||
// Check block labels only when there are unregistered domains, since "In use" goes before
|
||||
// "Blocked by BSA".
|
||||
ImmutableSet<InternetDomainName> bsaBlockedDomainNames =
|
||||
existingDomains.size() == parsedDomains.size()
|
||||
? ImmutableSet.of()
|
||||
: getBsaBlockedDomains(parsedDomains.values());
|
||||
Optional<AllocationTokenExtension> allocationTokenExtension =
|
||||
eppInput.getSingleExtension(AllocationTokenExtension.class);
|
||||
Optional<AllocationTokenDomainCheckResults> tokenDomainCheckResults =
|
||||
|
@ -203,6 +214,7 @@ public final class DomainCheckFlow implements TransactionalFlow {
|
|||
getMessageForCheck(
|
||||
parsedDomains.get(domainName),
|
||||
existingDomains,
|
||||
bsaBlockedDomainNames,
|
||||
domainCheckResults,
|
||||
tldStates,
|
||||
allocationToken);
|
||||
|
@ -234,6 +246,7 @@ public final class DomainCheckFlow implements TransactionalFlow {
|
|||
private Optional<String> getMessageForCheck(
|
||||
InternetDomainName domainName,
|
||||
ImmutableMap<String, VKey<Domain>> existingDomains,
|
||||
ImmutableSet<InternetDomainName> bsaBlockedDomains,
|
||||
ImmutableMap<InternetDomainName, String> tokenCheckResults,
|
||||
ImmutableMap<String, TldState> tldStates,
|
||||
Optional<AllocationToken> allocationToken) {
|
||||
|
@ -251,7 +264,18 @@ public final class DomainCheckFlow implements TransactionalFlow {
|
|||
}
|
||||
}
|
||||
}
|
||||
return Optional.ofNullable(emptyToNull(tokenCheckResults.get(domainName)));
|
||||
Optional<String> tokenResult =
|
||||
Optional.ofNullable(emptyToNull(tokenCheckResults.get(domainName)));
|
||||
if (tokenResult.isPresent()) {
|
||||
return tokenResult;
|
||||
}
|
||||
if (bsaBlockedDomains.contains(domainName)) {
|
||||
// TODO(weiminyu): extract to a constant for here and CheckApiAction.
|
||||
// Excerpt from BSA's custom message. Max len 32 chars by EPP XML schema.
|
||||
return Optional.of("Blocked by a GlobalBlock service");
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle the fee check extension. */
|
||||
|
@ -415,6 +439,21 @@ public final class DomainCheckFlow implements TransactionalFlow {
|
|||
return availabilityCheckDomains;
|
||||
}
|
||||
|
||||
static ImmutableSet<InternetDomainName> getBsaBlockedDomains(
|
||||
ImmutableCollection<InternetDomainName> parsedDomains) {
|
||||
Map<String, ImmutableList<InternetDomainName>> labelToDomainNames =
|
||||
parsedDomains.stream()
|
||||
.collect(
|
||||
Collectors.groupingBy(
|
||||
parsedDomain -> parsedDomain.parts().get(0), toImmutableList()));
|
||||
ImmutableSet<String> blockedLabels =
|
||||
getBlockedLabels(ImmutableList.copyOf(labelToDomainNames.keySet()));
|
||||
labelToDomainNames.keySet().retainAll(blockedLabels);
|
||||
return labelToDomainNames.values().stream()
|
||||
.flatMap(Collection::stream)
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
/** By server policy, fee check names must be listed in the availability check. */
|
||||
static class OnlyCheckedNamesCanBeFeeCheckedException extends ParameterValuePolicyErrorException {
|
||||
OnlyCheckedNamesCanBeFeeCheckedException() {
|
||||
|
|
|
@ -296,7 +296,7 @@ class CheckApiActionTest {
|
|||
"tier", "premium",
|
||||
"status", "success",
|
||||
"available", false,
|
||||
"reason", "Blocked by the Brand Safety Alliance");
|
||||
"reason", "Blocked by a GlobalBlock service");
|
||||
|
||||
verifySuccessMetric(PREMIUM, BSA_BLOCKED);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import com.google.common.collect.ImmutableMap;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Ordering;
|
||||
import google.registry.bsa.persistence.BsaTestingUtils;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.FlowUtils.UnknownCurrencyEppException;
|
||||
|
@ -157,6 +158,37 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
|
|||
create(true, "example3.tld", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_bsaBlocked_otherwiseAvailable_blocked() throws Exception {
|
||||
BsaTestingUtils.persistBsaLabel("example1", clock.nowUtc());
|
||||
doCheckTest(
|
||||
create(false, "example1.tld", "Blocked by a GlobalBlock service"),
|
||||
create(true, "example2.tld", null),
|
||||
create(true, "example3.tld", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_bsaBlocked_alsoRegistered_registered() throws Exception {
|
||||
BsaTestingUtils.persistBsaLabel("example1", clock.nowUtc());
|
||||
persistActiveDomain("example1.tld");
|
||||
doCheckTest(
|
||||
create(false, "example1.tld", "In use"),
|
||||
create(true, "example2.tld", null),
|
||||
create(true, "example3.tld", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_bsaBlocked_alsoReserved_reserved() throws Exception {
|
||||
BsaTestingUtils.persistBsaLabel("reserved", clock.nowUtc());
|
||||
BsaTestingUtils.persistBsaLabel("allowedinsunrise", clock.nowUtc());
|
||||
setEppInput("domain_check_one_tld_reserved.xml");
|
||||
doCheckTest(
|
||||
create(false, "reserved.tld", "Reserved"),
|
||||
create(false, "allowedinsunrise.tld", "Reserved"),
|
||||
create(true, "example2.tld", null),
|
||||
create(true, "example3.tld", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_clTridNotSpecified() throws Exception {
|
||||
setEppInput("domain_check_no_cltrid.xml");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue