mirror of
https://github.com/google/nomulus.git
synced 2025-08-18 07:24:05 +02:00
Add new parameter renew_one_year to URS (#1364)
* Add autorenews to URS (#1343) * Add autorenews to URS * Add autorenews to existing xml files for test cases * Harmonize domain.get() in existing code * Fix typo in test case name * Modify existing test helper method to allow testing with different domain bases
This commit is contained in:
parent
0f4156c563
commit
34ecc6fbe7
2 changed files with 161 additions and 42 deletions
|
@ -36,6 +36,7 @@ import google.registry.model.domain.DomainBase;
|
|||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.tools.soy.DomainRenewSoyInfo;
|
||||
import google.registry.tools.soy.UniformRapidSuspensionSoyInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -43,6 +44,7 @@ import java.util.Optional;
|
|||
import java.util.Set;
|
||||
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
|
||||
/** A command to suspend a domain for the Uniform Rapid Suspension process. */
|
||||
@Parameters(separators = " =",
|
||||
|
@ -97,6 +99,13 @@ final class UniformRapidSuspensionCommand extends MutatingEppToolCommand {
|
|||
description = "Flag indicating that is is an undo command, which removes locks.")
|
||||
private boolean undo;
|
||||
|
||||
@Parameter(
|
||||
names = {"--renew_one_year"},
|
||||
required = true,
|
||||
description = "Flag indicating whether or not the domain will be renewed for a year.",
|
||||
arity = 1)
|
||||
private boolean renewOneYear;
|
||||
|
||||
/** Set of existing locks that need to be preserved during undo, sorted for nicer output. */
|
||||
ImmutableSortedSet<String> existingLocks;
|
||||
|
||||
|
@ -114,19 +123,20 @@ final class UniformRapidSuspensionCommand extends MutatingEppToolCommand {
|
|||
superuser = true;
|
||||
DateTime now = DateTime.now(UTC);
|
||||
ImmutableSet<String> newHostsSet = ImmutableSet.copyOf(newHosts);
|
||||
Optional<DomainBase> domain = loadByForeignKey(DomainBase.class, domainName, now);
|
||||
checkArgumentPresent(domain, "Domain '%s' does not exist or is deleted", domainName);
|
||||
Optional<DomainBase> domainOpt = loadByForeignKey(DomainBase.class, domainName, now);
|
||||
checkArgumentPresent(domainOpt, "Domain '%s' does not exist or is deleted", domainName);
|
||||
DomainBase domain = domainOpt.get();
|
||||
Set<String> missingHosts =
|
||||
difference(newHostsSet, checkResourcesExist(HostResource.class, newHosts, now));
|
||||
checkArgument(missingHosts.isEmpty(), "Hosts do not exist: %s", missingHosts);
|
||||
checkArgument(
|
||||
locksToPreserve.isEmpty() || undo,
|
||||
"Locks can only be preserved when running with --undo");
|
||||
existingNameservers = getExistingNameservers(domain.get());
|
||||
existingLocks = getExistingLocks(domain.get());
|
||||
existingDsData = getExistingDsData(domain.get());
|
||||
existingNameservers = getExistingNameservers(domain);
|
||||
existingLocks = getExistingLocks(domain);
|
||||
existingDsData = getExistingDsData(domain);
|
||||
removeStatuses =
|
||||
(hasClientHold(domain.get()) && !undo)
|
||||
(hasClientHold(domain) && !undo)
|
||||
? ImmutableSet.of(StatusValue.CLIENT_HOLD.getXmlName())
|
||||
: ImmutableSet.of();
|
||||
ImmutableSet<String> statusesToApply;
|
||||
|
@ -138,6 +148,25 @@ final class UniformRapidSuspensionCommand extends MutatingEppToolCommand {
|
|||
} else {
|
||||
statusesToApply = URS_LOCKS;
|
||||
}
|
||||
|
||||
// trigger renew flow
|
||||
if (renewOneYear) {
|
||||
setSoyTemplate(DomainRenewSoyInfo.getInstance(), DomainRenewSoyInfo.RENEWDOMAIN);
|
||||
addSoyRecord(
|
||||
CLIENT_ID,
|
||||
new SoyMapData(
|
||||
"domainName",
|
||||
domain.getDomainName(),
|
||||
"expirationDate",
|
||||
domain
|
||||
.getRegistrationExpirationTime()
|
||||
.toString(DateTimeFormat.forPattern("YYYY-MM-dd")),
|
||||
// period is the number of years to renew the registration for
|
||||
"period",
|
||||
String.valueOf(1)));
|
||||
}
|
||||
|
||||
// trigger update flow
|
||||
setSoyTemplate(
|
||||
UniformRapidSuspensionSoyInfo.getInstance(),
|
||||
UniformRapidSuspensionSoyInfo.UNIFORMRAPIDSUSPENSION);
|
||||
|
|
|
@ -23,12 +23,15 @@ import static google.registry.testing.DatabaseHelper.persistResource;
|
|||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -40,6 +43,8 @@ class UniformRapidSuspensionCommandTest
|
|||
private HostResource ns2;
|
||||
private HostResource urs1;
|
||||
private HostResource urs2;
|
||||
private DomainBase defaultDomainBase;
|
||||
private ImmutableSet<DelegationSignerData> defaultDsData;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
|
@ -50,32 +55,36 @@ class UniformRapidSuspensionCommandTest
|
|||
ns2 = persistActiveHost("ns2.example.com");
|
||||
urs1 = persistActiveHost("urs1.example.com");
|
||||
urs2 = persistActiveHost("urs2.example.com");
|
||||
defaultDomainBase = newDomainBase("evil.tld");
|
||||
defaultDsData =
|
||||
ImmutableSet.of(
|
||||
DelegationSignerData.create(1, 2, 3, new HexBinaryAdapter().unmarshal("dead")),
|
||||
DelegationSignerData.create(4, 5, 6, new HexBinaryAdapter().unmarshal("beef")));
|
||||
}
|
||||
|
||||
private void persistDomainWithHosts(HostResource... hosts) {
|
||||
private void persistDomainWithHosts(
|
||||
DomainBase domainBase, ImmutableSet<DelegationSignerData> dsData, HostResource... hosts) {
|
||||
ImmutableSet.Builder<VKey<HostResource>> hostRefs = new ImmutableSet.Builder<>();
|
||||
for (HostResource host : hosts) {
|
||||
hostRefs.add(host.createVKey());
|
||||
}
|
||||
persistResource(newDomainBase("evil.tld").asBuilder()
|
||||
.setNameservers(hostRefs.build())
|
||||
.setDsData(ImmutableSet.of(
|
||||
DelegationSignerData.create(1, 2, 3, new HexBinaryAdapter().unmarshal("dead")),
|
||||
DelegationSignerData.create(4, 5, 6, new HexBinaryAdapter().unmarshal("beef"))))
|
||||
.build());
|
||||
persistResource(
|
||||
domainBase.asBuilder().setNameservers(hostRefs.build()).setDsData(dsData).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCommand_addsLocksReplacesHostsAndDsDataPrintsUndo() throws Exception {
|
||||
persistDomainWithHosts(ns1, ns2);
|
||||
persistDomainWithHosts(defaultDomainBase, defaultDsData, ns1, ns2);
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld",
|
||||
"--hosts=urs1.example.com,urs2.example.com",
|
||||
"--dsdata=1 1 1 abcd");
|
||||
"--dsdata=1 1 1 abcd",
|
||||
"--renew_one_year=false");
|
||||
eppVerifier
|
||||
.expectRegistrarId("CharlestonRoad")
|
||||
.expectSuperuser()
|
||||
.verifySent("uniform_rapid_suspension.xml");
|
||||
.verifySent("uniform_rapid_suspension.xml")
|
||||
.verifyNoMoreSent();
|
||||
assertInStdout("uniform_rapid_suspension --undo");
|
||||
assertInStdout("--domain_name evil.tld");
|
||||
assertInStdout("--hosts ns1.example.com,ns2.example.com");
|
||||
|
@ -86,12 +95,16 @@ class UniformRapidSuspensionCommandTest
|
|||
|
||||
@Test
|
||||
void testCommand_respectsExistingHost() throws Exception {
|
||||
persistDomainWithHosts(urs2, ns1);
|
||||
runCommandForced("--domain_name=evil.tld", "--hosts=urs1.example.com,urs2.example.com");
|
||||
persistDomainWithHosts(defaultDomainBase, defaultDsData, urs2, ns1);
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld",
|
||||
"--hosts=urs1.example.com,urs2.example.com",
|
||||
"--renew_one_year=false");
|
||||
eppVerifier
|
||||
.expectRegistrarId("CharlestonRoad")
|
||||
.expectSuperuser()
|
||||
.verifySent("uniform_rapid_suspension_existing_host.xml");
|
||||
.verifySent("uniform_rapid_suspension_existing_host.xml")
|
||||
.verifyNoMoreSent();
|
||||
assertInStdout("uniform_rapid_suspension --undo ");
|
||||
assertInStdout("--domain_name evil.tld");
|
||||
assertInStdout("--hosts ns1.example.com,urs2.example.com");
|
||||
|
@ -101,8 +114,11 @@ class UniformRapidSuspensionCommandTest
|
|||
@Test
|
||||
void testCommand_generatesUndoForUndelegatedDomain() throws Exception {
|
||||
persistActiveDomain("evil.tld");
|
||||
runCommandForced("--domain_name=evil.tld", "--hosts=urs1.example.com,urs2.example.com");
|
||||
eppVerifier.verifySentAny();
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld",
|
||||
"--hosts=urs1.example.com,urs2.example.com",
|
||||
"--renew_one_year=false");
|
||||
eppVerifier.verifySentAny().verifyNoMoreSent();
|
||||
assertInStdout("uniform_rapid_suspension --undo");
|
||||
assertInStdout("--domain_name evil.tld");
|
||||
assertNotInStdout("--locks_to_preserve");
|
||||
|
@ -114,8 +130,8 @@ class UniformRapidSuspensionCommandTest
|
|||
newDomainBase("evil.tld").asBuilder()
|
||||
.addStatusValue(StatusValue.SERVER_DELETE_PROHIBITED)
|
||||
.build());
|
||||
runCommandForced("--domain_name=evil.tld");
|
||||
eppVerifier.verifySentAny();
|
||||
runCommandForced("--domain_name=evil.tld", "--renew_one_year=false");
|
||||
eppVerifier.verifySentAny().verifyNoMoreSent();
|
||||
assertInStdout("uniform_rapid_suspension --undo");
|
||||
assertInStdout("--domain_name evil.tld");
|
||||
assertInStdout("--locks_to_preserve serverDeleteProhibited");
|
||||
|
@ -133,11 +149,13 @@ class UniformRapidSuspensionCommandTest
|
|||
runCommandForced(
|
||||
"--domain_name=evil.tld",
|
||||
"--hosts=urs1.example.com,urs2.example.com",
|
||||
"--dsdata=1 1 1 abcd");
|
||||
"--dsdata=1 1 1 abcd",
|
||||
"--renew_one_year=false");
|
||||
eppVerifier
|
||||
.expectRegistrarId("CharlestonRoad")
|
||||
.expectSuperuser()
|
||||
.verifySent("uniform_rapid_suspension_with_client_hold.xml");
|
||||
.verifySent("uniform_rapid_suspension_with_client_hold.xml")
|
||||
.verifyNoMoreSent();
|
||||
assertInStdout("uniform_rapid_suspension --undo");
|
||||
assertInStdout("--domain_name evil.tld");
|
||||
assertInStdout("--hosts ns1.example.com,ns2.example.com");
|
||||
|
@ -146,54 +164,62 @@ class UniformRapidSuspensionCommandTest
|
|||
|
||||
@Test
|
||||
void testUndo_removesLocksReplacesHostsAndDsData() throws Exception {
|
||||
persistDomainWithHosts(urs1, urs2);
|
||||
persistDomainWithHosts(defaultDomainBase, defaultDsData, urs1, urs2);
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld", "--undo", "--hosts=ns1.example.com,ns2.example.com");
|
||||
"--domain_name=evil.tld",
|
||||
"--undo",
|
||||
"--hosts=ns1.example.com,ns2.example.com",
|
||||
"--renew_one_year=false");
|
||||
eppVerifier
|
||||
.expectRegistrarId("CharlestonRoad")
|
||||
.expectSuperuser()
|
||||
.verifySent("uniform_rapid_suspension_undo.xml");
|
||||
.verifySent("uniform_rapid_suspension_undo.xml")
|
||||
.verifyNoMoreSent();
|
||||
assertNotInStdout("--undo"); // Undo shouldn't print a new undo command.
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUndo_respectsLocksToPreserveFlag() throws Exception {
|
||||
persistDomainWithHosts(urs1, urs2);
|
||||
persistDomainWithHosts(defaultDomainBase, defaultDsData, urs1, urs2);
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld",
|
||||
"--undo",
|
||||
"--locks_to_preserve=serverDeleteProhibited",
|
||||
"--hosts=ns1.example.com,ns2.example.com");
|
||||
"--hosts=ns1.example.com,ns2.example.com",
|
||||
"--renew_one_year=false");
|
||||
eppVerifier
|
||||
.expectRegistrarId("CharlestonRoad")
|
||||
.expectSuperuser()
|
||||
.verifySent("uniform_rapid_suspension_undo_preserve.xml");
|
||||
.verifySent("uniform_rapid_suspension_undo_preserve.xml")
|
||||
.verifyNoMoreSent();
|
||||
assertNotInStdout("--undo"); // Undo shouldn't print a new undo command.
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUndo_restoresClientHolds() throws Exception {
|
||||
persistDomainWithHosts(urs1, urs2);
|
||||
persistDomainWithHosts(defaultDomainBase, defaultDsData, urs1, urs2);
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld",
|
||||
"--undo",
|
||||
"--hosts=ns1.example.com,ns2.example.com",
|
||||
"--restore_client_hold");
|
||||
"--restore_client_hold",
|
||||
"--renew_one_year=false");
|
||||
eppVerifier
|
||||
.expectRegistrarId("CharlestonRoad")
|
||||
.expectSuperuser()
|
||||
.verifySent("uniform_rapid_suspension_undo_client_hold.xml");
|
||||
.verifySent("uniform_rapid_suspension_undo_client_hold.xml")
|
||||
.verifyNoMoreSent();
|
||||
assertNotInStdout("--undo"); // Undo shouldn't print a new undo command.
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAutorenews_setToFalsebyDefault() throws Exception {
|
||||
void testAutorenews_setToFalseByDefault() throws Exception {
|
||||
persistResource(
|
||||
newDomainBase("evil.tld")
|
||||
.asBuilder()
|
||||
.addStatusValue(StatusValue.SERVER_DELETE_PROHIBITED)
|
||||
.build());
|
||||
runCommandForced("--domain_name=evil.tld");
|
||||
runCommandForced("--domain_name=evil.tld", "--renew_one_year=false");
|
||||
eppVerifier.verifySentAny();
|
||||
assertInStdout("<superuser:autorenews>false</superuser:autorenews>");
|
||||
}
|
||||
|
@ -209,11 +235,57 @@ class UniformRapidSuspensionCommandTest
|
|||
"--domain_name=evil.tld",
|
||||
"--undo",
|
||||
"--hosts=ns1.example.com,ns2.example.com",
|
||||
"--restore_client_hold");
|
||||
"--restore_client_hold",
|
||||
"--renew_one_year=false");
|
||||
eppVerifier.verifySentAny();
|
||||
assertInStdout("<superuser:autorenews>true</superuser:autorenews>");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRenewOneYear_renewFlowIsTriggered() throws Exception {
|
||||
// this test case was written based on an existing test case,
|
||||
// testUndo_removesLocksReplacesHostsAndDsData() but two things were modified to test the
|
||||
// renew workflow, which were:
|
||||
// 1) a different domain that contains creation time and expiration time
|
||||
// 2) renew_one_year is set to true
|
||||
|
||||
persistDomainWithHosts(
|
||||
newDomainBase("evil.tld")
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(DateTime.parse("2021-10-01T05:01:11Z"))
|
||||
.setRegistrationExpirationTime(DateTime.parse("2022-10-01T05:01:11Z"))
|
||||
.setPersistedCurrentSponsorRegistrarId("CharlestonRoad")
|
||||
.build(),
|
||||
defaultDsData,
|
||||
urs1,
|
||||
urs2);
|
||||
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld",
|
||||
"--undo",
|
||||
"--hosts=ns1.example.com,ns2.example.com",
|
||||
"--renew_one_year=true");
|
||||
|
||||
// verify if renew flow is triggered
|
||||
eppVerifier
|
||||
.expectRegistrarId("CharlestonRoad")
|
||||
.expectSuperuser()
|
||||
.verifySent(
|
||||
"domain_renew.xml",
|
||||
ImmutableMap.of("DOMAIN", "evil.tld", "EXPDATE", "2022-10-01", "YEARS", "1"));
|
||||
|
||||
// verify if update flow is triggered
|
||||
eppVerifier
|
||||
.expectRegistrarId("CharlestonRoad")
|
||||
.expectSuperuser()
|
||||
.verifySent("uniform_rapid_suspension_undo.xml")
|
||||
.verifyNoMoreSent();
|
||||
assertNotInStdout("--undo"); // Undo shouldn't print a new undo command.
|
||||
|
||||
// verify that no other flows are triggered after the renew and update flows
|
||||
eppVerifier.verifyNoMoreSent();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_locksToPreserveWithoutUndo() {
|
||||
persistActiveDomain("evil.tld");
|
||||
|
@ -222,7 +294,9 @@ class UniformRapidSuspensionCommandTest
|
|||
IllegalArgumentException.class,
|
||||
() ->
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld", "--locks_to_preserve=serverDeleteProhibited"));
|
||||
"--domain_name=evil.tld",
|
||||
"--locks_to_preserve=serverDeleteProhibited",
|
||||
"--renew_one_year=false"));
|
||||
assertThat(thrown).hasMessageThat().contains("--undo");
|
||||
}
|
||||
|
||||
|
@ -232,17 +306,29 @@ class UniformRapidSuspensionCommandTest
|
|||
ParameterException thrown =
|
||||
assertThrows(
|
||||
ParameterException.class,
|
||||
() -> runCommandForced("--hosts=urs1.example.com,urs2.example.com"));
|
||||
() ->
|
||||
runCommandForced(
|
||||
"--hosts=urs1.example.com,urs2.example.com", "--renew_one_year=false"));
|
||||
assertThat(thrown).hasMessageThat().contains("--domain_name");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_renewOneYearRequired() {
|
||||
persistActiveDomain("evil.tld");
|
||||
ParameterException thrown =
|
||||
assertThrows(ParameterException.class, () -> runCommandForced("--domain_name=evil.tld"));
|
||||
assertThat(thrown).hasMessageThat().contains("--renew_one_year");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_extraFieldInDsData() {
|
||||
persistActiveDomain("evil.tld");
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommandForced("--domain_name=evil.tld", "--dsdata=1 1 1 abc 1"));
|
||||
() ->
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld", "--dsdata=1 1 1 abc 1", "--renew_one_year=false"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("dsRecord 1 1 1 abc 1 should have 4 parts, but has 5");
|
||||
|
@ -254,7 +340,9 @@ class UniformRapidSuspensionCommandTest
|
|||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommandForced("--domain_name=evil.tld", "--dsdata=1 1 1"));
|
||||
() ->
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld", "--dsdata=1 1 1", "--renew_one_year=false"));
|
||||
assertThat(thrown).hasMessageThat().contains("dsRecord 1 1 1 should have 4 parts, but has 3");
|
||||
}
|
||||
|
||||
|
@ -264,7 +352,9 @@ class UniformRapidSuspensionCommandTest
|
|||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommandForced("--domain_name=evil.tld", "--dsdata=1,2,3"));
|
||||
() ->
|
||||
runCommandForced(
|
||||
"--domain_name=evil.tld", "--dsdata=1,2,3", "--renew_one_year=false"));
|
||||
assertThat(thrown).hasMessageThat().contains("dsRecord 1 should have 4 parts, but has 1");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue