Throw a more useful error message on attempted domain restore reports (#145)

* Throw a more useful error message on attempted domain restore reports

Per DomainRestoreRequestFlow's Javadoc, we automatically approve and instantly
enact all domain restore requests, thus we don't use or support restore
reports. This improves the registrar-visible error message to help make this
more clear.
This commit is contained in:
Ben McIlwain 2019-07-02 14:11:37 -04:00 committed by GitHub
parent 3a81ec5480
commit a88b102f07
4 changed files with 72 additions and 3 deletions

View file

@ -209,6 +209,7 @@ public abstract class EppException extends Exception {
/** Specified command is not implemented. */ /** Specified command is not implemented. */
@EppResultCode(Code.UNIMPLEMENTED_COMMAND) @EppResultCode(Code.UNIMPLEMENTED_COMMAND)
public static class UnimplementedCommandException extends EppException { public static class UnimplementedCommandException extends EppException {
public UnimplementedCommandException(InnerCommand command) { public UnimplementedCommandException(InnerCommand command) {
super(String.format( super(String.format(
"No flow found for %s with extension %s", "No flow found for %s with extension %s",
@ -217,6 +218,10 @@ public abstract class EppException extends Exception {
? ((ResourceCommandWrapper) command).getResourceCommand().getClass().getSimpleName() ? ((ResourceCommandWrapper) command).getResourceCommand().getClass().getSimpleName()
: null)); : null));
} }
public UnimplementedCommandException(String message) {
super(message);
}
} }
/** Abstract exception class. Do not throw this directly or catch in tests. */ /** Abstract exception class. Do not throw this directly or catch in tests. */

View file

@ -82,6 +82,9 @@ public class FlowPicker {
/** Marker class for unimplemented flows. */ /** Marker class for unimplemented flows. */
private abstract static class UnimplementedFlow implements Flow {} private abstract static class UnimplementedFlow implements Flow {}
/** Marker class for unimplemented restore flows. */
private abstract static class UnimplementedRestoreFlow implements Flow {}
/** A function type that takes an {@link EppInput} and returns a {@link Flow} class. */ /** A function type that takes an {@link EppInput} and returns a {@link Flow} class. */
private abstract static class FlowProvider { private abstract static class FlowProvider {
/** Get the flow associated with this {@link EppInput} or return null to signal no match. */ /** Get the flow associated with this {@link EppInput} or return null to signal no match. */
@ -160,7 +163,7 @@ public class FlowPicker {
// Restore command with an op of "report" is not currently supported. // Restore command with an op of "report" is not currently supported.
return (rgpUpdateExtension.get().getRestoreCommand().getRestoreOp() == RestoreOp.REQUEST) return (rgpUpdateExtension.get().getRestoreCommand().getRestoreOp() == RestoreOp.REQUEST)
? DomainRestoreRequestFlow.class ? DomainRestoreRequestFlow.class
: UnimplementedFlow.class; : UnimplementedRestoreFlow.class;
}}; }};
/** /**
@ -265,8 +268,11 @@ public class FlowPicker {
Class<? extends Flow> flowClass = flowProvider.get(eppInput); Class<? extends Flow> flowClass = flowProvider.get(eppInput);
if (flowClass == UnimplementedFlow.class) { if (flowClass == UnimplementedFlow.class) {
break; // We found it, but it's marked as not implemented. break; // We found it, but it's marked as not implemented.
} } else if (flowClass == UnimplementedRestoreFlow.class) {
if (flowClass != null) { throw new UnimplementedCommandException(
"Domain restores are approved and enacted instantly, "
+ "therefore domain restore reports are not supported");
} else if (flowClass != null) {
return flowClass; // We found it! return flowClass; // We found it!
} }
} }

View file

@ -632,4 +632,16 @@ public class DomainRestoreRequestFlowTest
TransactionReportField.RESTORED_DOMAINS, TransactionReportField.RESTORED_DOMAINS,
1)); 1));
} }
@Test
public void testFailure_restoreReportsAreNotSupported() {
setEppInput("domain_update_restore_report.xml");
// This exception is referred to by its fully qualified path (rather than being imported) so
// that it is not included in the list of exceptions thrown by DomainRestoreRequestFlow, as this
// test EPP won't trigger the request flow at all.
EppException thrown = assertThrows(
google.registry.flows.EppException.UnimplementedCommandException.class, this::runFlow);
assertThat(thrown).hasMessageThat().contains("domain restore reports are not supported");
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
} }

View file

@ -0,0 +1,46 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0
epp-1.0.xsd">
<command>
<update>
<domain:update
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"
xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0
domain-1.0.xsd">
<domain:name>example.com</domain:name>
<domain:chg/>
</domain:update>
</update>
<extension>
<rgp:update xmlns:rgp="urn:ietf:params:xml:ns:rgp-1.0"
xsi:schemaLocation="urn:ietf:params:xml:ns:rgp-1.0
rgp-1.0.xsd">
<rgp:restore op="report">
<rgp:report>
<rgp:preData>Pre-delete registration data goes here.
Both XML and free text are allowed.</rgp:preData>
<rgp:postData>Post-restore registration data goes here.
Both XML and free text are allowed.</rgp:postData>
<rgp:delTime>2003-07-10T22:00:00.0Z</rgp:delTime>
<rgp:resTime>2003-07-20T22:00:00.0Z</rgp:resTime>
<rgp:resReason>Registrant error.</rgp:resReason>
<rgp:statement>This registrar has not restored the
Registered Name in order to assume the rights to use
or sell the Registered Name for itself or for any
third party.</rgp:statement>
<rgp:statement>The information in this report is
true to best of this registrar's knowledge, and this
registrar acknowledges that intentionally supplying
false information in this report shall constitute an
incurable material breach of the
Registry-Registrar Agreement.</rgp:statement>
<rgp:other>Supporting information goes
here.</rgp:other>
</rgp:report>
</rgp:restore>
</rgp:update>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>