Update create logic to ignore signed marks unless in sunrise

This addresses an issue where the existing logic assumed that the presence of a
signed mark means the current flow is a sunrise/sunrush request, when this isn't
necessarily true. It's safe to ignore signed marks in other circumstances.

This is a combination of work by Justin Graham <justin.af.graham@gmail.com>,
Nick Felt, and me (Ben). It is based on the original PR located at:
https://github.com/google/nomulus/pull/41

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=140784461
This commit is contained in:
mcilwain 2016-12-01 15:14:55 -08:00 committed by Ben McIlwain
parent 59f4984083
commit 3740171bbf
7 changed files with 79 additions and 43 deletions

View file

@ -27,3 +27,4 @@ Lai Jiang <jianglai@google.com>
Jordyn Buchanan <jordyn@google.com> Jordyn Buchanan <jordyn@google.com>
Wolfgang Meyers <wolfgang@donuts.co> Wolfgang Meyers <wolfgang@donuts.co>
Hans Ridder <hans.ridder@gmail.com> Hans Ridder <hans.ridder@gmail.com>
Justin Graham <justin.af.graham@gmail.com>

View file

@ -610,7 +610,6 @@ An EPP flow that creates a new domain resource.
* 2002 * 2002
* Service extension(s) must be declared at login. * Service extension(s) must be declared at login.
* Signed marks are not accepted in the current registry phase.
* The current registry phase does not allow for general registrations. * The current registry phase does not allow for general registrations.
* 2003 * 2003
* Fees must be explicitly acknowledged when performing any operations on a * Fees must be explicitly acknowledged when performing any operations on a

View file

@ -106,7 +106,6 @@ import org.joda.time.DateTime;
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException} * @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
* @error {@link google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException} * @error {@link google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException}
* @error {@link google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException} * @error {@link google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link DomainCreateFlow.SignedMarksNotAcceptedInCurrentPhaseException}
* @error {@link DomainFlowUtils.AcceptedTooLongAgoException} * @error {@link DomainFlowUtils.AcceptedTooLongAgoException}
* @error {@link DomainFlowUtils.BadDomainNameCharacterException} * @error {@link DomainFlowUtils.BadDomainNameCharacterException}
* @error {@link DomainFlowUtils.BadDomainNamePartsCountException} * @error {@link DomainFlowUtils.BadDomainNamePartsCountException}
@ -154,7 +153,7 @@ import org.joda.time.DateTime;
public class DomainCreateFlow implements TransactionalFlow { public class DomainCreateFlow implements TransactionalFlow {
private static final Set<TldState> QLP_SMD_ALLOWED_STATES = private static final Set<TldState> SUNRISE_STATES =
Sets.immutableEnumSet(TldState.SUNRISE, TldState.SUNRUSH); Sets.immutableEnumSet(TldState.SUNRISE, TldState.SUNRUSH);
@Inject ExtensionManager extensionManager; @Inject ExtensionManager extensionManager;
@ -202,9 +201,7 @@ public class DomainCreateFlow implements TransactionalFlow {
verifyNoCodeMarks(launchCreate); verifyNoCodeMarks(launchCreate);
validateLaunchCreateNotice(launchCreate.getNotice(), domainLabel, isSuperuser, now); validateLaunchCreateNotice(launchCreate.getNotice(), domainLabel, isSuperuser, now);
} }
if (hasSignedMarks) { boolean isSunriseCreate = hasSignedMarks && SUNRISE_STATES.contains(tldState);
verifySignedMarksAllowed(tldState, isAnchorTenant);
}
customLogic.afterValidation( customLogic.afterValidation(
DomainCreateFlowCustomLogic.AfterValidationParameters.newBuilder() DomainCreateFlowCustomLogic.AfterValidationParameters.newBuilder()
.setDomainName(domainName) .setDomainName(domainName)
@ -226,7 +223,7 @@ public class DomainCreateFlow implements TransactionalFlow {
verifyLaunchPhaseMatchesRegistryPhase(registry, launchCreate, now); verifyLaunchPhaseMatchesRegistryPhase(registry, launchCreate, now);
} }
if (!isAnchorTenant) { if (!isAnchorTenant) {
verifyNotReserved(domainName, hasSignedMarks); verifyNotReserved(domainName, isSunriseCreate);
} }
if (hasClaimsNotice) { if (hasClaimsNotice) {
verifyClaimsPeriodNotEnded(registry, now); verifyClaimsPeriodNotEnded(registry, now);
@ -293,7 +290,7 @@ public class DomainCreateFlow implements TransactionalFlow {
entitiesToSave.add( entitiesToSave.add(
prepareMarkedLrpTokenEntity(authInfo.getPw().getValue(), domainName, historyEntry)); prepareMarkedLrpTokenEntity(authInfo.getPw().getValue(), domainName, historyEntry));
} }
enqueueTasks(hasSignedMarks, hasClaimsNotice, newDomain); enqueueTasks(isSunriseCreate, hasClaimsNotice, newDomain);
EntityChanges entityChanges = EntityChanges entityChanges =
customLogic.beforeSave( customLogic.beforeSave(
@ -324,14 +321,6 @@ public class DomainCreateFlow implements TransactionalFlow {
|| (metadataExtension != null && metadataExtension.getIsAnchorTenant()); || (metadataExtension != null && metadataExtension.getIsAnchorTenant());
} }
/** Only QLP domains can have a signed mark on a domain create, and only in sunrise or sunrush. */
private void verifySignedMarksAllowed(TldState tldState, boolean isAnchorTenant)
throws SignedMarksNotAcceptedInCurrentPhaseException {
if (!isAnchorTenant || !QLP_SMD_ALLOWED_STATES.contains(tldState)) {
throw new SignedMarksNotAcceptedInCurrentPhaseException();
}
}
/** Prohibit creating a domain if there is an open application for the same name. */ /** Prohibit creating a domain if there is an open application for the same name. */
private void verifyNoOpenApplications(DateTime now) throws DomainHasOpenApplicationsException { private void verifyNoOpenApplications(DateTime now) throws DomainHasOpenApplicationsException {
for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) { for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) {
@ -425,11 +414,11 @@ public class DomainCreateFlow implements TransactionalFlow {
} }
private void enqueueTasks( private void enqueueTasks(
boolean hasSignedMarks, boolean hasClaimsNotice, DomainResource newDomain) { boolean isSunriseCreate, boolean hasClaimsNotice, DomainResource newDomain) {
if (newDomain.shouldPublishToDns()) { if (newDomain.shouldPublishToDns()) {
DnsQueue.create().addDomainRefreshTask(newDomain.getFullyQualifiedDomainName()); DnsQueue.create().addDomainRefreshTask(newDomain.getFullyQualifiedDomainName());
} }
if (hasClaimsNotice || hasSignedMarks) { if (hasClaimsNotice || isSunriseCreate) {
LordnTask.enqueueDomainResourceTask(newDomain); LordnTask.enqueueDomainResourceTask(newDomain);
} }
} }
@ -448,13 +437,6 @@ public class DomainCreateFlow implements TransactionalFlow {
} }
} }
/** Signed marks are not accepted in the current registry phase. */
static class SignedMarksNotAcceptedInCurrentPhaseException extends CommandUseErrorException {
public SignedMarksNotAcceptedInCurrentPhaseException() {
super("Signed marks are not accepted in the current registry phase");
}
}
/** The current registry phase does not allow for general registrations. */ /** The current registry phase does not allow for general registrations. */
static class NoGeneralRegistrationsInCurrentPhaseException extends CommandUseErrorException { static class NoGeneralRegistrationsInCurrentPhaseException extends CommandUseErrorException {
public NoGeneralRegistrationsInCurrentPhaseException() { public NoGeneralRegistrationsInCurrentPhaseException() {

View file

@ -366,18 +366,18 @@ public class DomainFlowUtils {
} }
} }
static void verifyNotReserved( static void verifyNotReserved(InternetDomainName domainName, boolean isSunrise)
InternetDomainName domainName, boolean isSunriseApplication) throws EppException { throws EppException {
if (isReserved(domainName, isSunriseApplication)) { if (isReserved(domainName, isSunrise)) {
throw new DomainReservedException(domainName.toString()); throw new DomainReservedException(domainName.toString());
} }
} }
private static boolean isReserved(InternetDomainName domainName, boolean inSunrise) { private static boolean isReserved(InternetDomainName domainName, boolean isSunrise) {
ReservationType type = getReservationType(domainName); ReservationType type = getReservationType(domainName);
return type == ReservationType.FULLY_BLOCKED return type == ReservationType.FULLY_BLOCKED
|| type == ReservationType.RESERVED_FOR_ANCHOR_TENANT || type == ReservationType.RESERVED_FOR_ANCHOR_TENANT
|| (TYPES_ALLOWED_FOR_CREATE_ONLY_IN_SUNRISE.contains(type) && !inSunrise); || (TYPES_ALLOWED_FOR_CREATE_ONLY_IN_SUNRISE.contains(type) && !isSunrise);
} }
/** Returns an enum that encodes how and when this name is reserved in the current tld. */ /** Returns an enum that encodes how and when this name is reserved in the current tld. */

View file

@ -58,7 +58,6 @@ import google.registry.flows.ExtensionManager.UndeclaredServiceExtensionExceptio
import google.registry.flows.ResourceFlowTestCase; import google.registry.flows.ResourceFlowTestCase;
import google.registry.flows.domain.DomainCreateFlow.DomainHasOpenApplicationsException; import google.registry.flows.domain.DomainCreateFlow.DomainHasOpenApplicationsException;
import google.registry.flows.domain.DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException; import google.registry.flows.domain.DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException;
import google.registry.flows.domain.DomainCreateFlow.SignedMarksNotAcceptedInCurrentPhaseException;
import google.registry.flows.domain.DomainFlowUtils.AcceptedTooLongAgoException; import google.registry.flows.domain.DomainFlowUtils.AcceptedTooLongAgoException;
import google.registry.flows.domain.DomainFlowUtils.BadDomainNameCharacterException; import google.registry.flows.domain.DomainFlowUtils.BadDomainNameCharacterException;
import google.registry.flows.domain.DomainFlowUtils.BadDomainNamePartsCountException; import google.registry.flows.domain.DomainFlowUtils.BadDomainNamePartsCountException;
@ -123,6 +122,7 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.DatastoreHelper; import google.registry.testing.DatastoreHelper;
import google.registry.testing.TaskQueueHelper.TaskMatcher; import google.registry.testing.TaskQueueHelper.TaskMatcher;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import org.joda.money.CurrencyUnit; import org.joda.money.CurrencyUnit;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -252,9 +252,14 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
} }
private void assertNoLordn() throws Exception { private void assertNoLordn() throws Exception {
assertNoLordn(null, null);
}
private void assertNoLordn(
@Nullable String smdId, @Nullable LaunchNotice launchNotice) throws Exception {
assertAboutDomains().that(reloadResourceByForeignKey()) assertAboutDomains().that(reloadResourceByForeignKey())
.hasSmdId(null).and() .hasSmdId(smdId).and()
.hasLaunchNotice(null); .hasLaunchNotice(launchNotice);
assertNoTasksEnqueued(QUEUE_CLAIMS, QUEUE_SUNRISE); assertNoTasksEnqueued(QUEUE_CLAIMS, QUEUE_SUNRISE);
} }
@ -411,6 +416,18 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
doSuccessfulTest(); doSuccessfulTest();
} }
@Test
public void testSuccess_generalAvailability_ignoresEncodedSignedMark() throws Exception {
createTld("tld", TldState.GENERAL_AVAILABILITY);
clock.setTo(DateTime.parse("2014-09-09T09:09:09Z"));
setEppInput("domain_create_registration_encoded_signed_mark.xml");
eppRequestSource = EppRequestSource.TOOL; // Only tools can pass in metadata.
persistContactsAndHosts();
runFlow();
assertSuccessfulCreate("tld", true);
assertNoLordn("0000001761376042759136-65535", null);
}
@Test @Test
public void testSuccess_fee_v06() throws Exception { public void testSuccess_fee_v06() throws Exception {
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6")); setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
@ -1210,10 +1227,11 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
} }
@Test @Test
public void testFailure_signedMark() throws Exception { public void testFailure_signedMarkWithoutAnchorTenant() throws Exception {
createTld("tld", TldState.SUNRISE);
setEppInput("domain_create_signed_mark.xml"); setEppInput("domain_create_signed_mark.xml");
persistContactsAndHosts(); persistContactsAndHosts();
thrown.expect(SignedMarksNotAcceptedInCurrentPhaseException.class); thrown.expect(NoGeneralRegistrationsInCurrentPhaseException.class);
runFlow(); runFlow();
} }
@ -1450,7 +1468,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
} }
@Test @Test
public void testSuccess_qlpSunriseRegistrationWithEncodedSignedMark() throws Exception { public void testSuccess_qlpSunriseRegistration_withEncodedSignedMark() throws Exception {
createTld("tld", TldState.SUNRISE); createTld("tld", TldState.SUNRISE);
clock.setTo(DateTime.parse("2014-09-09T09:09:09Z")); clock.setTo(DateTime.parse("2014-09-09T09:09:09Z"));
setEppInput("domain_create_registration_qlp_sunrise_encoded_signed_mark.xml"); setEppInput("domain_create_registration_qlp_sunrise_encoded_signed_mark.xml");
@ -1462,7 +1480,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
} }
@Test @Test
public void testSuccess_qlpSunriseRegistrationWithClaimsNotice() throws Exception { public void testSuccess_qlpSunriseRegistration_withClaimsNotice() throws Exception {
createTld("tld", TldState.SUNRISE); createTld("tld", TldState.SUNRISE);
clock.setTo(DateTime.parse("2009-08-16T09:00:00.0Z")); clock.setTo(DateTime.parse("2009-08-16T09:00:00.0Z"));
setEppInput("domain_create_registration_qlp_sunrise_claims_notice.xml"); setEppInput("domain_create_registration_qlp_sunrise_claims_notice.xml");
@ -1515,7 +1533,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
} }
@Test @Test
public void testSuccess_qlpSunrushRegistrationWithEncodedSignedMark() throws Exception { public void testSuccess_qlpSunrushRegistration_withEncodedSignedMark() throws Exception {
createTld("tld", TldState.SUNRUSH); createTld("tld", TldState.SUNRUSH);
clock.setTo(DateTime.parse("2014-09-09T09:09:09Z")); clock.setTo(DateTime.parse("2014-09-09T09:09:09Z"));
setEppInput("domain_create_registration_qlp_sunrush_encoded_signed_mark.xml"); setEppInput("domain_create_registration_qlp_sunrush_encoded_signed_mark.xml");
@ -1527,7 +1545,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
} }
@Test @Test
public void testSuccess_qlpSunrushRegistrationWithClaimsNotice() throws Exception { public void testSuccess_qlpSunrushRegistration_withClaimsNotice() throws Exception {
createTld("tld", TldState.SUNRUSH); createTld("tld", TldState.SUNRUSH);
clock.setTo(DateTime.parse("2009-08-16T09:00:00.0Z")); clock.setTo(DateTime.parse("2009-08-16T09:00:00.0Z"));
setEppInput("domain_create_registration_qlp_sunrush_claims_notice.xml"); setEppInput("domain_create_registration_qlp_sunrush_claims_notice.xml");
@ -1567,18 +1585,19 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
} }
@Test @Test
public void testFailure_qlpLandrushRegistrationWithEncodedSignedMark() throws Exception { public void testSuccess_qlpLandrushRegistration_ignoresEncodedSignedMark() throws Exception {
createTld("tld", TldState.LANDRUSH); createTld("tld", TldState.LANDRUSH);
clock.setTo(DateTime.parse("2014-09-09T09:09:09Z")); clock.setTo(DateTime.parse("2014-09-09T09:09:09Z"));
setEppInput("domain_create_registration_qlp_landrush_encoded_signed_mark.xml"); setEppInput("domain_create_registration_qlp_landrush_encoded_signed_mark.xml");
eppRequestSource = EppRequestSource.TOOL; // Only tools can pass in metadata. eppRequestSource = EppRequestSource.TOOL; // Only tools can pass in metadata.
persistContactsAndHosts(); persistContactsAndHosts();
thrown.expect(SignedMarksNotAcceptedInCurrentPhaseException.class);
runFlow(); runFlow();
assertSuccessfulCreate("tld", true);
assertNoLordn("0000001761376042759136-65535", null);
} }
@Test @Test
public void testSuccess_qlpLandrushRegistrationWithClaimsNotice() throws Exception { public void testSuccess_qlpLandrushRegistration_withClaimsNotice() throws Exception {
createTld("tld", TldState.LANDRUSH); createTld("tld", TldState.LANDRUSH);
clock.setTo(DateTime.parse("2009-08-16T09:00:00.0Z")); clock.setTo(DateTime.parse("2009-08-16T09:00:00.0Z"));
setEppInput("domain_create_registration_qlp_landrush_claims_notice.xml"); setEppInput("domain_create_registration_qlp_landrush_claims_notice.xml");

File diff suppressed because one or more lines are too long

View file

@ -21,7 +21,7 @@
<launch:create <launch:create
xmlns:launch="urn:ietf:params:xml:ns:launch-1.0" xmlns:launch="urn:ietf:params:xml:ns:launch-1.0"
type="registration"> type="registration">
<launch:phase>claims</launch:phase> <launch:phase>sunrise</launch:phase>
<smd:signedMark xmlns:smd="urn:ietf:params:xml:ns:signedMark-1.0" id="signedMark"> <smd:signedMark xmlns:smd="urn:ietf:params:xml:ns:signedMark-1.0" id="signedMark">
<smd:id>1-2</smd:id> <smd:id>1-2</smd:id>
<smd:issuerInfo issuerID="2"> <smd:issuerInfo issuerID="2">