mirror of
https://github.com/google/nomulus.git
synced 2025-05-22 20:29:36 +02:00
Add autoRenewEndTime field to Domain entity (#765)
* Add autoRenewEndTime field to Domain entity This is the first step towards allowing administrators to selectively disable autorenew.
This commit is contained in:
parent
83dadc77d1
commit
a5bad9a2a4
9 changed files with 103 additions and 20 deletions
|
@ -25,6 +25,11 @@
|
||||||
<property name="tld" direction="asc"/>
|
<property name="tld" direction="asc"/>
|
||||||
<property name="creationTime" direction="desc"/>
|
<property name="creationTime" direction="desc"/>
|
||||||
</datastore-index>
|
</datastore-index>
|
||||||
|
<!-- For finding non-autorenewing domains to be deleted. -->
|
||||||
|
<datastore-index kind="DomainBase" ancestor="false" source="manual">
|
||||||
|
<property name="autorenewEndTime" direction="asc"/>
|
||||||
|
<property name="deletionTime" direction="asc"/>
|
||||||
|
</datastore-index>
|
||||||
<!-- For finding host resources by registrar. -->
|
<!-- For finding host resources by registrar. -->
|
||||||
<datastore-index kind="HostResource" ancestor="false" source="manual">
|
<datastore-index kind="HostResource" ancestor="false" source="manual">
|
||||||
<property name="currentSponsorClientId" direction="asc"/>
|
<property name="currentSponsorClientId" direction="asc"/>
|
||||||
|
|
|
@ -16,7 +16,6 @@ package google.registry.model.domain;
|
||||||
|
|
||||||
|
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import com.googlecode.objectify.annotation.Entity;
|
|
||||||
import google.registry.model.EppResource;
|
import google.registry.model.EppResource;
|
||||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||||
import google.registry.model.annotations.ExternalMessagingName;
|
import google.registry.model.annotations.ExternalMessagingName;
|
||||||
|
@ -31,10 +30,13 @@ import javax.persistence.AccessType;
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Index;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.JoinTable;
|
import javax.persistence.JoinTable;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,16 +49,17 @@ import org.joda.time.DateTime;
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc5731">RFC 5731</a>
|
* @see <a href="https://tools.ietf.org/html/rfc5731">RFC 5731</a>
|
||||||
*/
|
*/
|
||||||
@ReportedOn
|
@ReportedOn
|
||||||
@Entity
|
@com.googlecode.objectify.annotation.Entity
|
||||||
@javax.persistence.Entity(name = "Domain")
|
@Entity(name = "Domain")
|
||||||
@javax.persistence.Table(
|
@Table(
|
||||||
name = "Domain",
|
name = "Domain",
|
||||||
indexes = {
|
indexes = {
|
||||||
@javax.persistence.Index(columnList = "creationTime"),
|
@Index(columnList = "creationTime"),
|
||||||
@javax.persistence.Index(columnList = "currentSponsorRegistrarId"),
|
@Index(columnList = "currentSponsorRegistrarId"),
|
||||||
@javax.persistence.Index(columnList = "deletionTime"),
|
@Index(columnList = "deletionTime"),
|
||||||
@javax.persistence.Index(columnList = "domainName"),
|
@Index(columnList = "domainName"),
|
||||||
@javax.persistence.Index(columnList = "tld")
|
@Index(columnList = "tld"),
|
||||||
|
@Index(columnList = "autorenewEndTime")
|
||||||
})
|
})
|
||||||
@WithStringVKey
|
@WithStringVKey
|
||||||
@ExternalMessagingName("domain")
|
@ExternalMessagingName("domain")
|
||||||
|
|
|
@ -252,11 +252,27 @@ public class DomainContent extends EppResource
|
||||||
*/
|
*/
|
||||||
DateTime lastTransferTime;
|
DateTime lastTransferTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the domain's autorenewal status will expire.
|
||||||
|
*
|
||||||
|
* <p>This will be null for the vast majority of domains because all domains autorenew
|
||||||
|
* indefinitely by default and autorenew can only be countermanded by administrators, typically
|
||||||
|
* for reasons of the URS process or termination of a registrar for nonpayment.
|
||||||
|
*
|
||||||
|
* <p>When a domain is scheduled to not autorenew, this field is set to the current value of its
|
||||||
|
* {@link #registrationExpirationTime}, after which point the next invocation of a periodic
|
||||||
|
* cronjob will explicitly delete the domain. This field is a DateTime and not a boolean because
|
||||||
|
* of edge cases that occur during the autorenew grace period. We need to be able to tell the
|
||||||
|
* difference domains that have reached their life and must be deleted now, and domains that
|
||||||
|
* happen to be in the autorenew grace period now but should be deleted in roughly a year.
|
||||||
|
*/
|
||||||
|
@Nullable @Index DateTime autorenewEndTime;
|
||||||
|
|
||||||
@OnLoad
|
@OnLoad
|
||||||
void load() {
|
void load() {
|
||||||
// Reconstitute all of the contacts so that they have VKeys.
|
// Reconstitute all of the contacts so that they have VKeys.
|
||||||
allContacts =
|
allContacts =
|
||||||
allContacts.stream().map(contact -> contact.reconstitute()).collect(toImmutableSet());
|
allContacts.stream().map(DesignatedContact::reconstitute).collect(toImmutableSet());
|
||||||
setContactFields(allContacts, true);
|
setContactFields(allContacts, true);
|
||||||
|
|
||||||
// We have to return the cloned object here because the original object's
|
// We have to return the cloned object here because the original object's
|
||||||
|
@ -275,8 +291,7 @@ public class DomainContent extends EppResource
|
||||||
@PostLoad
|
@PostLoad
|
||||||
void postLoad() {
|
void postLoad() {
|
||||||
// Reconstitute the contact list.
|
// Reconstitute the contact list.
|
||||||
ImmutableSet.Builder<DesignatedContact> contactsBuilder =
|
ImmutableSet.Builder<DesignatedContact> contactsBuilder = new ImmutableSet.Builder<>();
|
||||||
new ImmutableSet.Builder<DesignatedContact>();
|
|
||||||
|
|
||||||
if (registrantContact != null) {
|
if (registrantContact != null) {
|
||||||
contactsBuilder.add(
|
contactsBuilder.add(
|
||||||
|
@ -323,6 +338,10 @@ public class DomainContent extends EppResource
|
||||||
return smdId;
|
return smdId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<DateTime> getAutorenewEndTime() {
|
||||||
|
return Optional.ofNullable(autorenewEndTime);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DomainTransferData getTransferData() {
|
public DomainTransferData getTransferData() {
|
||||||
return Optional.ofNullable(transferData).orElse(DomainTransferData.EMPTY);
|
return Optional.ofNullable(transferData).orElse(DomainTransferData.EMPTY);
|
||||||
|
@ -835,6 +854,11 @@ public class DomainContent extends EppResource
|
||||||
return thisCastToDerived();
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public B setAutorenewEndTime(Optional<DateTime> autorenewEndTime) {
|
||||||
|
getInstance().autorenewEndTime = autorenewEndTime.orElse(null);
|
||||||
|
return thisCastToDerived();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public B setTransferData(DomainTransferData transferData) {
|
public B setTransferData(DomainTransferData transferData) {
|
||||||
getInstance().transferData = transferData;
|
getInstance().transferData = transferData;
|
||||||
|
|
|
@ -14,14 +14,33 @@
|
||||||
|
|
||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beust.jcommander.Parameter;
|
||||||
import com.beust.jcommander.Parameters;
|
import com.beust.jcommander.Parameters;
|
||||||
import google.registry.model.SchemaVersion;
|
import google.registry.model.SchemaVersion;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
/** Generates the schema file used for model versioning. */
|
/** Generates the schema file used for model versioning. */
|
||||||
@Parameters(commandDescription = "Generate a model schema file")
|
@Parameters(commandDescription = "Generate a model schema file")
|
||||||
final class GetSchemaCommand implements Command {
|
final class GetSchemaCommand implements Command {
|
||||||
|
|
||||||
|
@Parameter(
|
||||||
|
names = {"-o", "--out_file"},
|
||||||
|
description = "Name of the output file.")
|
||||||
|
String outFile;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() throws IOException {
|
||||||
System.out.println(SchemaVersion.getSchema());
|
String schema = SchemaVersion.getSchema();
|
||||||
|
if (outFile == null) {
|
||||||
|
System.out.println(schema);
|
||||||
|
} else {
|
||||||
|
File file = new File(outFile);
|
||||||
|
file.createNewFile(); // Create the output file if it doesn't already exist.
|
||||||
|
Files.write(file.toPath(), schema.getBytes(UTF_8));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.transfer.DomainTransferData;
|
import google.registry.model.transfer.DomainTransferData;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
|
import java.util.Optional;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -66,12 +67,11 @@ public class DomainBaseTest extends EntityTestCase {
|
||||||
private DomainBase domain;
|
private DomainBase domain;
|
||||||
private VKey<BillingEvent.OneTime> oneTimeBillKey;
|
private VKey<BillingEvent.OneTime> oneTimeBillKey;
|
||||||
private VKey<BillingEvent.Recurring> recurringBillKey;
|
private VKey<BillingEvent.Recurring> recurringBillKey;
|
||||||
private VKey<DomainBase> domainKey;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
createTld("com");
|
createTld("com");
|
||||||
domainKey = VKey.from(Key.create(null, DomainBase.class, "4-COM"));
|
VKey<DomainBase> domainKey = VKey.from(Key.create(null, DomainBase.class, "4-COM"));
|
||||||
VKey<HostResource> hostKey =
|
VKey<HostResource> hostKey =
|
||||||
persistResource(
|
persistResource(
|
||||||
new HostResource.Builder()
|
new HostResource.Builder()
|
||||||
|
@ -158,6 +158,7 @@ public class DomainBaseTest extends EntityTestCase {
|
||||||
fakeClock.nowUtc().plusDays(1),
|
fakeClock.nowUtc().plusDays(1),
|
||||||
"registrar",
|
"registrar",
|
||||||
null))
|
null))
|
||||||
|
.setAutorenewEndTime(Optional.of(fakeClock.nowUtc().plusYears(2)))
|
||||||
.build()));
|
.build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +177,8 @@ public class DomainBaseTest extends EntityTestCase {
|
||||||
"nsHosts",
|
"nsHosts",
|
||||||
"currentSponsorClientId",
|
"currentSponsorClientId",
|
||||||
"deletionTime",
|
"deletionTime",
|
||||||
"tld");
|
"tld",
|
||||||
|
"autorenewEndTime");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -185,6 +185,7 @@ class google.registry.model.domain.DomainBase {
|
||||||
java.util.Set<google.registry.model.eppcommon.StatusValue> status;
|
java.util.Set<google.registry.model.eppcommon.StatusValue> status;
|
||||||
java.util.Set<google.registry.persistence.VKey<google.registry.model.host.HostResource>> nsHosts;
|
java.util.Set<google.registry.persistence.VKey<google.registry.model.host.HostResource>> nsHosts;
|
||||||
java.util.Set<java.lang.String> subordinateHosts;
|
java.util.Set<java.lang.String> subordinateHosts;
|
||||||
|
org.joda.time.DateTime autorenewEndTime;
|
||||||
org.joda.time.DateTime deletionTime;
|
org.joda.time.DateTime deletionTime;
|
||||||
org.joda.time.DateTime lastEppUpdateTime;
|
org.joda.time.DateTime lastEppUpdateTime;
|
||||||
org.joda.time.DateTime lastTransferTime;
|
org.joda.time.DateTime lastTransferTime;
|
||||||
|
@ -765,4 +766,4 @@ enum google.registry.model.transfer.TransferStatus {
|
||||||
PENDING;
|
PENDING;
|
||||||
SERVER_APPROVED;
|
SERVER_APPROVED;
|
||||||
SERVER_CANCELLED;
|
SERVER_CANCELLED;
|
||||||
}
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
-- Copyright 2020 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.
|
||||||
|
|
||||||
|
ALTER TABLE "Domain" ADD COLUMN autorenew_end_time timestamptz;
|
||||||
|
ALTER TABLE "DomainHistory" ADD COLUMN autorenew_end_time timestamptz;
|
||||||
|
CREATE INDEX IDXlrq7v63pc21uoh3auq6eybyhl ON "Domain" (autorenew_end_time);
|
|
@ -233,6 +233,7 @@ create sequence history_id_sequence start 1 increment 1;
|
||||||
auth_info_repo_id text,
|
auth_info_repo_id text,
|
||||||
auth_info_value text,
|
auth_info_value text,
|
||||||
billing_recurrence_id int8,
|
billing_recurrence_id int8,
|
||||||
|
autorenew_end_time timestamptz,
|
||||||
autorenew_poll_message_id int8,
|
autorenew_poll_message_id int8,
|
||||||
billing_contact text,
|
billing_contact text,
|
||||||
deletion_poll_message_id int8,
|
deletion_poll_message_id int8,
|
||||||
|
@ -283,6 +284,7 @@ create sequence history_id_sequence start 1 increment 1;
|
||||||
auth_info_repo_id text,
|
auth_info_repo_id text,
|
||||||
auth_info_value text,
|
auth_info_value text,
|
||||||
billing_recurrence_id int8,
|
billing_recurrence_id int8,
|
||||||
|
autorenew_end_time timestamptz,
|
||||||
autorenew_poll_message_id int8,
|
autorenew_poll_message_id int8,
|
||||||
billing_contact text,
|
billing_contact text,
|
||||||
deletion_poll_message_id int8,
|
deletion_poll_message_id int8,
|
||||||
|
@ -591,6 +593,7 @@ create index IDXhsjqiy2lyobfymplb28nm74lm on "Domain" (current_sponsor_registrar
|
||||||
create index IDX5mnf0wn20tno4b9do88j61klr on "Domain" (deletion_time);
|
create index IDX5mnf0wn20tno4b9do88j61klr on "Domain" (deletion_time);
|
||||||
create index IDXc5aw4pk1vkd6ymhvkpanmoadv on "Domain" (domain_name);
|
create index IDXc5aw4pk1vkd6ymhvkpanmoadv on "Domain" (domain_name);
|
||||||
create index IDXrwl38wwkli1j7gkvtywi9jokq on "Domain" (tld);
|
create index IDXrwl38wwkli1j7gkvtywi9jokq on "Domain" (tld);
|
||||||
|
create index IDXlrq7v63pc21uoh3auq6eybyhl on "Domain" (autorenew_end_time);
|
||||||
create index IDXrh4xmrot9bd63o382ow9ltfig on "DomainHistory" (creation_time);
|
create index IDXrh4xmrot9bd63o382ow9ltfig on "DomainHistory" (creation_time);
|
||||||
create index IDXaro1omfuaxjwmotk3vo00trwm on "DomainHistory" (history_registrar_id);
|
create index IDXaro1omfuaxjwmotk3vo00trwm on "DomainHistory" (history_registrar_id);
|
||||||
create index IDXsu1nam10cjes9keobapn5jvxj on "DomainHistory" (history_type);
|
create index IDXsu1nam10cjes9keobapn5jvxj on "DomainHistory" (history_type);
|
||||||
|
|
|
@ -401,7 +401,8 @@ CREATE TABLE public."Domain" (
|
||||||
update_timestamp timestamp with time zone,
|
update_timestamp timestamp with time zone,
|
||||||
billing_recurrence_id bigint,
|
billing_recurrence_id bigint,
|
||||||
autorenew_poll_message_id bigint,
|
autorenew_poll_message_id bigint,
|
||||||
deletion_poll_message_id bigint
|
deletion_poll_message_id bigint,
|
||||||
|
autorenew_end_time timestamp with time zone
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -464,7 +465,8 @@ CREATE TABLE public."DomainHistory" (
|
||||||
last_epp_update_time timestamp with time zone,
|
last_epp_update_time timestamp with time zone,
|
||||||
statuses text[],
|
statuses text[],
|
||||||
update_timestamp timestamp with time zone,
|
update_timestamp timestamp with time zone,
|
||||||
domain_repo_id text NOT NULL
|
domain_repo_id text NOT NULL,
|
||||||
|
autorenew_end_time timestamp with time zone
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1386,6 +1388,13 @@ CREATE INDEX idxkjt9yaq92876dstimd93hwckh ON public."Domain" USING btree (curren
|
||||||
CREATE INDEX idxknk8gmj7s47q56cwpa6rmpt5l ON public."HostHistory" USING btree (history_type);
|
CREATE INDEX idxknk8gmj7s47q56cwpa6rmpt5l ON public."HostHistory" USING btree (history_type);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxlrq7v63pc21uoh3auq6eybyhl; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxlrq7v63pc21uoh3auq6eybyhl ON public."Domain" USING btree (autorenew_end_time);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idxn1f711wicdnooa2mqb7g1m55o; Type: INDEX; Schema: public; Owner: -
|
-- Name: idxn1f711wicdnooa2mqb7g1m55o; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue