Add support for a domain delete superuser EPP extension

Allow superusers to change the grace period and allow
superusers to change the pending delete length.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=168028545
This commit is contained in:
bbilbo 2017-09-08 12:11:16 -07:00 committed by jianglai
parent c85dc0c089
commit 4b83615513
6 changed files with 166 additions and 5 deletions

View file

@ -72,6 +72,7 @@ import google.registry.model.domain.fee12.FeeDeleteResponseExtensionV12;
import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.secdns.SecDnsCreateExtension; import google.registry.model.domain.secdns.SecDnsCreateExtension;
import google.registry.model.domain.superuser.DomainDeleteSuperuserExtension;
import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension; import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.StatusValue;
@ -131,7 +132,8 @@ public final class DomainDeleteFlow implements TransactionalFlow {
@Override @Override
public final EppResponse run() throws EppException { public final EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class, SecDnsCreateExtension.class); extensionManager.register(
MetadataExtension.class, SecDnsCreateExtension.class, DomainDeleteSuperuserExtension.class);
customLogic.beforeValidation(); customLogic.beforeValidation();
extensionManager.validate(); extensionManager.validate();
validateClientIsLoggedIn(clientId); validateClientIsLoggedIn(clientId);
@ -147,6 +149,16 @@ public final class DomainDeleteFlow implements TransactionalFlow {
? ResourceFlowUtils.<DomainResource, DomainResource.Builder>resolvePendingTransfer( ? ResourceFlowUtils.<DomainResource, DomainResource.Builder>resolvePendingTransfer(
existingDomain, TransferStatus.SERVER_CANCELLED, now) existingDomain, TransferStatus.SERVER_CANCELLED, now)
: existingDomain.asBuilder(); : existingDomain.asBuilder();
Duration redemptionGracePeriodLength = registry.getRedemptionGracePeriodLength();
Duration pendingDeleteLength = registry.getPendingDeleteLength();
DomainDeleteSuperuserExtension domainDeleteSuperuserExtension =
eppInput.getSingleExtension(DomainDeleteSuperuserExtension.class);
if (domainDeleteSuperuserExtension != null) {
redemptionGracePeriodLength =
Duration.standardDays(domainDeleteSuperuserExtension.getRedemptionGracePeriodDays());
pendingDeleteLength =
Duration.standardDays(domainDeleteSuperuserExtension.getPendingDeleteDays());
}
boolean inAddGracePeriod = boolean inAddGracePeriod =
existingDomain.getGracePeriodStatuses().contains(GracePeriodStatus.ADD); existingDomain.getGracePeriodStatuses().contains(GracePeriodStatus.ADD);
// If the domain is in the Add Grace Period, we delete it immediately. // If the domain is in the Add Grace Period, we delete it immediately.
@ -155,10 +167,10 @@ public final class DomainDeleteFlow implements TransactionalFlow {
inAddGracePeriod inAddGracePeriod
? Duration.ZERO ? Duration.ZERO
// By default, this should be 30 days of grace, and 5 days of pending delete. // By default, this should be 30 days of grace, and 5 days of pending delete.
: registry.getRedemptionGracePeriodLength().plus(registry.getPendingDeleteLength()); : redemptionGracePeriodLength.plus(pendingDeleteLength);
HistoryEntry historyEntry = buildHistoryEntry( HistoryEntry historyEntry = buildHistoryEntry(
existingDomain, registry, now, durationUntilDelete, inAddGracePeriod); existingDomain, registry, now, durationUntilDelete, inAddGracePeriod);
if (inAddGracePeriod) { if (durationUntilDelete.equals(Duration.ZERO)) {
builder.setDeletionTime(now).setStatusValues(null); builder.setDeletionTime(now).setStatusValues(null);
} else { } else {
DateTime deletionTime = now.plus(durationUntilDelete); DateTime deletionTime = now.plus(durationUntilDelete);
@ -171,7 +183,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
// billing event because there isn't one for a domain delete. // billing event because there isn't one for a domain delete.
.setGracePeriods(ImmutableSet.of(GracePeriod.createWithoutBillingEvent( .setGracePeriods(ImmutableSet.of(GracePeriod.createWithoutBillingEvent(
GracePeriodStatus.REDEMPTION, GracePeriodStatus.REDEMPTION,
now.plus(registry.getRedemptionGracePeriodLength()), now.plus(redemptionGracePeriodLength),
clientId))) clientId)))
.setDeletePollMessage(Key.create(deletePollMessage)); .setDeletePollMessage(Key.create(deletePollMessage));
// Note: The expiration time is unchanged, so if it's before the new deletion time, there will // Note: The expiration time is unchanged, so if it's before the new deletion time, there will

View file

@ -0,0 +1,36 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.domain.superuser;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/** A superuser extension that may be present on domain delete commands. */
@XmlRootElement(name = "domainDelete")
public class DomainDeleteSuperuserExtension extends SuperuserExtension {
@XmlElement(name = "redemptionGracePeriodDays")
int redemptionGracePeriodDays;
@XmlElement(name = "pendingDeleteDays")
int pendingDeleteDays;
public int getRedemptionGracePeriodDays() {
return redemptionGracePeriodDays;
}
public int getPendingDeleteDays() {
return pendingDeleteDays;
}
}

View file

@ -51,6 +51,7 @@ import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.rgp.RgpUpdateExtension; import google.registry.model.domain.rgp.RgpUpdateExtension;
import google.registry.model.domain.secdns.SecDnsCreateExtension; import google.registry.model.domain.secdns.SecDnsCreateExtension;
import google.registry.model.domain.secdns.SecDnsUpdateExtension; import google.registry.model.domain.secdns.SecDnsUpdateExtension;
import google.registry.model.domain.superuser.DomainDeleteSuperuserExtension;
import google.registry.model.domain.superuser.DomainTransferRequestSuperuserExtension; import google.registry.model.domain.superuser.DomainTransferRequestSuperuserExtension;
import google.registry.model.eppinput.ResourceCommand.ResourceCheck; import google.registry.model.eppinput.ResourceCommand.ResourceCheck;
import google.registry.model.eppinput.ResourceCommand.SingleResourceCommand; import google.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
@ -347,7 +348,8 @@ public class EppInput extends ImmutableObject {
@XmlElementRef(type = RgpUpdateExtension.class), @XmlElementRef(type = RgpUpdateExtension.class),
@XmlElementRef(type = SecDnsCreateExtension.class), @XmlElementRef(type = SecDnsCreateExtension.class),
@XmlElementRef(type = SecDnsUpdateExtension.class), @XmlElementRef(type = SecDnsUpdateExtension.class),
@XmlElementRef(type = DomainTransferRequestSuperuserExtension.class) }) @XmlElementRef(type = DomainTransferRequestSuperuserExtension.class),
@XmlElementRef(type = DomainDeleteSuperuserExtension.class) })
@XmlElementWrapper @XmlElementWrapper
List<CommandExtension> extension; List<CommandExtension> extension;

View file

@ -38,4 +38,13 @@
</restriction> </restriction>
</simpleType> </simpleType>
<element name="domainDelete" type="superuser:domainDeleteType" />
<complexType name="domainDeleteType">
<all>
<element name="redemptionGracePeriodDays" type="nonNegativeInteger" />
<element name="pendingDeleteDays" type="nonNegativeInteger" />
</all>
</complexType>
</schema> </schema>

View file

@ -952,4 +952,89 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
// The cancellation record is the same as the original, except with a -1 counter // The cancellation record is the same as the original, except with a -1 counter
existingRecord.asBuilder().setReportAmount(-1).build()); existingRecord.asBuilder().setReportAmount(-1).build());
} }
@Test
public void testSuccess_superuserExtension_nonZeroDayGrace_nonZeroDayPendingDelete()
throws Exception {
eppRequestSource = EppRequestSource.TOOL;
setEppInput(
"domain_delete_superuser_extension.xml",
ImmutableMap.of("REDEMPTION_GRACE_PERIOD_DAYS", "15", "PENDING_DELETE_DAYS", "4"));
setUpSuccessfulTest();
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, readFile("domain_delete_response_pending.xml"));
DomainResource resource = reloadResourceByForeignKey();
assertAboutDomains()
.that(resource)
.hasExactlyStatusValues(StatusValue.INACTIVE, StatusValue.PENDING_DELETE)
.and()
.hasDeletionTime(clock.nowUtc().plus(Duration.standardDays(19)));
assertThat(resource.getGracePeriods())
.containsExactly(
GracePeriod.create(
GracePeriodStatus.REDEMPTION,
clock.nowUtc().plus(Duration.standardDays(15)),
"TheRegistrar",
null));
}
@Test
public void testSuccess_superuserExtension_zeroDayGrace_nonZeroDayPendingDelete()
throws Exception {
eppRequestSource = EppRequestSource.TOOL;
setEppInput(
"domain_delete_superuser_extension.xml",
ImmutableMap.of("REDEMPTION_GRACE_PERIOD_DAYS", "0", "PENDING_DELETE_DAYS", "4"));
setUpSuccessfulTest();
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, readFile("domain_delete_response_pending.xml"));
DomainResource resource = reloadResourceByForeignKey();
assertAboutDomains()
.that(resource)
.hasExactlyStatusValues(StatusValue.INACTIVE, StatusValue.PENDING_DELETE)
.and()
.hasDeletionTime(clock.nowUtc().plus(Duration.standardDays(4)));
assertThat(resource.getGracePeriods()).isEmpty();
}
@Test
public void testSuccess_superuserExtension_nonZeroDayGrace_zeroDayPendingDelete()
throws Exception {
eppRequestSource = EppRequestSource.TOOL;
setEppInput(
"domain_delete_superuser_extension.xml",
ImmutableMap.of("REDEMPTION_GRACE_PERIOD_DAYS", "15", "PENDING_DELETE_DAYS", "0"));
setUpSuccessfulTest();
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, readFile("domain_delete_response_pending.xml"));
DomainResource resource = reloadResourceByForeignKey();
assertAboutDomains()
.that(resource)
.hasExactlyStatusValues(StatusValue.INACTIVE, StatusValue.PENDING_DELETE)
.and()
.hasDeletionTime(clock.nowUtc().plus(Duration.standardDays(15)));
assertThat(resource.getGracePeriods())
.containsExactly(
GracePeriod.create(
GracePeriodStatus.REDEMPTION,
clock.nowUtc().plus(Duration.standardDays(15)),
"TheRegistrar",
null));
}
@Test
public void testSuccess_superuserExtension_zeroDayGrace_zeroDayPendingDelete() throws Exception {
eppRequestSource = EppRequestSource.TOOL;
setEppInput(
"domain_delete_superuser_extension.xml",
ImmutableMap.of("REDEMPTION_GRACE_PERIOD_DAYS", "0", "PENDING_DELETE_DAYS", "0"));
setUpSuccessfulTest();
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, readFile("domain_delete_response.xml"));
assertThat(reloadResourceByForeignKey()).isNull();
}
} }

View file

@ -0,0 +1,17 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<delete>
<domain:delete
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.tld</domain:name>
</domain:delete>
</delete>
<extension>
<superuser:domainDelete xmlns:superuser="urn:google:params:xml:ns:superuser-1.0">
<superuser:redemptionGracePeriodDays>%REDEMPTION_GRACE_PERIOD_DAYS%</superuser:redemptionGracePeriodDays>
<superuser:pendingDeleteDays>%PENDING_DELETE_DAYS%</superuser:pendingDeleteDays>
</superuser:domainDelete>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>