mirror of
https://github.com/google/nomulus.git
synced 2025-04-30 03:57:51 +02:00
Don't allow non-active registrars to create domains or applications
Specifically, this prevents suspended registrars from creating domains or applications. Pending registrars already can't perform these actions because they get an error message when attempting to log in. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=170481338
This commit is contained in:
parent
d09bd89629
commit
1c4e79f99e
14 changed files with 89 additions and 21 deletions
|
@ -314,6 +314,7 @@ An EPP flow that creates a new application for a domain resource.
|
|||
* Specified extension is not implemented.
|
||||
* 2201
|
||||
* Registrar is not authorized to access this TLD.
|
||||
* Registrar must be active in order to create domains or applications.
|
||||
* 2202
|
||||
* Invalid limited registration period token.
|
||||
* 2302
|
||||
|
@ -546,6 +547,7 @@ An EPP flow that creates a new domain resource.
|
|||
* 2201
|
||||
* Only a tool can pass a metadata extension.
|
||||
* Registrar is not authorized to access this TLD.
|
||||
* Registrar must be active in order to create domains or applications.
|
||||
* 2202
|
||||
* Invalid limited registration period token.
|
||||
* 2302
|
||||
|
|
|
@ -123,7 +123,7 @@ public final class SyncGroupMembersAction implements Runnable {
|
|||
@Override
|
||||
public boolean apply(Registrar registrar) {
|
||||
// Only grab active registrars that require syncing and are of the correct type.
|
||||
return registrar.isActive()
|
||||
return registrar.isLive()
|
||||
&& registrar.getContactsRequireSyncing()
|
||||
&& registrar.getType() == Registrar.Type.REAL;
|
||||
}})
|
||||
|
|
|
@ -35,6 +35,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyLaunchPhaseMatc
|
|||
import static google.registry.flows.domain.DomainFlowUtils.verifyNoCodeMarks;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistryStateAllowsLaunchFlows;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
||||
import static google.registry.model.EppResourceUtils.createDomainRepoId;
|
||||
|
@ -147,6 +148,7 @@ import org.joda.time.DateTime;
|
|||
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
||||
* @error {@link DomainFlowUtils.PremiumNameBlockedException}
|
||||
* @error {@link DomainFlowUtils.RegistrantNotAllowedException}
|
||||
* @error {@link DomainFlowUtils.RegistrarMustBeActiveToCreateDomainsException}
|
||||
* @error {@link DomainFlowTmchUtils.SignedMarksMustBeEncodedException}
|
||||
* @error {@link DomainFlowTmchUtils.SignedMarkCertificateExpiredException}
|
||||
* @error {@link DomainFlowTmchUtils.SignedMarkCertificateInvalidException}
|
||||
|
@ -194,6 +196,7 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
|
|||
customLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
verifyRegistrarIsActive(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
||||
// Fail if the domain is already registered (e.g. this is a landrush application but the domain
|
||||
|
|
|
@ -35,6 +35,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyLaunchPhaseMatc
|
|||
import static google.registry.flows.domain.DomainFlowUtils.verifyNoCodeMarks;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
||||
import static google.registry.model.EppResourceUtils.createDomainRepoId;
|
||||
import static google.registry.model.eppcommon.StatusValue.SERVER_TRANSFER_PROHIBITED;
|
||||
|
@ -155,6 +156,7 @@ import org.joda.time.Duration;
|
|||
* @error {@link NameserversNotSpecifiedForTldWithNameserverWhitelistException}
|
||||
* @error {@link DomainFlowUtils.PremiumNameBlockedException}
|
||||
* @error {@link DomainFlowUtils.RegistrantNotAllowedException}
|
||||
* @error {@link DomainFlowUtils.RegistrarMustBeActiveToCreateDomainsException}
|
||||
* @error {@link DomainFlowUtils.TldDoesNotExistException}
|
||||
* @error {@link DomainFlowUtils.TooManyDsRecordsException}
|
||||
* @error {@link DomainFlowUtils.TooManyNameserversException}
|
||||
|
@ -196,6 +198,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
|||
customLogic.beforeValidation();
|
||||
extensionManager.validate();
|
||||
validateClientIsLoggedIn(clientId);
|
||||
verifyRegistrarIsActive(clientId);
|
||||
DateTime now = ofy().getTransactionTime();
|
||||
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
||||
Period period = command.getPeriod();
|
||||
|
|
|
@ -102,6 +102,7 @@ import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
|||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.Registry.TldState;
|
||||
import google.registry.model.registry.label.ReservationType;
|
||||
|
@ -753,6 +754,19 @@ public class DomainFlowUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the registrar with the given client ID is active.
|
||||
*
|
||||
* <p>Non-active registrars are not allowed to create domain applications or domain resources.
|
||||
*/
|
||||
static void verifyRegistrarIsActive(String clientId)
|
||||
throws RegistrarMustBeActiveToCreateDomainsException {
|
||||
Registrar registrar = Registrar.loadByClientIdCached(clientId).get();
|
||||
if (registrar.getState() != State.ACTIVE) {
|
||||
throw new RegistrarMustBeActiveToCreateDomainsException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Check that the registry phase is not incompatible with launch extension flows. */
|
||||
static void verifyRegistryStateAllowsLaunchFlows(Registry registry, DateTime now)
|
||||
throws BadCommandForRegistryPhaseException {
|
||||
|
@ -1426,4 +1440,12 @@ public class DomainFlowUtils {
|
|||
MAX_REGISTRATION_YEARS));
|
||||
}
|
||||
}
|
||||
|
||||
/** Registrar must be active in order to create domains or applications. */
|
||||
static class RegistrarMustBeActiveToCreateDomainsException extends AuthorizationErrorException {
|
||||
public RegistrarMustBeActiveToCreateDomainsException() {
|
||||
super("Registrar must be active in order to create domains or applications");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -145,10 +145,8 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
|||
|
||||
/** Represents the state of a persisted registrar entity. */
|
||||
public enum State {
|
||||
/**
|
||||
* This registrar is provisioned and may have access to the testing environment, but is not yet
|
||||
* allowed to access the production environment.
|
||||
*/
|
||||
|
||||
/** This registrar is provisioned but not yet active, and cannot log in. */
|
||||
PENDING,
|
||||
|
||||
/** This is an active registrar account which is allowed to provision and modify domains. */
|
||||
|
@ -177,8 +175,8 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
|||
/** Regex for telephone support passcode (5 digit string). */
|
||||
public static final Pattern PHONE_PASSCODE_PATTERN = Pattern.compile("\\d{5}");
|
||||
|
||||
/** The states in which a {@link Registrar} is considered {@link #isActive active}. */
|
||||
private static final ImmutableSet<State> ACTIVE_STATES =
|
||||
/** The states in which a {@link Registrar} is considered {@link #isLive live}. */
|
||||
private static final ImmutableSet<State> LIVE_STATES =
|
||||
Sets.immutableEnumSet(State.ACTIVE, State.SUSPENDED);
|
||||
|
||||
/**
|
||||
|
@ -486,14 +484,19 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
|||
return nullToEmptyImmutableSortedCopy(allowedTlds);
|
||||
}
|
||||
|
||||
/** Returns {@code true} if registrar is active. */
|
||||
public boolean isActive() {
|
||||
return ACTIVE_STATES.contains(state);
|
||||
/**
|
||||
* Returns {@code true} if the registrar is live.
|
||||
*
|
||||
* <p>A live registrar is one that can have live domains/contacts/hosts in the registry, meaning
|
||||
* that it is either currently active or used to be active (i.e. suspended).
|
||||
*/
|
||||
public boolean isLive() {
|
||||
return LIVE_STATES.contains(state);
|
||||
}
|
||||
|
||||
/** Returns {@code true} if registrar should be visible in WHOIS results. */
|
||||
public boolean isActiveAndPubliclyVisible() {
|
||||
return ACTIVE_STATES.contains(state) && PUBLICLY_VISIBLE_TYPES.contains(type);
|
||||
public boolean isLiveAndPubliclyVisible() {
|
||||
return LIVE_STATES.contains(state) && PUBLICLY_VISIBLE_TYPES.contains(type);
|
||||
}
|
||||
|
||||
public String getClientCertificate() {
|
||||
|
|
|
@ -239,7 +239,7 @@ public abstract class RdapActionBase implements Runnable {
|
|||
* 2. The request did not specify a registrar to filter on, or the registrar matches.
|
||||
*/
|
||||
boolean shouldBeVisible(Registrar registrar) {
|
||||
return (registrar.isActiveAndPubliclyVisible()
|
||||
return (registrar.isLiveAndPubliclyVisible()
|
||||
|| (shouldIncludeDeleted()
|
||||
&& getAuthorization().isAuthorizedForClientId(registrar.getClientId())))
|
||||
&& (!registrarParam.isPresent() || registrarParam.get().equals(registrar.getClientId()));
|
||||
|
|
|
@ -101,7 +101,7 @@ public class RdapEntityAction extends RdapActionBase {
|
|||
if (ianaIdentifier != null) {
|
||||
wasValidKey = true;
|
||||
Optional<Registrar> registrar = getRegistrarByIanaIdentifier(ianaIdentifier);
|
||||
if ((registrar.isPresent()) && registrar.get().isActiveAndPubliclyVisible()) {
|
||||
if ((registrar.isPresent()) && registrar.get().isLiveAndPubliclyVisible()) {
|
||||
return rdapJsonFormatter.makeRdapJsonForRegistrar(
|
||||
registrar.get(), true, rdapLinkBase, rdapWhoisServer, now, OutputDataType.FULL);
|
||||
}
|
||||
|
|
|
@ -243,7 +243,7 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
|||
} else {
|
||||
outputDataType = OutputDataType.FULL;
|
||||
for (Registrar registrar : registrars) {
|
||||
if (registrar.isActiveAndPubliclyVisible()) {
|
||||
if (registrar.isLiveAndPubliclyVisible()) {
|
||||
numEntities++;
|
||||
if (numEntities > 1) {
|
||||
outputDataType = OutputDataType.SUMMARY;
|
||||
|
@ -276,7 +276,7 @@ public class RdapEntitySearchAction extends RdapActionBase {
|
|||
authorization));
|
||||
}
|
||||
for (Registrar registrar : registrars) {
|
||||
if (registrar.isActiveAndPubliclyVisible()) {
|
||||
if (registrar.isLiveAndPubliclyVisible()) {
|
||||
if (jsonOutputList.size() >= rdapResultSetMaxSize) {
|
||||
return RdapSearchResults.create(
|
||||
ImmutableList.copyOf(jsonOutputList), IncompletenessWarningType.TRUNCATED);
|
||||
|
|
|
@ -768,7 +768,7 @@ public class RdapJsonFormatter {
|
|||
ImmutableMap.Builder<String, Object> jsonBuilder = new ImmutableMap.Builder<>();
|
||||
jsonBuilder.put("objectClassName", "entity");
|
||||
jsonBuilder.put("handle", registrar.getIanaIdentifier().toString());
|
||||
jsonBuilder.put("status", registrar.isActive() ? STATUS_LIST_ACTIVE : STATUS_LIST_REMOVED);
|
||||
jsonBuilder.put("status", registrar.isLive() ? STATUS_LIST_ACTIVE : STATUS_LIST_REMOVED);
|
||||
jsonBuilder.put("roles", ImmutableList.of(RdapEntityRole.REGISTRAR.rfc7483String));
|
||||
jsonBuilder.put("links",
|
||||
ImmutableList.of(makeLink("entity", registrar.getIanaIdentifier().toString(), linkBase)));
|
||||
|
|
|
@ -109,7 +109,7 @@ final class VerifyOteCommand implements ServerSideCommand {
|
|||
.transform(new Function<Registrar, String>() {
|
||||
@Override
|
||||
public String apply(Registrar registrar) {
|
||||
if (!registrar.isActive()) {
|
||||
if (!registrar.isLive()) {
|
||||
return null;
|
||||
}
|
||||
String name = registrar.getClientId();
|
||||
|
|
|
@ -51,7 +51,7 @@ final class RegistrarLookupCommand implements WhoisCommand {
|
|||
Map<String, Registrar> map = new HashMap<>();
|
||||
// Use the normalized registrar name as a key, and ignore inactive and hidden registrars.
|
||||
for (Registrar registrar : Registrar.loadAllCached()) {
|
||||
if (!registrar.isActiveAndPubliclyVisible() || registrar.getRegistrarName() == null) {
|
||||
if (!registrar.isLiveAndPubliclyVisible() || registrar.getRegistrarName() == null) {
|
||||
continue;
|
||||
}
|
||||
String normalized = normalizeRegistrarName(registrar.getRegistrarName());
|
||||
|
|
|
@ -98,6 +98,7 @@ import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTl
|
|||
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveToCreateDomainsException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
|
||||
|
@ -112,6 +113,8 @@ import google.registry.model.domain.launch.ApplicationStatus;
|
|||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.launch.LaunchPhase;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.Registry.TldState;
|
||||
import google.registry.model.registry.label.ReservedList;
|
||||
|
@ -723,6 +726,22 @@ public class DomainApplicationCreateFlowTest
|
|||
runFlow();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_suspendedRegistrarCantCreateDomainApplication() throws Exception {
|
||||
setEppInput("domain_create_sunrise_encoded_signed_mark.xml");
|
||||
persistContactsAndHosts();
|
||||
clock.advanceOneMilli();
|
||||
persistResource(
|
||||
Registrar.loadByClientId("TheRegistrar")
|
||||
.get()
|
||||
.asBuilder()
|
||||
.setState(State.SUSPENDED)
|
||||
.build());
|
||||
clock.advanceOneMilli();
|
||||
thrown.expect(RegistrarMustBeActiveToCreateDomainsException.class);
|
||||
runFlow();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_sunriseApplicationInLandrush() throws Exception {
|
||||
createTld("tld", TldState.LANDRUSH);
|
||||
|
|
|
@ -104,6 +104,7 @@ import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTl
|
|||
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveToCreateDomainsException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
|
||||
|
@ -125,6 +126,8 @@ import google.registry.model.domain.rgp.GracePeriodStatus;
|
|||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.Registry.TldState;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
|
@ -132,7 +135,6 @@ import google.registry.model.reporting.DomainTransactionRecord;
|
|||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.monitoring.whitebox.EppMetric;
|
||||
import google.registry.testing.DatastoreHelper;
|
||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -1439,6 +1441,20 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
runFlow();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_suspendedRegistrarCantCreateDomain() throws Exception {
|
||||
setEppInput("domain_create.xml");
|
||||
persistContactsAndHosts();
|
||||
persistResource(
|
||||
Registrar.loadByClientId("TheRegistrar")
|
||||
.get()
|
||||
.asBuilder()
|
||||
.setState(State.SUSPENDED)
|
||||
.build());
|
||||
thrown.expect(RegistrarMustBeActiveToCreateDomainsException.class);
|
||||
runFlow();
|
||||
}
|
||||
|
||||
private void doFailingDomainNameTest(
|
||||
String domainName,
|
||||
Class<? extends Throwable> exception) throws Exception {
|
||||
|
@ -1579,7 +1595,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
@Test
|
||||
public void testFailure_notAuthorizedForTld() throws Exception {
|
||||
createTld("irrelevant", "IRR");
|
||||
DatastoreHelper.persistResource(
|
||||
persistResource(
|
||||
loadRegistrar("TheRegistrar")
|
||||
.asBuilder()
|
||||
.setAllowedTlds(ImmutableSet.<String>of("irrelevant"))
|
||||
|
|
Loading…
Add table
Reference in a new issue