Compare commits
11 Commits
nomulus-20
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19bc1c9c9c | ||
|
|
c361c9e601 | ||
|
|
aa0dcea537 | ||
|
|
e920e4d201 | ||
|
|
cd13f6c5d3 | ||
|
|
210de9340e | ||
|
|
5d58be6f0a | ||
|
|
d8066ca752 | ||
|
|
ca3ae9b0e4 | ||
|
|
295251ee78 | ||
|
|
7ca0e9387c |
@@ -31,10 +31,6 @@ def coreResourcesDir = "${rootDir}/core/build/resources/main"
|
||||
war {
|
||||
webInf {
|
||||
from "../../core/src/main/java/google/registry/env/common/${project.name}/WEB-INF"
|
||||
|
||||
from("${coreResourcesDir}/META-INF/persistence.xml") {
|
||||
into "classes/META-INF"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,15 @@ PRESUBMITS = {
|
||||
"System.(out|err).println is only allowed in tools/ packages. Please "
|
||||
"use a logger instead.",
|
||||
|
||||
# ObjectifyService.register is restricted to main/ or AppEngineRule.
|
||||
PresubmitCheck(
|
||||
r".*\bObjectifyService\.register", "java", {
|
||||
"/build/", "/generated/", "node_modules/", "src/main/",
|
||||
"AppEngineRule.java"
|
||||
}):
|
||||
"ObjectifyService.register is not allowed in tests. Please use "
|
||||
"AppengineRule.register instead.",
|
||||
|
||||
# PostgreSQLContainer instantiation must specify docker tag
|
||||
PresubmitCheck(
|
||||
r"[\s\S]*new\s+PostgreSQLContainer(<[\s\S]*>)?\(\s*\)[\s\S]*",
|
||||
|
||||
@@ -295,6 +295,8 @@ dependencies {
|
||||
testAnnotationProcessor deps['com.google.auto.value:auto-value']
|
||||
annotationProcessor deps['com.google.dagger:dagger-compiler']
|
||||
testAnnotationProcessor deps['com.google.dagger:dagger-compiler']
|
||||
annotationProcessor project(':processor')
|
||||
testAnnotationProcessor project(':processor')
|
||||
|
||||
testCompile deps['com.google.appengine:appengine-testing']
|
||||
testCompile deps['com.google.guava:guava-testlib']
|
||||
|
||||
@@ -12,24 +12,24 @@ com.google.dagger:dagger-producers:2.21
|
||||
com.google.dagger:dagger-spi:2.21
|
||||
com.google.dagger:dagger:2.21
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:javac-shaded:9-dev-r4023-3
|
||||
com.google.googlejavaformat:google-java-format:1.5
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
com.squareup:javapoet:1.11.1
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-compat-qual:2.5.3
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
|
||||
@@ -12,24 +12,24 @@ com.google.dagger:dagger-producers:2.21
|
||||
com.google.dagger:dagger-spi:2.21
|
||||
com.google.dagger:dagger:2.21
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:javac-shaded:9-dev-r4023-3
|
||||
com.google.googlejavaformat:google-java-format:1.5
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
com.squareup:javapoet:1.11.1
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.annotation:jsr250-api:1.0
|
||||
javax.inject:javax.inject:1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-compat-qual:2.5.3
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
|
||||
@@ -1512,21 +1512,11 @@ public final class RegistryConfig {
|
||||
return CONFIG_SETTINGS.get().hibernate.hikariConnectionTimeout;
|
||||
}
|
||||
|
||||
/** Returns the minimum idle connections for HikariCP. */
|
||||
public static String getHibernateHikariMinimumIdle() {
|
||||
return CONFIG_SETTINGS.get().hibernate.hikariMinimumIdle;
|
||||
}
|
||||
|
||||
/** Returns the maximum pool size for HikariCP. */
|
||||
public static String getHibernateHikariMaximumPoolSize() {
|
||||
return CONFIG_SETTINGS.get().hibernate.hikariMaximumPoolSize;
|
||||
}
|
||||
|
||||
/** Returns the idle timeout for HikariCP. */
|
||||
public static String getHibernateHikariIdleTimeout() {
|
||||
return CONFIG_SETTINGS.get().hibernate.hikariIdleTimeout;
|
||||
}
|
||||
|
||||
/** Returns the roid suffix to be used for the roids of all contacts and hosts. */
|
||||
public static String getContactAndHostRoidSuffix() {
|
||||
return CONFIG_SETTINGS.get().registryPolicy.contactAndHostRoidSuffix;
|
||||
|
||||
@@ -112,9 +112,7 @@ public class RegistryConfigSettings {
|
||||
public String connectionIsolation;
|
||||
public String logSqlQueries;
|
||||
public String hikariConnectionTimeout;
|
||||
public String hikariMinimumIdle;
|
||||
public String hikariMaximumPoolSize;
|
||||
public String hikariIdleTimeout;
|
||||
}
|
||||
|
||||
/** Configuration for Cloud SQL. */
|
||||
|
||||
@@ -207,9 +207,17 @@ hibernate:
|
||||
|
||||
# Connection pool configurations.
|
||||
hikariConnectionTimeout: 20000
|
||||
hikariMinimumIdle: 0
|
||||
|
||||
# We occasionally received "Connection is not available, request timed out"
|
||||
# exception when setting minimumIdle to 0 and it turned out it is a bug (See
|
||||
# https://github.com/brettwooldridge/HikariCP/issues/1212) in HikariCP and
|
||||
# the workaround is to use a fixed size connection pool.
|
||||
#
|
||||
# HikariCP also recommends not setting minimumIdle for maximum performance
|
||||
# and responsiveness to spike demands (See
|
||||
# https://github.com/brettwooldridge/HikariCP).
|
||||
# TODO(b/154720215): Experiment with a smaller pool size.
|
||||
hikariMaximumPoolSize: 20
|
||||
hikariIdleTimeout: 300000
|
||||
|
||||
cloudSql:
|
||||
# jdbc url for the Cloud SQL database.
|
||||
|
||||
@@ -70,9 +70,11 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
|
||||
/** The ID of the registrar that is currently sponsoring this resource. */
|
||||
@Index
|
||||
@Column(nullable = false)
|
||||
String currentSponsorClientId;
|
||||
|
||||
/** The ID of the registrar that created this resource. */
|
||||
@Column(nullable = false)
|
||||
String creationClientId;
|
||||
|
||||
/**
|
||||
@@ -88,7 +90,9 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
// Map the method to XML, not the field, because if we map the field (with an adaptor class) it
|
||||
// will never be omitted from the xml even if the timestamp inside creationTime is null and we
|
||||
// return null from the adaptor. (Instead it gets written as an empty tag.)
|
||||
@Index CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
@Column(nullable = false)
|
||||
@Index
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/**
|
||||
* The time when this resource was or will be deleted.
|
||||
@@ -131,7 +135,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
@Transient
|
||||
ImmutableSortedMap<DateTime, Key<CommitLogManifest>> revisions = ImmutableSortedMap.of();
|
||||
|
||||
public final String getRepoId() {
|
||||
public String getRepoId() {
|
||||
return repoId;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,14 @@ package google.registry.model.contact;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.eppcommon.Address;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* EPP Contact Address
|
||||
*
|
||||
* <p>This class is embedded inside the {@link PostalInfo} of an EPP contact to hold its
|
||||
* address. The fields are all defined in parent class {@link Address}, but the subclass is still
|
||||
* necessary to pick up the contact namespace.
|
||||
* <p>This class is embedded inside the {@link PostalInfo} of an EPP contact to hold its address.
|
||||
* The fields are all defined in parent class {@link Address}, but the subclass is still necessary
|
||||
* to pick up the contact namespace.
|
||||
*
|
||||
* <p>This does not implement {@code Overlayable} because it is intended to be bulk replaced on
|
||||
* update.
|
||||
@@ -30,6 +31,7 @@ import google.registry.model.eppcommon.Address;
|
||||
* @see PostalInfo
|
||||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
public class ContactAddress extends Address {
|
||||
|
||||
/** Builder for {@link ContactAddress}. */
|
||||
|
||||
@@ -20,6 +20,7 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/** A version of authInfo specifically for contacts. */
|
||||
@Embed
|
||||
@javax.persistence.Embeddable
|
||||
@XmlType(namespace = "urn:ietf:params:xml:ns:contact-1.0")
|
||||
public class ContactAuthInfo extends AuthInfo {
|
||||
public static ContactAuthInfo create(PasswordAuth pw) {
|
||||
|
||||
@@ -16,17 +16,19 @@ package google.registry.model.contact;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.eppcommon.PhoneNumber;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* EPP Contact Phone Number
|
||||
*
|
||||
* <p>This class is embedded inside a {@link ContactResource} hold the phone number of an EPP
|
||||
* contact. The fields are all defined in the parent class {@link PhoneNumber}, but the subclass is
|
||||
* contact. The fields are all defined in the parent class {@link PhoneNumber}, but the subclass is
|
||||
* still necessary to pick up the contact namespace.
|
||||
*
|
||||
* @see ContactResource
|
||||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
public class ContactPhoneNumber extends PhoneNumber {
|
||||
|
||||
/** Builder for {@link ContactPhoneNumber}. */
|
||||
|
||||
@@ -33,6 +33,11 @@ import google.registry.model.transfer.TransferData;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Transient;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -43,9 +48,19 @@ import org.joda.time.DateTime;
|
||||
*/
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@javax.persistence.Entity(name = "Contact")
|
||||
@javax.persistence.Table(
|
||||
name = "Contact",
|
||||
indexes = {
|
||||
@javax.persistence.Index(columnList = "creationTime"),
|
||||
@javax.persistence.Index(columnList = "currentSponsorClientId"),
|
||||
@javax.persistence.Index(columnList = "deletionTime"),
|
||||
@javax.persistence.Index(columnList = "contactId", unique = true),
|
||||
@javax.persistence.Index(columnList = "searchName")
|
||||
})
|
||||
@ExternalMessagingName("contact")
|
||||
public class ContactResource extends EppResource implements
|
||||
ForeignKeyedEppResource, ResourceWithTransferData {
|
||||
public class ContactResource extends EppResource
|
||||
implements ForeignKeyedEppResource, ResourceWithTransferData {
|
||||
|
||||
/**
|
||||
* Unique identifier for this contact.
|
||||
@@ -61,13 +76,55 @@ public class ContactResource extends EppResource implements
|
||||
* US-ASCII character set. Personal info; cleared by {@link Builder#wipeOut}.
|
||||
*/
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "name", column = @Column(name = "addr_local_name")),
|
||||
@AttributeOverride(name = "org", column = @Column(name = "addr_local_org")),
|
||||
@AttributeOverride(name = "type", column = @Column(name = "addr_local_type")),
|
||||
@AttributeOverride(
|
||||
name = "address.streetLine1",
|
||||
column = @Column(name = "addr_local_street_line1")),
|
||||
@AttributeOverride(
|
||||
name = "address.streetLine2",
|
||||
column = @Column(name = "addr_local_street_line2")),
|
||||
@AttributeOverride(
|
||||
name = "address.streetLine3",
|
||||
column = @Column(name = "addr_local_street_line3")),
|
||||
@AttributeOverride(name = "address.city", column = @Column(name = "addr_local_city")),
|
||||
@AttributeOverride(name = "address.state", column = @Column(name = "addr_local_state")),
|
||||
@AttributeOverride(name = "address.zip", column = @Column(name = "addr_local_zip")),
|
||||
@AttributeOverride(
|
||||
name = "address.countryCode",
|
||||
column = @Column(name = "addr_local_country_code"))
|
||||
})
|
||||
PostalInfo localizedPostalInfo;
|
||||
|
||||
/**
|
||||
* Internationalized postal info for the contact. Personal info; cleared by
|
||||
* {@link Builder#wipeOut}.
|
||||
* Internationalized postal info for the contact. Personal info; cleared by {@link
|
||||
* Builder#wipeOut}.
|
||||
*/
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "name", column = @Column(name = "addr_i18n_name")),
|
||||
@AttributeOverride(name = "org", column = @Column(name = "addr_i18n_org")),
|
||||
@AttributeOverride(name = "type", column = @Column(name = "addr_i18n_type")),
|
||||
@AttributeOverride(
|
||||
name = "address.streetLine1",
|
||||
column = @Column(name = "addr_i18n_street_line1")),
|
||||
@AttributeOverride(
|
||||
name = "address.streetLine2",
|
||||
column = @Column(name = "addr_i18n_street_line2")),
|
||||
@AttributeOverride(
|
||||
name = "address.streetLine3",
|
||||
column = @Column(name = "addr_i18n_street_line3")),
|
||||
@AttributeOverride(name = "address.city", column = @Column(name = "addr_i18n_city")),
|
||||
@AttributeOverride(name = "address.state", column = @Column(name = "addr_i18n_state")),
|
||||
@AttributeOverride(name = "address.zip", column = @Column(name = "addr_i18n_zip")),
|
||||
@AttributeOverride(
|
||||
name = "address.countryCode",
|
||||
column = @Column(name = "addr_i18n_country_code"))
|
||||
})
|
||||
PostalInfo internationalizedPostalInfo;
|
||||
|
||||
/**
|
||||
@@ -80,10 +137,20 @@ public class ContactResource extends EppResource implements
|
||||
|
||||
/** Contact’s voice number. Personal info; cleared by {@link Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "phoneNumber", column = @Column(name = "voice_phone_number")),
|
||||
@AttributeOverride(name = "extension", column = @Column(name = "voice_phone_extension")),
|
||||
})
|
||||
ContactPhoneNumber voice;
|
||||
|
||||
/** Contact’s fax number. Personal info; cleared by {@link Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "phoneNumber", column = @Column(name = "fax_phone_number")),
|
||||
@AttributeOverride(name = "extension", column = @Column(name = "fax_phone_extension")),
|
||||
})
|
||||
ContactPhoneNumber fax;
|
||||
|
||||
/** Contact’s email address. Personal info; cleared by {@link Builder#wipeOut}. */
|
||||
@@ -91,10 +158,16 @@ public class ContactResource extends EppResource implements
|
||||
String email;
|
||||
|
||||
/** Authorization info (aka transfer secret) of the contact. */
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "pw.value", column = @Column(name = "auth_info_value")),
|
||||
@AttributeOverride(name = "pw.repoId", column = @Column(name = "auth_info_repo_id")),
|
||||
})
|
||||
ContactAuthInfo authInfo;
|
||||
|
||||
/** Data about any pending or past transfers on this contact. */
|
||||
TransferData transferData;
|
||||
// TODO(b/153363295): Figure out how to persist transfer data
|
||||
@Transient TransferData transferData;
|
||||
|
||||
/**
|
||||
* The time that this resource was last transferred.
|
||||
@@ -107,6 +180,16 @@ public class ContactResource extends EppResource implements
|
||||
// the wipeOut() function, so that data is not kept around for deleted contacts.
|
||||
|
||||
/** Disclosure policy. */
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "name", column = @Column(name = "disclose_types_name")),
|
||||
@AttributeOverride(name = "org", column = @Column(name = "disclose_types_org")),
|
||||
@AttributeOverride(name = "addr", column = @Column(name = "disclose_types_addr")),
|
||||
@AttributeOverride(name = "flag", column = @Column(name = "disclose_mode_flag")),
|
||||
@AttributeOverride(name = "voice.marked", column = @Column(name = "disclose_show_voice")),
|
||||
@AttributeOverride(name = "fax.marked", column = @Column(name = "disclose_show_fax")),
|
||||
@AttributeOverride(name = "email.marked", column = @Column(name = "disclose_show_email"))
|
||||
})
|
||||
Disclose disclose;
|
||||
|
||||
public String getContactId() {
|
||||
|
||||
@@ -22,11 +22,14 @@ import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.eppcommon.PresenceMarker;
|
||||
import java.util.List;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/** The "discloseType" from {@link "http://tools.ietf.org/html/rfc5733"}. */
|
||||
@Embed
|
||||
@Embeddable
|
||||
@XmlType(propOrder = {"name", "org", "addr", "voice", "fax", "email"})
|
||||
public class Disclose extends ImmutableObject {
|
||||
|
||||
@@ -36,11 +39,11 @@ public class Disclose extends ImmutableObject {
|
||||
|
||||
List<PostalInfoChoice> addr;
|
||||
|
||||
PresenceMarker voice;
|
||||
@Embedded PresenceMarker voice;
|
||||
|
||||
PresenceMarker fax;
|
||||
@Embedded PresenceMarker fax;
|
||||
|
||||
PresenceMarker email;
|
||||
@Embedded PresenceMarker email;
|
||||
|
||||
@XmlAttribute
|
||||
Boolean flag;
|
||||
|
||||
@@ -21,6 +21,9 @@ import google.registry.model.Buildable;
|
||||
import google.registry.model.Buildable.Overlayable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlEnumValue;
|
||||
@@ -29,10 +32,11 @@ import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
/**
|
||||
* Implementation of both "postalInfoType" and "chgPostalInfoType" from
|
||||
* {@link "http://tools.ietf.org/html/rfc5733"}.
|
||||
* Implementation of both "postalInfoType" and "chgPostalInfoType" from {@link
|
||||
* "http://tools.ietf.org/html/rfc5733"}.
|
||||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
@XmlType(propOrder = {"name", "org", "address", "type"})
|
||||
public class PostalInfo extends ImmutableObject implements Overlayable<PostalInfo> {
|
||||
|
||||
@@ -53,6 +57,7 @@ public class PostalInfo extends ImmutableObject implements Overlayable<PostalInf
|
||||
@XmlElement(name = "addr")
|
||||
ContactAddress address;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@XmlAttribute
|
||||
Type type;
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ import google.registry.model.registry.Registry;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import google.registry.util.CollectionUtils;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
@@ -78,6 +79,7 @@ import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Interval;
|
||||
@@ -105,7 +107,7 @@ import org.joda.time.Interval;
|
||||
})
|
||||
@ExternalMessagingName("domain")
|
||||
public class DomainBase extends EppResource
|
||||
implements ForeignKeyedEppResource, ResourceWithTransferData {
|
||||
implements ForeignKeyedEppResource, ResourceWithTransferData, DatastoreAndSqlEntity {
|
||||
|
||||
/** The max number of years that a domain can be registered for, as set by ICANN policy. */
|
||||
public static final int MAX_REGISTRATION_YEARS = 10;
|
||||
@@ -141,7 +143,10 @@ public class DomainBase extends EppResource
|
||||
*/
|
||||
@Index @ElementCollection @Transient Set<Key<HostResource>> nsHosts;
|
||||
|
||||
@Ignore @Transient Set<VKey<HostResource>> nsHostVKeys;
|
||||
@Ignore
|
||||
@ElementCollection
|
||||
@JoinTable(name = "DomainHost")
|
||||
Set<VKey<HostResource>> nsHostVKeys;
|
||||
|
||||
/**
|
||||
* The union of the contacts visible via {@link #getContacts} and {@link #getRegistrant}.
|
||||
|
||||
@@ -18,6 +18,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
@@ -31,17 +33,21 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
* "e164Type" type from {@link "http://tools.ietf.org/html/draft-lozano-tmch-smd"}.
|
||||
*
|
||||
* <blockquote>
|
||||
*
|
||||
* <p>"Contact telephone number structure is derived from structures defined in [ITU.E164.2005].
|
||||
* Telephone numbers described in this mapping are character strings that MUST begin with a plus
|
||||
* sign ("+", ASCII value 0x002B), followed by a country code defined in [ITU.E164.2005], followed
|
||||
* by a dot (".", ASCII value 0x002E), followed by a sequence of digits representing the telephone
|
||||
* number. An optional "x" attribute is provided to note telephone extension information."
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* @see google.registry.model.contact.ContactPhoneNumber
|
||||
* @see google.registry.model.mark.MarkPhoneNumber
|
||||
*/
|
||||
@XmlTransient
|
||||
@Embeddable
|
||||
@MappedSuperclass
|
||||
public class PhoneNumber extends ImmutableObject {
|
||||
|
||||
@XmlValue
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.model.eppcommon;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
/**
|
||||
@@ -26,6 +27,7 @@ import javax.xml.bind.annotation.XmlTransient;
|
||||
* {@code <foo></foo>}, and will unmarshal always to {@code <foo/>}.
|
||||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
public class PresenceMarker extends ImmutableObject implements Serializable {
|
||||
@XmlTransient
|
||||
boolean marked = true;
|
||||
|
||||
@@ -34,23 +34,27 @@ import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithStringVKey;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.ElementCollection;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* A persistable Host resource including mutable and non-mutable fields.
|
||||
*
|
||||
* <p>A host's {@link TransferData} is stored on the superordinate domain. Non-subordinate hosts
|
||||
* <p>A host's {@link TransferData} is stored on the superordinate domain. Non-subordinate hosts
|
||||
* don't carry a full set of TransferData; all they have is lastTransferTime.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc5732">RFC 5732</a>
|
||||
*/
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@ExternalMessagingName("host")
|
||||
@WithStringVKey
|
||||
public class HostResource extends EppResource implements ForeignKeyedEppResource {
|
||||
|
||||
/**
|
||||
@@ -64,8 +68,7 @@ public class HostResource extends EppResource implements ForeignKeyedEppResource
|
||||
String fullyQualifiedHostName;
|
||||
|
||||
/** IP Addresses for this host. Can be null if this is an external host. */
|
||||
@Index
|
||||
Set<InetAddress> inetAddresses;
|
||||
@Index @ElementCollection Set<InetAddress> inetAddresses;
|
||||
|
||||
/** The superordinate domain of this host, or null if this is an external host. */
|
||||
@Index
|
||||
|
||||
@@ -151,11 +151,14 @@ public class ObjectifyService {
|
||||
String kind = Key.getKind(clazz);
|
||||
boolean registered = factory().getMetadata(kind) != null;
|
||||
if (clazz.isAnnotationPresent(Entity.class)) {
|
||||
// Objectify silently ignores re-registrations for a given kind string, even if the classes
|
||||
// being registered are distinct. Throw an exception if that would happen here.
|
||||
checkState(!registered,
|
||||
// Objectify silently replaces current registration for a given kind string when a different
|
||||
// class is registered again for this kind. For simplicity's sake, throw an exception on any
|
||||
// re-registration.
|
||||
checkState(
|
||||
!registered,
|
||||
"Kind '%s' already registered, cannot register new @Entity %s",
|
||||
kind, clazz.getCanonicalName());
|
||||
kind,
|
||||
clazz.getCanonicalName());
|
||||
} else if (clazz.isAnnotationPresent(EntitySubclass.class)) {
|
||||
// Ensure that any @EntitySubclass classes have also had their parent @Entity registered,
|
||||
// which Objectify nominally requires but doesn't enforce in 4.x (though it may in 5.x).
|
||||
|
||||
@@ -73,6 +73,7 @@ import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.registrar.Registrar.BillingAccountEntry.CurrencyMapper;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import google.registry.util.CidrAddressBlock;
|
||||
import java.security.cert.CertificateParsingException;
|
||||
import java.util.Comparator;
|
||||
@@ -107,11 +108,12 @@ import org.joda.time.DateTime;
|
||||
columnList = "ianaIdentifier",
|
||||
name = "registrar_iana_identifier_idx"),
|
||||
})
|
||||
public class Registrar extends ImmutableObject implements Buildable, Jsonifiable {
|
||||
public class Registrar extends ImmutableObject
|
||||
implements Buildable, Jsonifiable, DatastoreAndSqlEntity {
|
||||
|
||||
/** Represents the type of a registrar entity. */
|
||||
public enum Type {
|
||||
/** A real-world, third-party registrar. Should have non-null IANA and billing IDs. */
|
||||
/** A real-world, third-party registrar. Should have non-null IANA and billing IDs. */
|
||||
REAL(Objects::nonNull),
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.model.server;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.isAtOrAfter;
|
||||
|
||||
@@ -29,7 +28,6 @@ import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.schema.server.LockDao;
|
||||
import google.registry.util.RequestStatusChecker;
|
||||
import google.registry.util.RequestStatusCheckerImpl;
|
||||
import java.io.Serializable;
|
||||
@@ -197,22 +195,6 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
|
||||
// Checking if an unexpired lock still exists - if so, the lock can't be acquired.
|
||||
Lock lock = ofy().load().type(Lock.class).id(lockId).now();
|
||||
try {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
Optional<google.registry.schema.server.Lock> cloudSqlLockOptional;
|
||||
if (tld == null) {
|
||||
cloudSqlLockOptional = LockDao.load(resourceName);
|
||||
} else {
|
||||
cloudSqlLockOptional = LockDao.load(resourceName, tld);
|
||||
}
|
||||
LockDao.compare(Optional.ofNullable(lock), cloudSqlLockOptional);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.atSevere().withCause(e).log(
|
||||
"Issue loading and comparing lock from Cloud SQL");
|
||||
}
|
||||
if (lock != null) {
|
||||
logger.atInfo().log(
|
||||
"Loaded existing lock: %s for request: %s", lock.lockId, lock.requestLogId);
|
||||
@@ -237,35 +219,6 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
// don't need to be backed up.
|
||||
ofy().saveWithoutBackup().entity(newLock);
|
||||
|
||||
// create and save the lock to Cloud SQL
|
||||
try {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
google.registry.schema.server.Lock cloudSqlLock;
|
||||
if (tld == null) {
|
||||
cloudSqlLock =
|
||||
google.registry.schema.server.Lock.createGlobal(
|
||||
resourceName,
|
||||
requestStatusChecker.getLogId(),
|
||||
now,
|
||||
leaseLength);
|
||||
} else {
|
||||
cloudSqlLock =
|
||||
google.registry.schema.server.Lock.create(
|
||||
resourceName,
|
||||
tld,
|
||||
requestStatusChecker.getLogId(),
|
||||
now,
|
||||
leaseLength);
|
||||
}
|
||||
LockDao.save(cloudSqlLock);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.atSevere().withCause(e).log(
|
||||
"Error saving lock to Cloud SQL: %s", newLock);
|
||||
}
|
||||
|
||||
return AcquireResult.create(now, lock, newLock, lockState);
|
||||
});
|
||||
|
||||
@@ -284,44 +237,12 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
// this can happen if release() is called around the expiration time and the lock
|
||||
// expires underneath us.
|
||||
Lock loadedLock = ofy().load().type(Lock.class).id(lockId).now();
|
||||
try {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
Optional<google.registry.schema.server.Lock> cloudSqlLockOptional;
|
||||
if (tld == null) {
|
||||
cloudSqlLockOptional = LockDao.load(resourceName);
|
||||
} else {
|
||||
cloudSqlLockOptional = LockDao.load(resourceName, tld);
|
||||
}
|
||||
LockDao.compare(Optional.ofNullable(loadedLock), cloudSqlLockOptional);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.atSevere().withCause(e).log(
|
||||
"Issue loading and comparing lock from Cloud SQL");
|
||||
}
|
||||
if (Lock.this.equals(loadedLock)) {
|
||||
// Use noBackupOfy() so that we don't create a commit log entry for deleting the
|
||||
// lock.
|
||||
logger.atInfo().log("Deleting lock: %s", lockId);
|
||||
ofy().deleteWithoutBackup().entity(Lock.this);
|
||||
|
||||
// Remove the lock from Cloud SQL
|
||||
try {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
if (tld == null) {
|
||||
LockDao.delete(resourceName);
|
||||
} else {
|
||||
LockDao.delete(resourceName, tld);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.atSevere().withCause(e).log(
|
||||
"Error deleting lock from Cloud SQL: %s", loadedLock);
|
||||
}
|
||||
|
||||
lockMetrics.recordRelease(
|
||||
resourceName, tld, new Duration(acquiredTime, tm().getTransactionTime()));
|
||||
} else {
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
@@ -31,6 +32,7 @@ import javax.persistence.PostUpdate;
|
||||
import javax.persistence.PrePersist;
|
||||
import javax.persistence.PreRemove;
|
||||
import javax.persistence.PreUpdate;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/**
|
||||
* A listener class to invoke entity callbacks in cases where Hibernate doesn't invoke the callback
|
||||
@@ -167,10 +169,12 @@ public class EntityCallbacksListener {
|
||||
|
||||
private Stream<Object> findEmbeddedProperties(Object object, Class<?> clazz) {
|
||||
return Arrays.stream(clazz.getDeclaredFields())
|
||||
.filter(field -> !field.isAnnotationPresent(Transient.class))
|
||||
.filter(
|
||||
field ->
|
||||
field.isAnnotationPresent(Embedded.class)
|
||||
|| field.getType().isAnnotationPresent(Embeddable.class))
|
||||
.filter(field -> !Modifier.isStatic(field.getModifiers()))
|
||||
.map(field -> getFieldObject(field, object))
|
||||
.filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ package google.registry.persistence;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.config.RegistryConfig.getHibernateConnectionIsolation;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariConnectionTimeout;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariIdleTimeout;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariMaximumPoolSize;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariMinimumIdle;
|
||||
import static google.registry.config.RegistryConfig.getHibernateLogSqlQueries;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
@@ -50,10 +48,7 @@ public class PersistenceModule {
|
||||
// This name must be the same as the one defined in persistence.xml.
|
||||
public static final String PERSISTENCE_UNIT_NAME = "nomulus";
|
||||
public static final String HIKARI_CONNECTION_TIMEOUT = "hibernate.hikari.connectionTimeout";
|
||||
public static final String HIKARI_MINIMUM_IDLE = "hibernate.hikari.minimumIdle";
|
||||
public static final String HIKARI_MAXIMUM_POOL_SIZE = "hibernate.hikari.maximumPoolSize";
|
||||
public static final String HIKARI_IDLE_TIMEOUT = "hibernate.hikari.idleTimeout";
|
||||
|
||||
public static final String HIKARI_DS_SOCKET_FACTORY = "hibernate.hikari.dataSource.socketFactory";
|
||||
public static final String HIKARI_DS_CLOUD_SQL_INSTANCE =
|
||||
"hibernate.hikari.dataSource.cloudSqlInstance";
|
||||
@@ -79,9 +74,7 @@ public class PersistenceModule {
|
||||
properties.put(Environment.ISOLATION, getHibernateConnectionIsolation());
|
||||
properties.put(Environment.SHOW_SQL, getHibernateLogSqlQueries());
|
||||
properties.put(HIKARI_CONNECTION_TIMEOUT, getHibernateHikariConnectionTimeout());
|
||||
properties.put(HIKARI_MINIMUM_IDLE, getHibernateHikariMinimumIdle());
|
||||
properties.put(HIKARI_MAXIMUM_POOL_SIZE, getHibernateHikariMaximumPoolSize());
|
||||
properties.put(HIKARI_IDLE_TIMEOUT, getHibernateHikariIdleTimeout());
|
||||
properties.put(Environment.DIALECT, NomulusPostgreSQLDialect.class.getName());
|
||||
return properties.build();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.persistence;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import java.util.Optional;
|
||||
@@ -41,20 +42,31 @@ public class VKey<T> extends ImmutableObject {
|
||||
this.primaryKey = primaryKey;
|
||||
}
|
||||
|
||||
public static <T> VKey<T> createSql(Class<? extends T> kind, Object primaryKey) {
|
||||
return new VKey(kind, null, primaryKey);
|
||||
/** Creates a {@link VKey} which only contains the sql primary key. */
|
||||
public static <T> VKey<T> createSql(Class<? extends T> kind, Object sqlKey) {
|
||||
checkArgumentNotNull(kind, "kind must not be null");
|
||||
checkArgumentNotNull(sqlKey, "sqlKey must not be null");
|
||||
return new VKey(kind, null, sqlKey);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} which only contains the ofy primary key. */
|
||||
public static <T> VKey<T> createOfy(
|
||||
Class<? extends T> kind, com.googlecode.objectify.Key<T> ofyKey) {
|
||||
Class<? extends T> kind, com.googlecode.objectify.Key<? extends T> ofyKey) {
|
||||
checkArgumentNotNull(kind, "kind must not be null");
|
||||
checkArgumentNotNull(ofyKey, "ofyKey must not be null");
|
||||
return new VKey(kind, ofyKey, null);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} which only contains both sql and ofy primary key. */
|
||||
public static <T> VKey<T> create(
|
||||
Class<? extends T> kind, Object primaryKey, com.googlecode.objectify.Key ofyKey) {
|
||||
return new VKey(kind, ofyKey, primaryKey);
|
||||
Class<? extends T> kind, Object sqlKey, com.googlecode.objectify.Key ofyKey) {
|
||||
checkArgumentNotNull(kind, "kind must not be null");
|
||||
checkArgumentNotNull(sqlKey, "sqlKey must not be null");
|
||||
checkArgumentNotNull(ofyKey, "ofyKey must not be null");
|
||||
return new VKey(kind, ofyKey, sqlKey);
|
||||
}
|
||||
|
||||
/** Returns the type of the entity. */
|
||||
public Class<? extends T> getKind() {
|
||||
return this.kind;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* Annotation for {@link Entity} which id is long type and needs an {@link AttributeConverter} for
|
||||
* its VKey.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface WithLongVKey {
|
||||
/**
|
||||
* Sets the suffix of the class name for the {@link AttributeConverter} generated by
|
||||
* LongVKeyProcessor. If not set, the suffix will be the type name of the VKey. Note that the
|
||||
* class name will be "VKeyConverter_" concatenated with the suffix.
|
||||
*/
|
||||
String classNameSuffix() default "";
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.persistence;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* Annotation for {@link Entity} which id is string type and needs an {@link AttributeConverter} for
|
||||
* its VKey.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface WithStringVKey {
|
||||
/**
|
||||
* Sets the suffix of the class name for the {@link AttributeConverter} generated by
|
||||
* StringVKeyProcessor. If not set, the suffix will be the type name of the VKey. Note that the
|
||||
* class name will be "VKeyConverter_" concatenated with the suffix.
|
||||
*/
|
||||
String classNameSuffix() default "";
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.persistence.converter;
|
||||
|
||||
import google.registry.model.contact.Disclose.PostalInfoChoice;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import java.util.List;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
|
||||
/** JPA {@link AttributeConverter} for storing/retrieving {@link List < PostalInfoChoice >}. */
|
||||
@Converter(autoApply = true)
|
||||
public class PostalInfoChoiceListConverter extends StringListConverterBase<PostalInfoChoice> {
|
||||
|
||||
@Override
|
||||
String toString(PostalInfoChoice element) {
|
||||
return element.getType().name();
|
||||
}
|
||||
|
||||
@Override
|
||||
PostalInfoChoice fromString(String value) {
|
||||
return PostalInfoChoice.create(PostalInfo.Type.valueOf(value));
|
||||
}
|
||||
}
|
||||
@@ -18,24 +18,20 @@ import google.registry.persistence.VKey;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* Converts VKey to a string column.
|
||||
*/
|
||||
public abstract class VKeyConverter<T> implements AttributeConverter<VKey<T>, String> {
|
||||
/** Converts VKey to a string column. */
|
||||
public abstract class VKeyConverter<T, C> implements AttributeConverter<VKey<? extends T>, C> {
|
||||
@Override
|
||||
@Nullable
|
||||
public String convertToDatabaseColumn(@Nullable VKey<T> attribute) {
|
||||
return attribute == null ? null : (String) attribute.getSqlKey();
|
||||
public C convertToDatabaseColumn(@Nullable VKey<? extends T> attribute) {
|
||||
return attribute == null ? null : (C) attribute.getSqlKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public VKey<T> convertToEntityAttribute(@Nullable String dbData) {
|
||||
public VKey<? extends T> convertToEntityAttribute(@Nullable C dbData) {
|
||||
return dbData == null ? null : VKey.createSql(getAttributeClass(), dbData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class of the attribute.
|
||||
*/
|
||||
/** Returns the class of the attribute. */
|
||||
protected abstract Class<T> getAttributeClass();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.schema.replay;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/** An entity that has the same Java object representation in SQL and Datastore. */
|
||||
public interface DatastoreAndSqlEntity extends DatastoreEntity, SqlEntity {
|
||||
|
||||
@Override
|
||||
default ImmutableList<DatastoreEntity> toDatastoreEntities() {
|
||||
return ImmutableList.of(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
default ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.schema.replay;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* An object that can be stored in Datastore and serialized using Objectify's {@link
|
||||
* com.googlecode.objectify.cmd.Saver#toEntity(Object)} code.
|
||||
*
|
||||
* <p>This is used when replaying {@link google.registry.model.ofy.CommitLogManifest}s to import
|
||||
* transactions and data into the secondary SQL store during the first, Datastore-primary, phase of
|
||||
* the migration.
|
||||
*/
|
||||
public interface DatastoreEntity {
|
||||
|
||||
ImmutableList<SqlEntity> toSqlEntities();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.schema.replay;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* An object that can be stored in Cloud SQL using {@link
|
||||
* javax.persistence.EntityManager#persist(Object)}
|
||||
*
|
||||
* <p>This will be used when replaying SQL transactions into Datastore, during the second,
|
||||
* SQL-primary, phase of the migration from Datastore to SQL.
|
||||
*/
|
||||
public interface SqlEntity {
|
||||
|
||||
ImmutableList<DatastoreEntity> toDatastoreEntities();
|
||||
}
|
||||
@@ -153,8 +153,8 @@ public final class DomainLockUtils {
|
||||
/**
|
||||
* Creates and applies a lock in one step.
|
||||
*
|
||||
* <p>This should only be used for admin actions, e.g. Nomulus tool commands or relocks.
|
||||
* Note: in the case of relocks, isAdmin is determined by the previous lock.
|
||||
* <p>This should only be used for admin actions, e.g. Nomulus tool commands or relocks. Note: in
|
||||
* the case of relocks, isAdmin is determined by the previous lock.
|
||||
*/
|
||||
public RegistryLock administrativelyApplyLock(
|
||||
String domainName, String registrarId, @Nullable String registrarPocId, boolean isAdmin) {
|
||||
@@ -175,7 +175,7 @@ public final class DomainLockUtils {
|
||||
|
||||
/**
|
||||
* Creates and applies an unlock in one step.
|
||||
*
|
||||
*
|
||||
* <p>This should only be used for admin actions, e.g. Nomulus tool commands.
|
||||
*/
|
||||
public RegistryLock administrativelyApplyUnlock(
|
||||
|
||||
@@ -132,10 +132,8 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
||||
jcommander.parse(args);
|
||||
} catch (ParameterException e) {
|
||||
// If we failed to fully parse the command but at least found a valid command name, show only
|
||||
// the usage for that command. Otherwise, show full usage. Either way, rethrow the error.
|
||||
if (jcommander.getParsedCommand() == null) {
|
||||
jcommander.usage();
|
||||
} else {
|
||||
// the usage for that command.
|
||||
if (jcommander.getParsedCommand() != null) {
|
||||
jcommander.usage(jcommander.getParsedCommand());
|
||||
}
|
||||
// Don't rethrow if we said: nomulus command --help
|
||||
@@ -144,8 +142,13 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (showAllCommands) {
|
||||
String parsedCommand = jcommander.getParsedCommand();
|
||||
// Show the list of all commands either if requested or if no subcommand name was specified
|
||||
// (which does not throw a ParameterException parse error above).
|
||||
if (showAllCommands || parsedCommand == null) {
|
||||
if (parsedCommand == null) {
|
||||
System.out.println("The list of available subcommands is:");
|
||||
}
|
||||
commands.keySet().forEach(System.out::println);
|
||||
return;
|
||||
}
|
||||
@@ -161,8 +164,7 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
||||
// retrieving the first (and, by virtue of our usage, only) object from it.
|
||||
Command command =
|
||||
(Command)
|
||||
Iterables.getOnlyElement(
|
||||
jcommander.getCommands().get(jcommander.getParsedCommand()).getObjects());
|
||||
Iterables.getOnlyElement(jcommander.getCommands().get(parsedCommand).getObjects());
|
||||
loggingParams.configureLogging(); // Must be called after parameters are parsed.
|
||||
|
||||
try {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.util.CollectionUtils.findDuplicates;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
|
||||
@@ -37,6 +38,13 @@ import org.joda.time.format.DateTimeFormatter;
|
||||
@Parameters(separators = " =", commandDescription = "Renew domain(s) via EPP.")
|
||||
final class RenewDomainCommand extends MutatingEppToolCommand {
|
||||
|
||||
@Parameter(
|
||||
names = {"-c", "--client"},
|
||||
description =
|
||||
"The registrar to execute as and bill the renewal to; otherwise each domain's sponsoring"
|
||||
+ " registrar. Renewals by non-sponsoring registrars require --superuser as well.")
|
||||
String clientId;
|
||||
|
||||
@Parameter(
|
||||
names = {"-p", "--period"},
|
||||
description = "Number of years to renew the registration for (defaults to 1).")
|
||||
@@ -63,7 +71,7 @@ final class RenewDomainCommand extends MutatingEppToolCommand {
|
||||
setSoyTemplate(RenewDomainSoyInfo.getInstance(), RenewDomainSoyInfo.RENEWDOMAIN);
|
||||
DomainBase domain = domainOptional.get();
|
||||
addSoyRecord(
|
||||
domain.getCurrentSponsorClientId(),
|
||||
isNullOrEmpty(clientId) ? domain.getCurrentSponsorClientId() : clientId,
|
||||
new SoyMapData(
|
||||
"domainName", domain.getFullyQualifiedDomainName(),
|
||||
"expirationDate", domain.getRegistrationExpirationTime().toString(DATE_FORMATTER),
|
||||
|
||||
@@ -186,9 +186,7 @@ public final class RegistrarFormFields {
|
||||
.build();
|
||||
|
||||
public static final FormField<String, String> REGISTRY_LOCK_EMAIL_ADDRESS_FIELD =
|
||||
FormFields.EMAIL
|
||||
.asBuilderNamed("registryLockEmailAddress")
|
||||
.build();
|
||||
FormFields.EMAIL.asBuilderNamed("registryLockEmailAddress").build();
|
||||
|
||||
public static final FormField<Boolean, Boolean> CONTACT_VISIBLE_IN_WHOIS_AS_ADMIN_FIELD =
|
||||
FormField.named("visibleInWhoisAsAdmin", Boolean.class)
|
||||
|
||||
@@ -391,7 +391,8 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
* @throws FormException if the checks fail.
|
||||
*/
|
||||
void checkContactRequirements(
|
||||
Set<RegistrarContact> existingContacts, Set<RegistrarContact> updatedContacts) {
|
||||
ImmutableSet<RegistrarContact> existingContacts,
|
||||
ImmutableSet<RegistrarContact> updatedContacts) {
|
||||
// Check that no two contacts use the same email address.
|
||||
Set<String> emails = new HashSet<>();
|
||||
for (RegistrarContact contact : updatedContacts) {
|
||||
@@ -435,7 +436,12 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
throw new ContactRequirementException(
|
||||
"An abuse contact visible in domain WHOIS query must be designated");
|
||||
}
|
||||
checkContactRegistryLockRequirements(existingContacts, updatedContacts);
|
||||
}
|
||||
|
||||
private static void checkContactRegistryLockRequirements(
|
||||
ImmutableSet<RegistrarContact> existingContacts,
|
||||
ImmutableSet<RegistrarContact> updatedContacts) {
|
||||
// Any contact(s) with new passwords must be allowed to set them
|
||||
for (RegistrarContact updatedContact : updatedContacts) {
|
||||
if (updatedContact.isRegistryLockAllowed()
|
||||
@@ -463,6 +469,31 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Any previously-existing contacts with registry lock enabled cannot be deleted
|
||||
existingContacts.stream()
|
||||
.filter(RegistrarContact::isRegistryLockAllowed)
|
||||
.forEach(
|
||||
contact -> {
|
||||
Optional<RegistrarContact> updatedContactOptional =
|
||||
updatedContacts.stream()
|
||||
.filter(
|
||||
updatedContact ->
|
||||
updatedContact.getEmailAddress().equals(contact.getEmailAddress()))
|
||||
.findFirst();
|
||||
if (!updatedContactOptional.isPresent()) {
|
||||
throw new FormException(
|
||||
String.format(
|
||||
"Cannot delete the contact %s that has registry lock enabled",
|
||||
contact.getEmailAddress()));
|
||||
}
|
||||
if (!updatedContactOptional.get().isRegistryLockAllowed()) {
|
||||
throw new FormException(
|
||||
String.format(
|
||||
"Cannot remove the ability to use registry lock on the contact %s",
|
||||
contact.getEmailAddress()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
* Move tests to another (sub)project. This is not a big problem, but feels unnatural.
|
||||
* Use Hibernate's ServiceRegistry for bootstrapping (not JPA-compliant)
|
||||
-->
|
||||
<class>google.registry.model.contact.ContactResource</class>
|
||||
<class>google.registry.model.domain.DomainBase</class>
|
||||
<class>google.registry.model.host.HostResource</class>
|
||||
<class>google.registry.model.registrar.Registrar</class>
|
||||
<class>google.registry.model.registrar.RegistrarContact</class>
|
||||
<class>google.registry.schema.domain.RegistryLock</class>
|
||||
@@ -40,6 +42,7 @@
|
||||
<class>google.registry.persistence.converter.CurrencyUnitConverter</class>
|
||||
<class>google.registry.persistence.converter.DateTimeConverter</class>
|
||||
<class>google.registry.persistence.converter.DurationConverter</class>
|
||||
<class>google.registry.persistence.converter.PostalInfoChoiceListConverter</class>
|
||||
<class>google.registry.persistence.converter.RegistrarPocSetConverter</class>
|
||||
<class>google.registry.persistence.converter.StatusValueSetConverter</class>
|
||||
<class>google.registry.persistence.converter.StringListConverter</class>
|
||||
@@ -47,6 +50,9 @@
|
||||
<class>google.registry.persistence.converter.UpdateAutoTimestampConverter</class>
|
||||
<class>google.registry.persistence.converter.ZonedDateTimeConverter</class>
|
||||
|
||||
<!-- Generated converters for VKey -->
|
||||
<class>google.registry.model.host.VKeyConverter_HostResource</class>
|
||||
|
||||
<!-- TODO(weiminyu): check out application-layer validation. -->
|
||||
<validation-mode>NONE</validation-mode>
|
||||
</persistence-unit>
|
||||
|
||||
@@ -145,6 +145,7 @@
|
||||
{param label: 'Email' /}
|
||||
{param namePrefix: $namePrefix /}
|
||||
{param name: 'emailAddress' /}
|
||||
{param disabled: not $readonly and $item['emailAddress'] != null /}
|
||||
{/call}
|
||||
{call registry.soy.forms.inputFieldRow data="all"}
|
||||
{param label: 'Phone' /}
|
||||
|
||||
@@ -64,8 +64,8 @@ public class DumpGoldenSchemaCommand extends PostgresqlCommand {
|
||||
if (result.getExitCode() != 0) {
|
||||
throw new RuntimeException(result.toString());
|
||||
}
|
||||
result = postgresContainer.execInContainer(
|
||||
"cp", CONTAINER_MOUNT_POINT_TMP, CONTAINER_MOUNT_POINT);
|
||||
result =
|
||||
postgresContainer.execInContainer("cp", CONTAINER_MOUNT_POINT_TMP, CONTAINER_MOUNT_POINT);
|
||||
if (result.getExitCode() != 0) {
|
||||
throw new RuntimeException(result.toString());
|
||||
}
|
||||
|
||||
@@ -50,7 +50,11 @@ import org.junit.runners.JUnit4;
|
||||
public class ExportCommitLogDiffActionTest {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||
public final AppEngineRule appEngine =
|
||||
AppEngineRule.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(TestObject.class)
|
||||
.build();
|
||||
|
||||
/** Local GCS service available for testing. */
|
||||
private final GcsService gcsService = GcsServiceFactory.createGcsService();
|
||||
|
||||
@@ -71,7 +71,11 @@ public class RestoreCommitLogsActionTest {
|
||||
final GcsService gcsService = createGcsService();
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||
public final AppEngineRule appEngine =
|
||||
AppEngineRule.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(TestObject.class)
|
||||
.build();
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
|
||||
@@ -153,6 +153,8 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
|
||||
doSuccessfulTest(
|
||||
responseFilename,
|
||||
renewalYears,
|
||||
"TheRegistrar",
|
||||
UserPrivileges.NORMAL,
|
||||
substitutions,
|
||||
Money.of(USD, 11).multipliedBy(renewalYears));
|
||||
}
|
||||
@@ -160,13 +162,16 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
|
||||
private void doSuccessfulTest(
|
||||
String responseFilename,
|
||||
int renewalYears,
|
||||
String renewalClientId,
|
||||
UserPrivileges userPrivileges,
|
||||
Map<String, String> substitutions,
|
||||
Money totalRenewCost)
|
||||
throws Exception {
|
||||
assertTransactionalFlow(true);
|
||||
DateTime currentExpiration = reloadResourceByForeignKey().getRegistrationExpirationTime();
|
||||
DateTime newExpiration = currentExpiration.plusYears(renewalYears);
|
||||
runFlowAssertResponse(loadFile(responseFilename, substitutions));
|
||||
runFlowAssertResponse(
|
||||
CommitMode.LIVE, userPrivileges, loadFile(responseFilename, substitutions));
|
||||
DomainBase domain = reloadResourceByForeignKey();
|
||||
HistoryEntry historyEntryDomainRenew =
|
||||
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RENEW);
|
||||
@@ -183,13 +188,13 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
|
||||
.and()
|
||||
.hasLastEppUpdateTime(clock.nowUtc())
|
||||
.and()
|
||||
.hasLastEppUpdateClientId("TheRegistrar");
|
||||
.hasLastEppUpdateClientId(renewalClientId);
|
||||
assertAboutHistoryEntries().that(historyEntryDomainRenew).hasPeriodYears(renewalYears);
|
||||
BillingEvent.OneTime renewBillingEvent =
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.RENEW)
|
||||
.setTargetId(getUniqueIdFromCommand())
|
||||
.setClientId("TheRegistrar")
|
||||
.setClientId(renewalClientId)
|
||||
.setCost(totalRenewCost)
|
||||
.setPeriodYears(renewalYears)
|
||||
.setEventTime(clock.nowUtc())
|
||||
@@ -233,7 +238,7 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.RENEW,
|
||||
clock.nowUtc().plus(Registry.get("tld").getRenewGracePeriodLength()),
|
||||
"TheRegistrar",
|
||||
renewalClientId,
|
||||
null),
|
||||
renewBillingEvent));
|
||||
}
|
||||
@@ -256,6 +261,19 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_recurringClientIdIsSame_whenSuperuserOverridesRenewal() throws Exception {
|
||||
persistDomain();
|
||||
setClientIdForFlow("NewRegistrar");
|
||||
doSuccessfulTest(
|
||||
"domain_renew_response.xml",
|
||||
5,
|
||||
"NewRegistrar",
|
||||
UserPrivileges.SUPERUSER,
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z"),
|
||||
Money.of(USD, 55));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_customLogicFee() throws Exception {
|
||||
// The "costly-renew" domain has an additional RENEW fee of 100 from custom logic on top of the
|
||||
@@ -269,7 +287,13 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
|
||||
"FEE", "111.00");
|
||||
setEppInput("domain_renew_fee.xml", customFeeMap);
|
||||
persistDomain();
|
||||
doSuccessfulTest("domain_renew_response_fee.xml", 1, customFeeMap, Money.of(USD, 111));
|
||||
doSuccessfulTest(
|
||||
"domain_renew_response_fee.xml",
|
||||
1,
|
||||
"TheRegistrar",
|
||||
UserPrivileges.NORMAL,
|
||||
customFeeMap,
|
||||
Money.of(USD, 111));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -687,7 +711,7 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
|
||||
|
||||
@Test
|
||||
public void testFailure_unauthorizedClient() throws Exception {
|
||||
sessionMetadata.setClientId("NewRegistrar");
|
||||
setClientIdForFlow("NewRegistrar");
|
||||
persistActiveDomain(getUniqueIdFromCommand());
|
||||
EppException thrown = assertThrows(ResourceNotOwnedException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
@@ -695,7 +719,7 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
|
||||
|
||||
@Test
|
||||
public void testSuccess_superuserUnauthorizedClient() throws Exception {
|
||||
sessionMetadata.setClientId("NewRegistrar");
|
||||
setClientIdForFlow("NewRegistrar");
|
||||
persistDomain();
|
||||
runFlowAssertResponse(
|
||||
CommitMode.LIVE,
|
||||
|
||||
@@ -19,12 +19,10 @@ import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.googlecode.objectify.ObjectifyService;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -35,19 +33,18 @@ import org.junit.runners.JUnit4;
|
||||
public class CreateAutoTimestampTest {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||
public final AppEngineRule appEngine =
|
||||
AppEngineRule.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(TestObject.class)
|
||||
.build();
|
||||
|
||||
/** Timestamped class. */
|
||||
@Entity
|
||||
@Entity(name = "CatTestEntity")
|
||||
public static class TestObject extends CrossTldSingleton {
|
||||
CreateAutoTimestamp createTime = CreateAutoTimestamp.create(null);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ObjectifyService.register(TestObject.class);
|
||||
}
|
||||
|
||||
private TestObject reload() {
|
||||
return ofy().load().entity(new TestObject()).now();
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.ObjectifyService;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
@@ -39,7 +38,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -50,12 +48,11 @@ import org.junit.runners.JUnit4;
|
||||
public class ImmutableObjectTest {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
@Before
|
||||
public void register() {
|
||||
ObjectifyService.register(ValueObject.class);
|
||||
}
|
||||
public final AppEngineRule appEngine =
|
||||
AppEngineRule.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(ValueObject.class)
|
||||
.build();
|
||||
|
||||
/** Simple subclass of ImmutableObject. */
|
||||
public static class SimpleObject extends ImmutableObject {
|
||||
|
||||
@@ -19,12 +19,10 @@ import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.googlecode.objectify.ObjectifyService;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -35,19 +33,18 @@ import org.junit.runners.JUnit4;
|
||||
public class UpdateAutoTimestampTest {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||
public final AppEngineRule appEngine =
|
||||
AppEngineRule.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(TestObject.class)
|
||||
.build();
|
||||
|
||||
/** Timestamped class. */
|
||||
@Entity
|
||||
@Entity(name = "UatTestEntity")
|
||||
public static class TestObject extends CrossTldSingleton {
|
||||
UpdateAutoTimestamp updateTime = UpdateAutoTimestamp.create(null);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ObjectifyService.register(TestObject.class);
|
||||
}
|
||||
|
||||
private TestObject reload() {
|
||||
return ofy().load().entity(new TestObject()).now();
|
||||
}
|
||||
|
||||
@@ -17,10 +17,13 @@ package google.registry.model.contact;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
||||
import static google.registry.testing.DatastoreHelper.cloneAndSetAutoTimestamps;
|
||||
import static google.registry.testing.DatastoreHelper.createTld;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.SqlHelper.assertThrowForeignKeyViolation;
|
||||
import static google.registry.testing.SqlHelper.saveRegistrar;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
@@ -37,87 +40,119 @@ import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import google.registry.persistence.VKey;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactResource}. */
|
||||
public class ContactResourceTest extends EntityTestCase {
|
||||
ContactResource originalContact;
|
||||
ContactResource contactResource;
|
||||
|
||||
@Before
|
||||
public ContactResourceTest() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
createTld("foobar");
|
||||
originalContact =
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id")
|
||||
.setRepoId("1-FOOBAR")
|
||||
.setCreationClientId("registrar1")
|
||||
.setLastEppUpdateTime(fakeClock.nowUtc())
|
||||
.setLastEppUpdateClientId("registrar2")
|
||||
.setLastTransferTime(fakeClock.nowUtc())
|
||||
.setPersistedCurrentSponsorClientId("registrar3")
|
||||
.setLocalizedPostalInfo(
|
||||
new PostalInfo.Builder()
|
||||
.setType(Type.LOCALIZED)
|
||||
.setAddress(
|
||||
new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
|
||||
.setCity("New York")
|
||||
.setState("NY")
|
||||
.setZip("10011")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.setInternationalizedPostalInfo(
|
||||
new PostalInfo.Builder()
|
||||
.setType(Type.INTERNATIONALIZED)
|
||||
.setAddress(
|
||||
new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
|
||||
.setCity("New York")
|
||||
.setState("NY")
|
||||
.setZip("10011")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.setVoiceNumber(new ContactPhoneNumber.Builder().setPhoneNumber("867-5309").build())
|
||||
.setFaxNumber(
|
||||
new ContactPhoneNumber.Builder()
|
||||
.setPhoneNumber("867-5309")
|
||||
.setExtension("1000")
|
||||
.build())
|
||||
.setEmailAddress("jenny@example.com")
|
||||
.setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("passw0rd")))
|
||||
.setDisclose(
|
||||
new Disclose.Builder()
|
||||
.setVoice(new PresenceMarker())
|
||||
.setEmail(new PresenceMarker())
|
||||
.setFax(new PresenceMarker())
|
||||
.setFlag(true)
|
||||
.setAddrs(ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
|
||||
.setNames(ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
|
||||
.setOrgs(ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
|
||||
.build())
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.OK))
|
||||
.setTransferData(
|
||||
new TransferData.Builder()
|
||||
.setGainingClientId("gaining")
|
||||
.setLosingClientId("losing")
|
||||
.setPendingTransferExpirationTime(fakeClock.nowUtc())
|
||||
.setServerApproveEntities(
|
||||
ImmutableSet.of(Key.create(BillingEvent.OneTime.class, 1)))
|
||||
.setTransferRequestTime(fakeClock.nowUtc())
|
||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||
.setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
|
||||
.build())
|
||||
.build();
|
||||
// Set up a new persisted ContactResource entity.
|
||||
contactResource =
|
||||
persistResource(
|
||||
cloneAndSetAutoTimestamps(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id")
|
||||
.setRepoId("1-FOOBAR")
|
||||
.setCreationClientId("a registrar")
|
||||
.setLastEppUpdateTime(fakeClock.nowUtc())
|
||||
.setLastEppUpdateClientId("another registrar")
|
||||
.setLastTransferTime(fakeClock.nowUtc())
|
||||
.setPersistedCurrentSponsorClientId("a third registrar")
|
||||
.setLocalizedPostalInfo(
|
||||
new PostalInfo.Builder()
|
||||
.setType(Type.LOCALIZED)
|
||||
.setAddress(
|
||||
new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
|
||||
.setCity("New York")
|
||||
.setState("NY")
|
||||
.setZip("10011")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.setInternationalizedPostalInfo(
|
||||
new PostalInfo.Builder()
|
||||
.setType(Type.INTERNATIONALIZED)
|
||||
.setAddress(
|
||||
new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
|
||||
.setCity("New York")
|
||||
.setState("NY")
|
||||
.setZip("10011")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.setVoiceNumber(
|
||||
new ContactPhoneNumber.Builder().setPhoneNumber("867-5309").build())
|
||||
.setFaxNumber(
|
||||
new ContactPhoneNumber.Builder()
|
||||
.setPhoneNumber("867-5309")
|
||||
.setExtension("1000")
|
||||
.build())
|
||||
.setEmailAddress("jenny@example.com")
|
||||
.setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("passw0rd")))
|
||||
.setDisclose(
|
||||
new Disclose.Builder()
|
||||
.setVoice(new PresenceMarker())
|
||||
.setEmail(new PresenceMarker())
|
||||
.setFax(new PresenceMarker())
|
||||
.setFlag(true)
|
||||
.setAddrs(
|
||||
ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
|
||||
.setNames(
|
||||
ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
|
||||
.setOrgs(
|
||||
ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
|
||||
.build())
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.OK))
|
||||
.setTransferData(
|
||||
new TransferData.Builder()
|
||||
.setGainingClientId("gaining")
|
||||
.setLosingClientId("losing")
|
||||
.setPendingTransferExpirationTime(fakeClock.nowUtc())
|
||||
.setServerApproveEntities(
|
||||
ImmutableSet.of(Key.create(BillingEvent.OneTime.class, 1)))
|
||||
.setTransferRequestTime(fakeClock.nowUtc())
|
||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||
.setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
|
||||
.build())
|
||||
.build()));
|
||||
contactResource = persistResource(cloneAndSetAutoTimestamps(originalContact));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloudSqlPersistence_failWhenViolateForeignKeyConstraint() {
|
||||
assertThrowForeignKeyViolation(() -> jpaTm().transact(() -> jpaTm().saveNew(originalContact)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloudSqlPersistence_succeed() {
|
||||
saveRegistrar("registrar1");
|
||||
saveRegistrar("registrar2");
|
||||
saveRegistrar("registrar3");
|
||||
jpaTm().transact(() -> jpaTm().saveNew(originalContact));
|
||||
ContactResource persisted =
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.load(VKey.createSql(ContactResource.class, originalContact.getRepoId())))
|
||||
.get();
|
||||
// TODO(b/153378849): Remove the hard code for postal info after resolving the issue that
|
||||
// @PostLoad doesn't work in Address
|
||||
ContactResource fixed =
|
||||
originalContact
|
||||
.asBuilder()
|
||||
.setCreationTime(persisted.getCreationTime())
|
||||
.setInternationalizedPostalInfo(persisted.getInternationalizedPostalInfo())
|
||||
.setLocalizedPostalInfo(persisted.getLocalizedPostalInfo())
|
||||
.setTransferData(null)
|
||||
.build();
|
||||
assertThat(persisted).isEqualTo(fixed);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,6 +16,8 @@ package google.registry.model.domain;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.SqlHelper.assertThrowForeignKeyViolation;
|
||||
import static google.registry.testing.SqlHelper.saveRegistrar;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
@@ -27,6 +29,8 @@ import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
@@ -54,20 +58,25 @@ public class DomainBaseSqlTest {
|
||||
DomainBase domain;
|
||||
Key<ContactResource> contactKey;
|
||||
Key<ContactResource> contact2Key;
|
||||
VKey<HostResource> host1VKey;
|
||||
HostResource host;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
contactKey = Key.create(ContactResource.class, "contact_id1");
|
||||
contact2Key = Key.create(ContactResource.class, "contact_id2");
|
||||
|
||||
host1VKey = VKey.createSql(HostResource.class, "host1");
|
||||
|
||||
domain =
|
||||
new DomainBase.Builder()
|
||||
.setFullyQualifiedDomainName("example.com")
|
||||
.setRepoId("4-COM")
|
||||
.setCreationClientId("a registrar")
|
||||
.setCreationClientId("registrar1")
|
||||
.setLastEppUpdateTime(fakeClock.nowUtc())
|
||||
.setLastEppUpdateClientId("AnotherRegistrar")
|
||||
.setLastEppUpdateClientId("registrar2")
|
||||
.setLastTransferTime(fakeClock.nowUtc())
|
||||
.setNameservers(host1VKey)
|
||||
.setStatusValues(
|
||||
ImmutableSet.of(
|
||||
StatusValue.CLIENT_DELETE_PROHIBITED,
|
||||
@@ -79,7 +88,7 @@ public class DomainBaseSqlTest {
|
||||
.setRegistrant(contactKey)
|
||||
.setContacts(ImmutableSet.of(DesignatedContact.create(Type.ADMIN, contact2Key)))
|
||||
.setSubordinateHosts(ImmutableSet.of("ns1.example.com"))
|
||||
.setPersistedCurrentSponsorClientId("losing")
|
||||
.setPersistedCurrentSponsorClientId("registrar3")
|
||||
.setRegistrationExpirationTime(fakeClock.nowUtc().plusYears(1))
|
||||
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("password")))
|
||||
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
|
||||
@@ -87,16 +96,31 @@ public class DomainBaseSqlTest {
|
||||
LaunchNotice.create("tcnid", "validatorId", START_OF_TIME, START_OF_TIME))
|
||||
.setSmdId("smdid")
|
||||
.build();
|
||||
|
||||
host =
|
||||
new HostResource.Builder()
|
||||
.setRepoId("host1")
|
||||
.setFullyQualifiedHostName("ns1.example.com")
|
||||
.setCreationClientId("registrar1")
|
||||
.setPersistedCurrentSponsorClientId("registrar2")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDomainBasePersistence() {
|
||||
saveRegistrar("registrar1");
|
||||
saveRegistrar("registrar2");
|
||||
saveRegistrar("registrar3");
|
||||
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
// Persist the domain.
|
||||
EntityManager em = jpaTm().getEntityManager();
|
||||
em.persist(domain);
|
||||
|
||||
// Persist the host.
|
||||
em.persist(host);
|
||||
});
|
||||
|
||||
jpaTm()
|
||||
@@ -125,4 +149,18 @@ public class DomainBaseSqlTest {
|
||||
assertThat(result).isEqualTo(org);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForeignKeyConstraints() {
|
||||
assertThrowForeignKeyViolation(
|
||||
() -> {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
// Persist the domain without the associated host object.
|
||||
EntityManager em = jpaTm().getEntityManager();
|
||||
em.persist(domain);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.model.ofy;
|
||||
|
||||
import static com.google.appengine.api.datastore.EntityTranslator.convertToPb;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.googlecode.objectify.ObjectifyService.register;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.CommitLogBucket.getBucketKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
@@ -47,7 +46,11 @@ import org.junit.runners.JUnit4;
|
||||
public class OfyCommitLogTest {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||
public final AppEngineRule appEngine =
|
||||
AppEngineRule.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(TestVirtualObject.class, Root.class, Child.class)
|
||||
.build();
|
||||
|
||||
@Rule
|
||||
public final InjectRule inject = new InjectRule();
|
||||
@@ -56,8 +59,6 @@ public class OfyCommitLogTest {
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
register(Root.class);
|
||||
register(Child.class);
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.server.Lock.LockState;
|
||||
import google.registry.schema.server.LockDao;
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectRule;
|
||||
@@ -65,19 +64,16 @@ public class LockTest {
|
||||
Optional<Lock> lock = Lock.acquire(RESOURCE_NAME, tld, leaseLength, requestStatusChecker, true);
|
||||
verify(Lock.lockMetrics).recordAcquire(RESOURCE_NAME, tld, expectedLockState);
|
||||
verifyNoMoreInteractions(Lock.lockMetrics);
|
||||
assertThat(LockDao.load(RESOURCE_NAME, tld)).isPresent();
|
||||
Lock.lockMetrics = null;
|
||||
return lock;
|
||||
}
|
||||
|
||||
private void release(Lock lock, String expectedTld, long expectedMillis) {
|
||||
assertThat(LockDao.load(RESOURCE_NAME, expectedTld)).isPresent();
|
||||
Lock.lockMetrics = mock(LockMetrics.class);
|
||||
lock.release();
|
||||
verify(Lock.lockMetrics)
|
||||
.recordRelease(RESOURCE_NAME, expectedTld, Duration.millis(expectedMillis));
|
||||
verifyNoMoreInteractions(Lock.lockMetrics);
|
||||
assertThat(LockDao.load(RESOURCE_NAME, expectedTld)).isEmpty();
|
||||
Lock.lockMetrics = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import static org.joda.time.Duration.standardHours;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.ObjectifyService;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import google.registry.model.ofy.CommitLogManifest;
|
||||
@@ -45,13 +44,17 @@ public class CommitLogRevisionsTranslatorFactoryTest {
|
||||
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01TZ");
|
||||
|
||||
@Entity
|
||||
@Entity(name = "ClrtfTestEntity")
|
||||
public static class TestObject extends CrossTldSingleton {
|
||||
ImmutableSortedMap<DateTime, Key<CommitLogManifest>> revisions = ImmutableSortedMap.of();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||
public final AppEngineRule appEngine =
|
||||
AppEngineRule.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(TestObject.class)
|
||||
.build();
|
||||
|
||||
@Rule
|
||||
public final InjectRule inject = new InjectRule();
|
||||
@@ -60,7 +63,6 @@ public class CommitLogRevisionsTranslatorFactoryTest {
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ObjectifyService.register(TestObject.class);
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,15 +28,19 @@ public class VKeyTest {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngineRule =
|
||||
AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||
AppEngineRule.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(TestObject.class)
|
||||
.build();
|
||||
|
||||
public VKeyTest() {}
|
||||
|
||||
@Test
|
||||
public void testOptionalAccessors() {
|
||||
VKey<TestObject> key = VKey.create(TestObject.class, null, null);
|
||||
assertThat(key.maybeGetSqlKey().isPresent()).isFalse();
|
||||
assertThat(key.maybeGetOfyKey().isPresent()).isFalse();
|
||||
VKey<TestObject> key =
|
||||
VKey.create(TestObject.class, "foo", Key.create(TestObject.create("foo")));
|
||||
assertThat(key.maybeGetSqlKey().isPresent()).isTrue();
|
||||
assertThat(key.maybeGetOfyKey().isPresent()).isTrue();
|
||||
|
||||
Key<TestObject> ofyKey = Key.create(TestObject.create("foo"));
|
||||
assertThat(VKey.createOfy(TestObject.class, ofyKey).maybeGetOfyKey().get()).isEqualTo(ofyKey);
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.persistence.converter;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithLongVKey;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Test SQL persistence of VKey. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class LongVKeyConverterTest {
|
||||
|
||||
@Rule
|
||||
public final JpaUnitTestRule jpaRule =
|
||||
new JpaTestRules.Builder()
|
||||
.withEntityClass(TestEntity.class, VKeyConverter_LongType.class)
|
||||
.buildUnitTestRule();
|
||||
|
||||
@Test
|
||||
public void testRoundTrip() {
|
||||
TestEntity original = new TestEntity(VKey.createSql(TestEntity.class, 10L));
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(original));
|
||||
|
||||
TestEntity retrieved =
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
|
||||
assertThat(retrieved.number.getSqlKey()).isEqualTo(10L);
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity")
|
||||
@WithLongVKey(classNameSuffix = "LongType")
|
||||
static class TestEntity {
|
||||
@Id String id = "id";
|
||||
|
||||
VKey<TestEntity> number;
|
||||
|
||||
TestEntity(VKey<TestEntity> number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
/** Default constructor, needed for hibernate. */
|
||||
public TestEntity() {}
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,9 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithStringVKey;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.junit.Rule;
|
||||
@@ -30,13 +30,15 @@ import org.junit.runners.JUnit4;
|
||||
|
||||
/** Test SQL persistence of VKey. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class VKeyConverterTest {
|
||||
public class StringVKeyConverterTest {
|
||||
|
||||
@Rule
|
||||
public final JpaUnitTestRule jpaRule =
|
||||
new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule();
|
||||
new JpaTestRules.Builder()
|
||||
.withEntityClass(TestEntity.class, VKeyConverter_StringType.class)
|
||||
.buildUnitTestRule();
|
||||
|
||||
public VKeyConverterTest() {}
|
||||
public StringVKeyConverterTest() {}
|
||||
|
||||
@Test
|
||||
public void testRoundTrip() {
|
||||
@@ -45,27 +47,16 @@ public class VKeyConverterTest {
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(original));
|
||||
|
||||
TestEntity retrieved =
|
||||
jpaTm().transact(
|
||||
() -> jpaTm().getEntityManager().find(TestEntity.class, "TheRealSpartacus"));
|
||||
jpaTm()
|
||||
.transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "TheRealSpartacus"));
|
||||
assertThat(retrieved.other.getSqlKey()).isEqualTo("ImSpartacus!");
|
||||
}
|
||||
|
||||
static class TestEntityVKeyConverter extends VKeyConverter<TestEntity> {
|
||||
|
||||
@Override
|
||||
protected Class<TestEntity> getAttributeClass() {
|
||||
return TestEntity.class;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity")
|
||||
@WithStringVKey(classNameSuffix = "StringType")
|
||||
static class TestEntity {
|
||||
@Id
|
||||
String id;
|
||||
@Id String id;
|
||||
|
||||
// Specifying "@Converter(autoApply = true) on TestEntityVKeyConverter this doesn't seem to
|
||||
// work.
|
||||
@Convert(converter = TestEntityVKeyConverter.class)
|
||||
VKey<TestEntity> other;
|
||||
|
||||
TestEntity(String id, VKey<TestEntity> other) {
|
||||
@@ -41,6 +41,7 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -76,7 +77,7 @@ abstract class JpaTransactionManagerRule extends ExternalResource {
|
||||
private final Clock clock;
|
||||
private final Optional<String> initScriptPath;
|
||||
private final ImmutableList<Class> extraEntityClasses;
|
||||
private final ImmutableMap userProperties;
|
||||
private final ImmutableMap<String, String> userProperties;
|
||||
|
||||
private static final JdbcDatabaseContainer database = create();
|
||||
private static final HibernateSchemaExporter exporter =
|
||||
@@ -143,15 +144,18 @@ abstract class JpaTransactionManagerRule extends ExternalResource {
|
||||
new String(Files.readAllBytes(tempSqlFile.toPath()), StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
ImmutableMap properties = PersistenceModule.providesDefaultDatabaseConfigs();
|
||||
Map<String, String> properties =
|
||||
Maps.newHashMap(PersistenceModule.providesDefaultDatabaseConfigs());
|
||||
// Set the minimumIdle to 0 so assertReasonableNumDbConnections() can check if there is
|
||||
// connection leak after each test.
|
||||
properties.put("hibernate.hikari.minimumIdle", "0");
|
||||
properties.put("hibernate.hikari.idleTimeout", "300000");
|
||||
if (!userProperties.isEmpty()) {
|
||||
// If there are user properties, create a new properties object with these added.
|
||||
ImmutableMap.Builder builder = properties.builder();
|
||||
builder.putAll(userProperties);
|
||||
properties.putAll(userProperties);
|
||||
// Forbid Hibernate push to stay consistent with flyway-based schema management.
|
||||
builder.put(Environment.HBM2DDL_AUTO, "none");
|
||||
builder.put(Environment.SHOW_SQL, "true");
|
||||
properties = builder.build();
|
||||
properties.put(Environment.HBM2DDL_AUTO, "none");
|
||||
properties.put(Environment.SHOW_SQL, "true");
|
||||
}
|
||||
assertReasonableNumDbConnections();
|
||||
emf =
|
||||
@@ -159,7 +163,7 @@ abstract class JpaTransactionManagerRule extends ExternalResource {
|
||||
getJdbcUrl(),
|
||||
database.getUsername(),
|
||||
database.getPassword(),
|
||||
properties,
|
||||
ImmutableMap.copyOf(properties),
|
||||
extraEntityClasses);
|
||||
emfEntityHash = entityHash;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.schema.integration;
|
||||
|
||||
import static com.google.common.truth.Truth.assert_;
|
||||
|
||||
import google.registry.model.contact.ContactResourceTest;
|
||||
import google.registry.model.domain.DomainBaseSqlTest;
|
||||
import google.registry.model.registry.RegistryLockDaoTest;
|
||||
import google.registry.persistence.transaction.JpaEntityCoverage;
|
||||
@@ -68,6 +69,7 @@ import org.junit.runner.RunWith;
|
||||
// BeforeSuiteTest must be the first entry. See class javadoc for details.
|
||||
BeforeSuiteTest.class,
|
||||
ClaimsListDaoTest.class,
|
||||
ContactResourceTest.class,
|
||||
CursorDaoTest.class,
|
||||
DomainBaseSqlTest.class,
|
||||
LockDaoTest.class,
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.schema.replay;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import io.github.classgraph.ClassGraph;
|
||||
import io.github.classgraph.ClassInfo;
|
||||
import io.github.classgraph.ClassInfoList;
|
||||
import io.github.classgraph.ScanResult;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test to verify classes implement {@link SqlEntity} and {@link DatastoreEntity} when they should.
|
||||
*/
|
||||
public class EntityTest {
|
||||
|
||||
@Test
|
||||
@Ignore("This won't be done until b/152410794 is done, since it requires many entity changes")
|
||||
public void testSqlEntityPersistence() {
|
||||
try (ScanResult scanResult =
|
||||
new ClassGraph().enableAnnotationInfo().whitelistPackages("google.registry").scan()) {
|
||||
// All javax.persistence entities must implement SqlEntity and vice versa
|
||||
ImmutableSet<String> javaxPersistenceClasses =
|
||||
getClassNames(
|
||||
scanResult.getClassesWithAnnotation(javax.persistence.Entity.class.getName()));
|
||||
ImmutableSet<String> sqlEntityClasses =
|
||||
getClassNames(scanResult.getClassesImplementing(SqlEntity.class.getName()));
|
||||
assertThat(javaxPersistenceClasses).isEqualTo(sqlEntityClasses);
|
||||
|
||||
// All com.googlecode.objectify.annotation.Entity classes must implement DatastoreEntity and
|
||||
// vice versa
|
||||
ImmutableSet<String> objectifyClasses =
|
||||
getClassNames(
|
||||
scanResult.getClassesWithAnnotation(
|
||||
com.googlecode.objectify.annotation.Entity.class.getName()));
|
||||
ImmutableSet<String> datastoreEntityClasses =
|
||||
getClassNames(scanResult.getClassesImplementing(DatastoreEntity.class.getName()));
|
||||
assertThat(objectifyClasses).isEqualTo(datastoreEntityClasses);
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableSet<String> getClassNames(ClassInfoList classInfoList) {
|
||||
return classInfoList.stream()
|
||||
.filter(ClassInfo::isStandardClass)
|
||||
.map(ClassInfo::loadClass)
|
||||
.map(Class::getName)
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.io.Files;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.ObjectifyFilter;
|
||||
import google.registry.model.ofy.ObjectifyService;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
@@ -50,6 +51,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.logging.LogManager;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -127,10 +129,14 @@ public final class AppEngineRule extends ExternalResource
|
||||
private String taskQueueXml;
|
||||
private UserInfo userInfo;
|
||||
|
||||
// Test Objectify entity classes to be used with this AppEngineRule instance.
|
||||
private ImmutableList<Class<?>> ofyTestEntities;
|
||||
|
||||
/** Builder for {@link AppEngineRule}. */
|
||||
public static class Builder {
|
||||
|
||||
private AppEngineRule rule = new AppEngineRule();
|
||||
private ImmutableList.Builder<Class<?>> ofyTestEntities = new ImmutableList.Builder();
|
||||
|
||||
/** Turn on the Datastore service and the Cloud SQL service. */
|
||||
public Builder withDatastoreAndCloudSql() {
|
||||
@@ -181,10 +187,29 @@ public final class AppEngineRule extends ExternalResource
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares test-only entities to be registered with {@code ObjectifyService}.
|
||||
*
|
||||
* <p>Note that {@code ObjectifyService} silently replaces the current registration for a given
|
||||
* kind when a different class is registered for this kind. Since {@code ObjectifyService} does
|
||||
* not support de-registration, each test entity class must be of a unique kind across the
|
||||
* entire code base. Although this requirement can be worked around by using different {@code
|
||||
* ObjectifyService} instances for each test (class), the setup overhead would rise
|
||||
* significantly.
|
||||
*
|
||||
* @see AppEngineRule#register(Class)
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final Builder withOfyTestEntities(Class<?>... entities) {
|
||||
ofyTestEntities.add(entities);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AppEngineRule build() {
|
||||
checkState(
|
||||
!rule.enableJpaEntityCoverageCheck || rule.withDatastoreAndCloudSql,
|
||||
"withJpaEntityCoverageCheck enabled without Cloud SQL");
|
||||
rule.ofyTestEntities = this.ofyTestEntities.build();
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
@@ -411,6 +436,7 @@ public final class AppEngineRule extends ExternalResource
|
||||
// Reset id allocation in ObjectifyService so that ids are deterministic in tests.
|
||||
ObjectifyService.resetNextTestId();
|
||||
loadInitialData();
|
||||
this.ofyTestEntities.forEach(AppEngineRule::register);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,6 +469,24 @@ public final class AppEngineRule extends ExternalResource
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers test-only Objectify entities and checks for re-registrations for the same kind by
|
||||
* different classes.
|
||||
*/
|
||||
private static void register(Class<?> entityClass) {
|
||||
String kind = Key.getKind(entityClass);
|
||||
Optional.ofNullable(com.googlecode.objectify.ObjectifyService.factory().getMetadata(kind))
|
||||
.ifPresent(
|
||||
meta ->
|
||||
checkState(
|
||||
meta.getEntityClass() == entityClass,
|
||||
"Cannot register %s. The Kind %s is already registered with %s.",
|
||||
entityClass.getName(),
|
||||
kind,
|
||||
meta.getEntityClass().getName()));
|
||||
com.googlecode.objectify.ObjectifyService.register(entityClass);
|
||||
}
|
||||
|
||||
/** Install {@code testing/logging.properties} so logging is less noisy. */
|
||||
private static void setupLogging() throws IOException {
|
||||
LogManager.getLogManager()
|
||||
|
||||
@@ -18,6 +18,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import org.junit.Before;
|
||||
@@ -88,9 +89,29 @@ public class AppEngineRuleTest {
|
||||
assertThrows(AssertionError.class, () -> appEngineRule.after());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterOfyEntities_failure() {
|
||||
AppEngineRule appEngineRule =
|
||||
AppEngineRule.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withOfyTestEntities(google.registry.testing.TestObject.class, TestObject.class)
|
||||
.build();
|
||||
String expectedErrorMessage =
|
||||
String.format(
|
||||
"Cannot register %s. The Kind %s is already registered with %s",
|
||||
TestObject.class.getName(),
|
||||
"TestObject",
|
||||
google.registry.testing.TestObject.class.getName());
|
||||
assertThrows(expectedErrorMessage, IllegalStateException.class, appEngineRule::before);
|
||||
appEngineRule.after();
|
||||
}
|
||||
|
||||
private void writeAutoIndexFile(String content) throws IOException {
|
||||
com.google.common.io.Files.asCharSink(
|
||||
new File(temporaryFolder.getRoot(), "datastore-indexes-auto.xml"), UTF_8)
|
||||
.write(content);
|
||||
}
|
||||
|
||||
@Entity
|
||||
private static final class TestObject {}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,19 @@
|
||||
|
||||
package google.registry.testing;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.AppEngineRule.makeRegistrar1;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.registry.RegistryLockDao;
|
||||
import google.registry.schema.domain.RegistryLock;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.RollbackException;
|
||||
import org.junit.function.ThrowingRunnable;
|
||||
|
||||
/** Static utils for setting up and retrieving test resources from the SQL database. */
|
||||
public class SqlHelper {
|
||||
@@ -52,5 +59,19 @@ public class SqlHelper {
|
||||
return jpaTm().transact(() -> RegistryLockDao.getByRevisionId(revisionId));
|
||||
}
|
||||
|
||||
public static void saveRegistrar(String clientId) {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> jpaTm().saveNew(makeRegistrar1().asBuilder().setClientId(clientId).build()));
|
||||
}
|
||||
|
||||
public static void assertThrowForeignKeyViolation(ThrowingRunnable runnable) {
|
||||
RollbackException thrown = assertThrows(RollbackException.class, runnable);
|
||||
assertThat(Throwables.getRootCause(thrown)).isInstanceOf(SQLException.class);
|
||||
assertThat(Throwables.getRootCause(thrown))
|
||||
.hasMessageThat()
|
||||
.contains("violates foreign key constraint");
|
||||
}
|
||||
|
||||
private SqlHelper() {}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package google.registry.testing;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.ObjectifyService;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
@@ -30,9 +29,6 @@ import google.registry.model.common.EntityGroupRoot;
|
||||
*/
|
||||
@Entity
|
||||
public class TestObject extends ImmutableObject {
|
||||
static {
|
||||
ObjectifyService.register(TestObject.class); // Register this kind on first reference.
|
||||
}
|
||||
|
||||
@Parent
|
||||
Key<EntityGroupRoot> parent;
|
||||
@@ -70,9 +66,6 @@ public class TestObject extends ImmutableObject {
|
||||
@Entity
|
||||
@VirtualEntity
|
||||
public static class TestVirtualObject extends ImmutableObject {
|
||||
static {
|
||||
ObjectifyService.register(TestVirtualObject.class); // Register this kind on first reference.
|
||||
}
|
||||
|
||||
@Id
|
||||
String id;
|
||||
|
||||
@@ -98,19 +98,20 @@ public class RegistrarContactCommandTest extends CommandTestCase<RegistrarContac
|
||||
"--visible_in_domain_whois_as_abuse=false",
|
||||
"NewRegistrar");
|
||||
RegistrarContact registrarContact = loadRegistrar("NewRegistrar").getContacts().asList().get(1);
|
||||
assertThat(registrarContact).isEqualTo(
|
||||
new RegistrarContact.Builder()
|
||||
.setParent(registrar)
|
||||
.setName("Judith Registrar")
|
||||
.setEmailAddress("judith.doe@example.com")
|
||||
.setRegistryLockEmailAddress("judith.doe@external.com")
|
||||
.setPhoneNumber("+1.2125650000")
|
||||
.setFaxNumber("+1.2125650001")
|
||||
.setTypes(ImmutableSet.of(WHOIS))
|
||||
.setVisibleInWhoisAsAdmin(true)
|
||||
.setVisibleInWhoisAsTech(false)
|
||||
.setVisibleInDomainWhoisAsAbuse(false)
|
||||
.build());
|
||||
assertThat(registrarContact)
|
||||
.isEqualTo(
|
||||
new RegistrarContact.Builder()
|
||||
.setParent(registrar)
|
||||
.setName("Judith Registrar")
|
||||
.setEmailAddress("judith.doe@example.com")
|
||||
.setRegistryLockEmailAddress("judith.doe@external.com")
|
||||
.setPhoneNumber("+1.2125650000")
|
||||
.setFaxNumber("+1.2125650001")
|
||||
.setTypes(ImmutableSet.of(WHOIS))
|
||||
.setVisibleInWhoisAsAdmin(true)
|
||||
.setVisibleInWhoisAsTech(false)
|
||||
.setVisibleInDomainWhoisAsAbuse(false)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -305,17 +306,18 @@ public class RegistrarContactCommandTest extends CommandTestCase<RegistrarContac
|
||||
"--visible_in_domain_whois_as_abuse=true",
|
||||
"NewRegistrar");
|
||||
RegistrarContact registrarContact = loadRegistrar("NewRegistrar").getContacts().asList().get(1);
|
||||
assertThat(registrarContact).isEqualTo(
|
||||
new RegistrarContact.Builder()
|
||||
.setParent(registrar)
|
||||
.setName("Jim Doe")
|
||||
.setEmailAddress("jim.doe@example.com")
|
||||
.setRegistryLockEmailAddress("jim.doe@external.com")
|
||||
.setTypes(ImmutableSet.of(ADMIN, ABUSE))
|
||||
.setVisibleInWhoisAsAdmin(true)
|
||||
.setVisibleInWhoisAsTech(false)
|
||||
.setVisibleInDomainWhoisAsAbuse(true)
|
||||
.build());
|
||||
assertThat(registrarContact)
|
||||
.isEqualTo(
|
||||
new RegistrarContact.Builder()
|
||||
.setParent(registrar)
|
||||
.setName("Jim Doe")
|
||||
.setEmailAddress("jim.doe@example.com")
|
||||
.setRegistryLockEmailAddress("jim.doe@external.com")
|
||||
.setTypes(ImmutableSet.of(ADMIN, ABUSE))
|
||||
.setVisibleInWhoisAsAdmin(true)
|
||||
.setVisibleInWhoisAsTech(false)
|
||||
.setVisibleInDomainWhoisAsAbuse(true)
|
||||
.build());
|
||||
assertThat(registrarContact.getGaeUserId()).isNull();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// 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.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import google.registry.testing.AppEngineRule;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link google.registry.tools.RegistryTool}. */
|
||||
public class RegistryToolTest {
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
// Lock for stdout/stderr. Note that this is static: since we're dealing with globals, we need
|
||||
// to lock for the entire JVM.
|
||||
private static final ReentrantLock stdoutLock = new ReentrantLock();
|
||||
|
||||
private PrintStream oldStdout;
|
||||
private final ByteArrayOutputStream stdout = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
// Capture standard output/error. This is problematic because gradle tests run in parallel in
|
||||
// the same JVM. So first lock out any other tests in this JVM that are trying to do this
|
||||
// trick.
|
||||
// TODO(mcilwain): Turn this into a JUnit 5 extension.
|
||||
stdoutLock.lock();
|
||||
oldStdout = System.out;
|
||||
System.setOut(new PrintStream(stdout));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
final void afterEach() {
|
||||
System.setOut(oldStdout);
|
||||
stdoutLock.unlock();
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_displayAvailableCommands() throws Exception {
|
||||
RegistryTool.main(new String[] {"-e", "unittest", "--commands"});
|
||||
// Check for the existence of a few common commands.
|
||||
assertThat(getStdout()).contains("login");
|
||||
assertThat(getStdout()).contains("check_domain");
|
||||
assertThat(getStdout()).contains("get_tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_noSubcommandSpecified_displaysAvailableCommands() throws Exception {
|
||||
RegistryTool.main(new String[] {"-e", "unittest"});
|
||||
assertThat(getStdout()).contains("The list of available subcommands is:");
|
||||
assertThat(getStdout()).contains("login");
|
||||
assertThat(getStdout()).contains("check_domain");
|
||||
assertThat(getStdout()).contains("get_tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_noEnvironmentSpecified_throwsCorrectError() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(IllegalArgumentException.class, () -> RegistryTool.main(new String[] {}));
|
||||
assertThat(thrown).hasMessageThat().contains("Please specify the environment flag");
|
||||
}
|
||||
|
||||
private String getStdout() {
|
||||
return new String(stdout.toByteArray(), UTF_8);
|
||||
}
|
||||
}
|
||||
@@ -15,21 +15,27 @@
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatastoreHelper.newDomainBase;
|
||||
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatastoreHelper.persistDeletedDomain;
|
||||
import static google.registry.testing.DatastoreHelper.persistNewRegistrar;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectRule;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.List;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
|
||||
|
||||
/** Unit tests for {@link RenewDomainCommand}. */
|
||||
public class RenewDomainCommandTest extends EppToolCommandTestCase<RenewDomainCommand> {
|
||||
@@ -63,23 +69,57 @@ public class RenewDomainCommandTest extends EppToolCommandTestCase<RenewDomainCo
|
||||
.verifyNoMoreSent();
|
||||
}
|
||||
|
||||
private static List<DomainBase> persistThreeDomains() {
|
||||
ImmutableList.Builder<DomainBase> domains = new ImmutableList.Builder<>();
|
||||
domains.add(
|
||||
persistActiveDomain(
|
||||
"domain1.tld",
|
||||
DateTime.parse("2014-09-05T05:05:05Z"),
|
||||
DateTime.parse("2015-09-05T05:05:05Z")));
|
||||
domains.add(
|
||||
persistActiveDomain(
|
||||
"domain2.tld",
|
||||
DateTime.parse("2014-11-05T05:05:05Z"),
|
||||
DateTime.parse("2015-11-05T05:05:05Z")));
|
||||
// The third domain is owned by a different registrar.
|
||||
domains.add(
|
||||
persistResource(
|
||||
newDomainBase("domain3.tld")
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(DateTime.parse("2015-01-05T05:05:05Z"))
|
||||
.setRegistrationExpirationTime(DateTime.parse("2016-01-05T05:05:05Z"))
|
||||
.setPersistedCurrentSponsorClientId("NewRegistrar")
|
||||
.build()));
|
||||
return domains.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_multipleDomains() throws Exception {
|
||||
persistActiveDomain(
|
||||
"domain1.tld",
|
||||
DateTime.parse("2014-09-05T05:05:05Z"),
|
||||
DateTime.parse("2015-09-05T05:05:05Z"));
|
||||
persistActiveDomain(
|
||||
"domain2.tld",
|
||||
DateTime.parse("2014-11-05T05:05:05Z"),
|
||||
DateTime.parse("2015-11-05T05:05:05Z"));
|
||||
persistActiveDomain(
|
||||
"domain3.tld",
|
||||
DateTime.parse("2015-01-05T05:05:05Z"),
|
||||
DateTime.parse("2016-01-05T05:05:05Z"));
|
||||
public void testSuccess_multipleDomains_renewsAndUsesEachDomainsRegistrar() throws Exception {
|
||||
persistThreeDomains();
|
||||
runCommandForced("--period 3", "domain1.tld", "domain2.tld", "domain3.tld");
|
||||
eppVerifier
|
||||
.expectClientId("TheRegistrar")
|
||||
.verifySent(
|
||||
"domain_renew.xml",
|
||||
ImmutableMap.of("DOMAIN", "domain1.tld", "EXPDATE", "2015-09-05", "YEARS", "3"))
|
||||
.verifySent(
|
||||
"domain_renew.xml",
|
||||
ImmutableMap.of("DOMAIN", "domain2.tld", "EXPDATE", "2015-11-05", "YEARS", "3"))
|
||||
.expectClientId("NewRegistrar")
|
||||
.verifySent(
|
||||
"domain_renew.xml",
|
||||
ImmutableMap.of("DOMAIN", "domain3.tld", "EXPDATE", "2016-01-05", "YEARS", "3"))
|
||||
.verifyNoMoreSent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_multipleDomains_renewsAndUsesSpecifiedRegistrar() throws Exception {
|
||||
persistThreeDomains();
|
||||
persistNewRegistrar("reg3", "Registrar 3", Registrar.Type.REAL, 9783L);
|
||||
runCommandForced("--period 3", "domain1.tld", "domain2.tld", "domain3.tld", "-u", "-c reg3");
|
||||
eppVerifier
|
||||
.expectClientId("reg3")
|
||||
.expectSuperuser()
|
||||
.verifySent(
|
||||
"domain_renew.xml",
|
||||
ImmutableMap.of("DOMAIN", "domain1.tld", "EXPDATE", "2015-09-05", "YEARS", "3"))
|
||||
@@ -106,9 +146,7 @@ public class RenewDomainCommandTest extends EppToolCommandTestCase<RenewDomainCo
|
||||
persistDeletedDomain("deleted.tld", DateTime.parse("2012-10-05T05:05:05Z"));
|
||||
IllegalArgumentException e =
|
||||
assertThrows(IllegalArgumentException.class, () -> runCommandForced("deleted.tld"));
|
||||
assertThat(e)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Domain 'deleted.tld' does not exist or is deleted");
|
||||
assertThat(e).hasMessageThat().isEqualTo("Domain 'deleted.tld' does not exist or is deleted");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -128,9 +166,7 @@ public class RenewDomainCommandTest extends EppToolCommandTestCase<RenewDomainCo
|
||||
IllegalArgumentException e =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class, () -> runCommandForced("domain.tld", "--period 10"));
|
||||
assertThat(e)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Cannot renew domains for 10 or more years");
|
||||
assertThat(e).hasMessageThat().isEqualTo("Cannot renew domains for 10 or more years");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -66,13 +66,12 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
|
||||
|
||||
@Test
|
||||
public void testPost_updateContacts_success() throws Exception {
|
||||
// Remove all the contacts but the first by updating with list of
|
||||
// just it.
|
||||
// Remove all the contacts but one by updating with a list of just it
|
||||
ImmutableMap<String, String> adminContact1 =
|
||||
ImmutableMap.of(
|
||||
"name", "contact1",
|
||||
"emailAddress", "contact1@email.com",
|
||||
"phoneNumber", "+1.2125650001",
|
||||
"name", "Marla Singer",
|
||||
"emailAddress", "Marla.Singer@crr.com",
|
||||
"phoneNumber", "+1.2128675309",
|
||||
// Have to keep ADMIN or else expect FormException for at-least-one.
|
||||
"types", "ADMIN,TECH");
|
||||
|
||||
@@ -83,15 +82,12 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
|
||||
action.handleJsonRequest(ImmutableMap.of("op", "update", "id", CLIENT_ID, "args", regMap));
|
||||
assertThat(response).containsEntry("status", "SUCCESS");
|
||||
|
||||
RegistrarContact newContact =
|
||||
new RegistrarContact.Builder()
|
||||
.setParent(registrar)
|
||||
.setName(adminContact1.get("name"))
|
||||
.setEmailAddress(adminContact1.get("emailAddress"))
|
||||
.setPhoneNumber(adminContact1.get("phoneNumber"))
|
||||
.setTypes(ImmutableList.of(Type.ADMIN, Type.TECH))
|
||||
.build();
|
||||
assertThat(loadRegistrar(CLIENT_ID).getContacts()).containsExactly(newContact);
|
||||
RegistrarContact foundContact =
|
||||
Iterables.getOnlyElement(loadRegistrar(CLIENT_ID).getContacts());
|
||||
assertThat(foundContact.getName()).isEqualTo(adminContact1.get("name"));
|
||||
assertThat(foundContact.getEmailAddress()).isEqualTo(adminContact1.get("emailAddress"));
|
||||
assertThat(foundContact.getPhoneNumber()).isEqualTo(adminContact1.get("phoneNumber"));
|
||||
assertThat(foundContact.getTypes()).containsExactly(Type.ADMIN, Type.TECH);
|
||||
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
|
||||
verifyNotificationEmailsSent();
|
||||
}
|
||||
@@ -188,41 +184,65 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
|
||||
|
||||
@Test
|
||||
public void testSuccess_setRegistryLockPassword() {
|
||||
addPasswordToTechContact();
|
||||
techContact = Iterables.getOnlyElement(loadRegistrar(CLIENT_ID).getContactsOfType(Type.TECH));
|
||||
assertThat(techContact.verifyRegistryLockPassword("hellothere")).isTrue();
|
||||
addPasswordToContactTwo();
|
||||
String emailAddress = AppEngineRule.makeRegistrarContact2().getEmailAddress();
|
||||
RegistrarContact newContactWithPassword =
|
||||
loadRegistrar(CLIENT_ID).getContacts().stream()
|
||||
.filter(rc -> rc.getEmailAddress().equals(emailAddress))
|
||||
.findFirst()
|
||||
.get();
|
||||
assertThat(newContactWithPassword.verifyRegistryLockPassword("hellothere")).isTrue();
|
||||
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_setRegistryLockPassword_notOverriddenLater() {
|
||||
addPasswordToTechContact();
|
||||
techContact = Iterables.getOnlyElement(loadRegistrar(CLIENT_ID).getContactsOfType(Type.TECH));
|
||||
assertThat(techContact.verifyRegistryLockPassword("hellothere")).isTrue();
|
||||
addPasswordToContactTwo();
|
||||
String emailAddress = AppEngineRule.makeRegistrarContact2().getEmailAddress();
|
||||
RegistrarContact newContactWithPassword =
|
||||
loadRegistrar(CLIENT_ID).getContacts().stream()
|
||||
.filter(rc -> rc.getEmailAddress().equals(emailAddress))
|
||||
.findFirst()
|
||||
.get();
|
||||
assertThat(newContactWithPassword.verifyRegistryLockPassword("hellothere")).isTrue();
|
||||
|
||||
techContact = Iterables.getOnlyElement(loadRegistrar(CLIENT_ID).getContactsOfType(Type.TECH));
|
||||
Map<String, Object> techContactMap = techContact.toJsonMap();
|
||||
techContactMap.put("name", "Some Other Name");
|
||||
Map<String, Object> newContactMap = newContactWithPassword.toJsonMap();
|
||||
newContactMap.put("name", "Some Other Name");
|
||||
Map<String, Object> reqJson = loadRegistrar(CLIENT_ID).toJsonMap();
|
||||
reqJson.put(
|
||||
"contacts",
|
||||
ImmutableList.of(AppEngineRule.makeRegistrarContact2().toJsonMap(), techContactMap));
|
||||
ImmutableList.of(
|
||||
AppEngineRule.makeRegistrarContact1().toJsonMap(),
|
||||
newContactMap,
|
||||
AppEngineRule.makeRegistrarContact3().toJsonMap()));
|
||||
Map<String, Object> response =
|
||||
action.handleJsonRequest(ImmutableMap.of("op", "update", "id", CLIENT_ID, "args", reqJson));
|
||||
assertThat(response).containsAtLeastEntriesIn(ImmutableMap.of("status", "SUCCESS"));
|
||||
techContact = Iterables.getOnlyElement(loadRegistrar(CLIENT_ID).getContactsOfType(Type.TECH));
|
||||
assertThat(techContact.verifyRegistryLockPassword("hellothere")).isTrue();
|
||||
newContactWithPassword =
|
||||
loadRegistrar(CLIENT_ID).getContacts().stream()
|
||||
.filter(rc -> rc.getEmailAddress().equals(emailAddress))
|
||||
.findFirst()
|
||||
.get();
|
||||
assertThat(newContactWithPassword.verifyRegistryLockPassword("hellothere")).isTrue();
|
||||
}
|
||||
|
||||
private void addPasswordToTechContact() {
|
||||
techContact =
|
||||
persistResource(techContact.asBuilder().setAllowedToSetRegistryLockPassword(true).build());
|
||||
Map<String, Object> contactMap = techContact.toJsonMap();
|
||||
private void addPasswordToContactTwo() {
|
||||
RegistrarContact contact =
|
||||
persistResource(
|
||||
AppEngineRule.makeRegistrarContact2()
|
||||
.asBuilder()
|
||||
.setRegistryLockEmailAddress("johndoe@theregistrar.com")
|
||||
.setAllowedToSetRegistryLockPassword(true)
|
||||
.build());
|
||||
Map<String, Object> contactMap = contact.toJsonMap();
|
||||
contactMap.put("registryLockPassword", "hellothere");
|
||||
Map<String, Object> reqJson = loadRegistrar(CLIENT_ID).toJsonMap();
|
||||
reqJson.put(
|
||||
"contacts",
|
||||
ImmutableList.of(AppEngineRule.makeRegistrarContact2().toJsonMap(), contactMap));
|
||||
ImmutableList.of(
|
||||
AppEngineRule.makeRegistrarContact1().toJsonMap(),
|
||||
contactMap,
|
||||
AppEngineRule.makeRegistrarContact3().toJsonMap()));
|
||||
Map<String, Object> response =
|
||||
action.handleJsonRequest(ImmutableMap.of("op", "update", "id", CLIENT_ID, "args", reqJson));
|
||||
assertThat(response).containsAtLeastEntriesIn(ImmutableMap.of("status", "SUCCESS"));
|
||||
@@ -260,13 +280,16 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
|
||||
public void testPost_failure_setRegistryLockPassword_notAllowed() {
|
||||
// "allowedToSetRegistryLockPassword" must be set through the back end first
|
||||
// before we can set a password through the UI
|
||||
Map<String, Object> contactMap =
|
||||
techContact.asBuilder().setAllowedToSetRegistryLockPassword(true).build().toJsonMap();
|
||||
Map<String, Object> contactMap = AppEngineRule.makeRegistrarContact2().toJsonMap();
|
||||
contactMap.put("allowedToSetRegistryLockPassword", true);
|
||||
contactMap.put("registryLockPassword", "hellothere");
|
||||
Map<String, Object> reqJson = loadRegistrar(CLIENT_ID).toJsonMap();
|
||||
reqJson.put(
|
||||
"contacts",
|
||||
ImmutableList.of(AppEngineRule.makeRegistrarContact2().toJsonMap(), contactMap));
|
||||
ImmutableList.of(
|
||||
AppEngineRule.makeRegistrarContact1().toJsonMap(),
|
||||
contactMap,
|
||||
AppEngineRule.makeRegistrarContact3().toJsonMap()));
|
||||
|
||||
Map<String, Object> response =
|
||||
action.handleJsonRequest(ImmutableMap.of("op", "update", "id", CLIENT_ID, "args", reqJson));
|
||||
@@ -304,6 +327,30 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
|
||||
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormException");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPost_failure_removingRegistryLockContact() {
|
||||
ImmutableMap<String, String> contact =
|
||||
ImmutableMap.of(
|
||||
"name", "contact1",
|
||||
"emailAddress", "contact1@email.com",
|
||||
"phoneNumber", "+1.2125650001",
|
||||
// Have to keep ADMIN or else expect FormException for at-least-one.
|
||||
"types", "ADMIN,TECH");
|
||||
Map<String, Object> regMap = loadRegistrar(CLIENT_ID).toJsonMap();
|
||||
regMap.put("contacts", ImmutableList.of(contact));
|
||||
Map<String, Object> response =
|
||||
action.handleJsonRequest(ImmutableMap.of("op", "update", "id", CLIENT_ID, "args", regMap));
|
||||
assertThat(response)
|
||||
.containsExactly(
|
||||
"status",
|
||||
"ERROR",
|
||||
"results",
|
||||
ImmutableList.of(),
|
||||
"message",
|
||||
"Cannot delete the contact Marla.Singer@crr.com that has registry lock enabled");
|
||||
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormException");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPost_failure_setRegistryLock_passwordTooShort() {
|
||||
techContact =
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.ui.server.registrar;
|
||||
|
||||
import static com.google.appengine.repackaged.com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat;
|
||||
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailAddress;
|
||||
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailDisplayName;
|
||||
@@ -23,14 +24,12 @@ import static google.registry.security.JsonHttpTestUtils.createJsonPayload;
|
||||
import static google.registry.testing.DatastoreHelper.createTlds;
|
||||
import static google.registry.testing.DatastoreHelper.disallowRegistrarAccess;
|
||||
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.truth.Truth;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
@@ -95,21 +94,13 @@ public abstract class RegistrarSettingsActionTestCase {
|
||||
// Add a technical contact to the registrar (in addition to the default admin contact created by
|
||||
// AppEngineRule).
|
||||
techContact =
|
||||
persistResource(
|
||||
new RegistrarContact.Builder()
|
||||
.setParent(loadRegistrar(CLIENT_ID))
|
||||
.setName("Jian-Yang")
|
||||
.setEmailAddress("jyang@bachman.accelerator")
|
||||
.setRegistryLockEmailAddress("jyang.registrylock@bachman.accelerator")
|
||||
.setPhoneNumber("+1.1234567890")
|
||||
.setTypes(ImmutableSet.of(RegistrarContact.Type.TECH))
|
||||
.build());
|
||||
getOnlyElement(loadRegistrar(CLIENT_ID).getContactsOfType(RegistrarContact.Type.TECH));
|
||||
|
||||
action.registrarAccessor = null;
|
||||
action.appEngineServiceUtils = appEngineServiceUtils;
|
||||
when(appEngineServiceUtils.getCurrentVersionHostname("backend")).thenReturn("backend.hostname");
|
||||
action.jsonActionRunner = new JsonActionRunner(
|
||||
ImmutableMap.of(), new JsonResponse(new ResponseImpl(rsp)));
|
||||
action.jsonActionRunner =
|
||||
new JsonActionRunner(ImmutableMap.of(), new JsonResponse(new ResponseImpl(rsp)));
|
||||
action.sendEmailUtils =
|
||||
new SendEmailUtils(
|
||||
getGSuiteOutgoingEmailAddress(),
|
||||
|
||||
@@ -18,6 +18,17 @@
|
||||
"emailAddress": "etphonehome@example.com",
|
||||
"gaeUserId": null,
|
||||
"types": "ADMIN,BILLING,TECH,WHOIS"
|
||||
},
|
||||
{
|
||||
"visibleInWhoisAsAdmin": false,
|
||||
"faxNumber": null,
|
||||
"phoneNumber": "+1.2128675309",
|
||||
"name": "Marla Singer",
|
||||
"visibleInWhoisAsTech": false,
|
||||
"emailAddress": "Marla.Singer@crr.com",
|
||||
"registryLockEmailAddress": "Marla.Singer.RegistryLock@crr.com",
|
||||
"gaeUserId": "12345",
|
||||
"types": "TECH"
|
||||
}
|
||||
],
|
||||
"allowedTlds": [
|
||||
|
||||
@@ -13,8 +13,7 @@ contacts:
|
||||
ADDED:
|
||||
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Extra Terrestrial, emailAddress=etphonehome@example.com, registryLockEmailAddress=null, phoneNumber=+1.2345678901, faxNumber=null, types=[ADMIN, BILLING, TECH, WHOIS], gaeUserId=null, visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false}
|
||||
REMOVED:
|
||||
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Marla Singer, emailAddress=Marla.Singer@crr.com, registryLockEmailAddress=Marla.Singer.RegistryLock@crr.com, phoneNumber=+1.2128675309, faxNumber=null, types=[TECH], gaeUserId=12345, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false},
|
||||
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=John Doe, emailAddress=johndoe@theregistrar.com, registryLockEmailAddress=null, phoneNumber=+1.1234567890, faxNumber=null, types=[ADMIN], gaeUserId=31337, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false},
|
||||
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Jian-Yang, emailAddress=jyang@bachman.accelerator, registryLockEmailAddress=jyang.registrylock@bachman.accelerator, phoneNumber=+1.1234567890, faxNumber=null, types=[TECH], gaeUserId=null, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false}
|
||||
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=John Doe, emailAddress=johndoe@theregistrar.com, registryLockEmailAddress=null, phoneNumber=+1.1234567890, faxNumber=null, types=[ADMIN], gaeUserId=31337, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false}
|
||||
FINAL CONTENTS:
|
||||
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Extra Terrestrial, emailAddress=etphonehome@example.com, registryLockEmailAddress=null, phoneNumber=+1.2345678901, faxNumber=null, types=[ADMIN, BILLING, TECH, WHOIS], gaeUserId=null, visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false}
|
||||
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Extra Terrestrial, emailAddress=etphonehome@example.com, registryLockEmailAddress=null, phoneNumber=+1.2345678901, faxNumber=null, types=[ADMIN, BILLING, TECH, WHOIS], gaeUserId=null, visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false},
|
||||
{parent=Key<?>(EntityGroupRoot("cross-tld")/Registrar("TheRegistrar")), name=Marla Singer, emailAddress=Marla.Singer@crr.com, registryLockEmailAddress=Marla.Singer.RegistryLock@crr.com, phoneNumber=+1.2128675309, faxNumber=null, types=[TECH], gaeUserId=12345, visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false, allowedToSetRegistryLockPassword=false}
|
||||
|
||||
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
54
db/src/main/resources/sql/flyway/V22__update_ns_hosts.sql
Normal file
@@ -0,0 +1,54 @@
|
||||
-- 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.
|
||||
|
||||
create table "DomainHost" (
|
||||
domain_repo_id text not null,
|
||||
ns_host_v_keys text
|
||||
);
|
||||
|
||||
create table "HostResource" (
|
||||
repo_id text not null,
|
||||
creation_client_id text,
|
||||
creation_time timestamptz,
|
||||
current_sponsor_client_id text,
|
||||
deletion_time timestamptz,
|
||||
last_epp_update_client_id text,
|
||||
last_epp_update_time timestamptz,
|
||||
statuses text[],
|
||||
fully_qualified_host_name text,
|
||||
last_superordinate_change timestamptz,
|
||||
last_transfer_time timestamptz,
|
||||
superordinate_domain bytea,
|
||||
primary key (repo_id)
|
||||
);
|
||||
|
||||
create table "HostResource_inetAddresses" (
|
||||
host_resource_repo_id text not null,
|
||||
inet_addresses bytea
|
||||
);
|
||||
|
||||
alter table if exists "DomainHost"
|
||||
add constraint FKfmi7bdink53swivs390m2btxg
|
||||
foreign key (domain_repo_id)
|
||||
references "Domain";
|
||||
|
||||
alter table if exists "DomainHost"
|
||||
add constraint FK_DomainHost_host_valid
|
||||
foreign key (ns_host_v_keys)
|
||||
references "HostResource";
|
||||
|
||||
alter table if exists "HostResource_inetAddresses"
|
||||
add constraint FK6unwhfkcu3oq6q347fxvpagv
|
||||
foreign key (host_resource_repo_id)
|
||||
references "HostResource";
|
||||
107
db/src/main/resources/sql/flyway/V23__create_contact.sql
Normal file
@@ -0,0 +1,107 @@
|
||||
-- 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.
|
||||
|
||||
create table "Contact" (
|
||||
repo_id text not null,
|
||||
creation_client_id text not null,
|
||||
creation_time timestamptz not null,
|
||||
current_sponsor_client_id text not null,
|
||||
deletion_time timestamptz,
|
||||
last_epp_update_client_id text,
|
||||
last_epp_update_time timestamptz,
|
||||
statuses text[],
|
||||
auth_info_repo_id text,
|
||||
auth_info_value text,
|
||||
contact_id text,
|
||||
disclose_types_addr text[],
|
||||
disclose_show_email boolean,
|
||||
disclose_show_fax boolean,
|
||||
disclose_mode_flag boolean,
|
||||
disclose_types_name text[],
|
||||
disclose_types_org text[],
|
||||
disclose_show_voice boolean,
|
||||
email text,
|
||||
fax_phone_extension text,
|
||||
fax_phone_number text,
|
||||
addr_i18n_city text,
|
||||
addr_i18n_country_code text,
|
||||
addr_i18n_state text,
|
||||
addr_i18n_street_line1 text,
|
||||
addr_i18n_street_line2 text,
|
||||
addr_i18n_street_line3 text,
|
||||
addr_i18n_zip text,
|
||||
addr_i18n_name text,
|
||||
addr_i18n_org text,
|
||||
addr_i18n_type text,
|
||||
last_transfer_time timestamptz,
|
||||
addr_local_city text,
|
||||
addr_local_country_code text,
|
||||
addr_local_state text,
|
||||
addr_local_street_line1 text,
|
||||
addr_local_street_line2 text,
|
||||
addr_local_street_line3 text,
|
||||
addr_local_zip text,
|
||||
addr_local_name text,
|
||||
addr_local_org text,
|
||||
addr_local_type text,
|
||||
search_name text,
|
||||
voice_phone_extension text,
|
||||
voice_phone_number text,
|
||||
primary key (repo_id)
|
||||
);
|
||||
|
||||
create index IDX3y752kr9uh4kh6uig54vemx0l on "Contact" (creation_time);
|
||||
create index IDXbn8t4wp85fgxjl8q4ctlscx55 on "Contact" (current_sponsor_client_id);
|
||||
create index IDXn1f711wicdnooa2mqb7g1m55o on "Contact" (deletion_time);
|
||||
create index IDX1p3esngcwwu6hstyua6itn6ff on "Contact" (search_name);
|
||||
|
||||
alter table if exists "Contact"
|
||||
add constraint UKoqd7n4hbx86hvlgkilq75olas unique (contact_id);
|
||||
|
||||
alter table "Domain" alter column creation_time set not null;
|
||||
alter table "Domain" alter column creation_client_id set not null;
|
||||
alter table "Domain" alter column current_sponsor_client_id set not null;
|
||||
|
||||
drop index IDX8ffrqm27qtj20jac056j7yq07;
|
||||
create index IDXkjt9yaq92876dstimd93hwckh on "Domain" (current_sponsor_client_id);
|
||||
|
||||
alter table if exists "Contact"
|
||||
add constraint FK1sfyj7o7954prbn1exk7lpnoe
|
||||
foreign key (creation_client_id)
|
||||
references "Registrar";
|
||||
|
||||
alter table if exists "Contact"
|
||||
add constraint FK93c185fx7chn68uv7nl6uv2s0
|
||||
foreign key (current_sponsor_client_id)
|
||||
references "Registrar";
|
||||
|
||||
alter table if exists "Contact"
|
||||
add constraint FKmb7tdiv85863134w1wogtxrb2
|
||||
foreign key (last_epp_update_client_id)
|
||||
references "Registrar";
|
||||
|
||||
alter table if exists "Domain"
|
||||
add constraint FK2jc69qyg2tv9hhnmif6oa1cx1
|
||||
foreign key (creation_client_id)
|
||||
references "Registrar";
|
||||
|
||||
alter table if exists "Domain"
|
||||
add constraint FK2u3srsfbei272093m3b3xwj23
|
||||
foreign key (current_sponsor_client_id)
|
||||
references "Registrar";
|
||||
|
||||
alter table if exists "Domain"
|
||||
add constraint FKjc0r9r5y1lfbt4gpbqw4wsuvq
|
||||
foreign key (last_epp_update_client_id)
|
||||
references "Registrar";
|
||||
@@ -26,6 +26,55 @@
|
||||
primary key (revision_id)
|
||||
);
|
||||
|
||||
create table "Contact" (
|
||||
repo_id text not null,
|
||||
creation_client_id text not null,
|
||||
creation_time timestamptz not null,
|
||||
current_sponsor_client_id text not null,
|
||||
deletion_time timestamptz,
|
||||
last_epp_update_client_id text,
|
||||
last_epp_update_time timestamptz,
|
||||
statuses text[],
|
||||
auth_info_repo_id text,
|
||||
auth_info_value text,
|
||||
contact_id text,
|
||||
disclose_types_addr text[],
|
||||
disclose_show_email boolean,
|
||||
disclose_show_fax boolean,
|
||||
disclose_mode_flag boolean,
|
||||
disclose_types_name text[],
|
||||
disclose_types_org text[],
|
||||
disclose_show_voice boolean,
|
||||
email text,
|
||||
fax_phone_extension text,
|
||||
fax_phone_number text,
|
||||
addr_i18n_city text,
|
||||
addr_i18n_country_code text,
|
||||
addr_i18n_state text,
|
||||
addr_i18n_street_line1 text,
|
||||
addr_i18n_street_line2 text,
|
||||
addr_i18n_street_line3 text,
|
||||
addr_i18n_zip text,
|
||||
addr_i18n_name text,
|
||||
addr_i18n_org text,
|
||||
addr_i18n_type text,
|
||||
last_transfer_time timestamptz,
|
||||
addr_local_city text,
|
||||
addr_local_country_code text,
|
||||
addr_local_state text,
|
||||
addr_local_street_line1 text,
|
||||
addr_local_street_line2 text,
|
||||
addr_local_street_line3 text,
|
||||
addr_local_zip text,
|
||||
addr_local_name text,
|
||||
addr_local_org text,
|
||||
addr_local_type text,
|
||||
search_name text,
|
||||
voice_phone_extension text,
|
||||
voice_phone_number text,
|
||||
primary key (repo_id)
|
||||
);
|
||||
|
||||
create table "Cursor" (
|
||||
scope text not null,
|
||||
type text not null,
|
||||
@@ -44,9 +93,9 @@
|
||||
|
||||
create table "Domain" (
|
||||
repo_id text not null,
|
||||
creation_client_id text,
|
||||
creation_time timestamptz,
|
||||
current_sponsor_client_id text,
|
||||
creation_client_id text not null,
|
||||
creation_time timestamptz not null,
|
||||
current_sponsor_client_id text not null,
|
||||
deletion_time timestamptz,
|
||||
last_epp_update_client_id text,
|
||||
last_epp_update_time timestamptz,
|
||||
@@ -67,6 +116,11 @@
|
||||
primary key (repo_id)
|
||||
);
|
||||
|
||||
create table "DomainHost" (
|
||||
domain_repo_id text not null,
|
||||
ns_host_v_keys text
|
||||
);
|
||||
|
||||
create table "GracePeriod" (
|
||||
id bigserial not null,
|
||||
billing_event_one_time bytea,
|
||||
@@ -77,6 +131,27 @@
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
create table "HostResource" (
|
||||
repo_id text not null,
|
||||
creation_client_id text not null,
|
||||
creation_time timestamptz not null,
|
||||
current_sponsor_client_id text not null,
|
||||
deletion_time timestamptz,
|
||||
last_epp_update_client_id text,
|
||||
last_epp_update_time timestamptz,
|
||||
statuses text[],
|
||||
fully_qualified_host_name text,
|
||||
last_superordinate_change timestamptz,
|
||||
last_transfer_time timestamptz,
|
||||
superordinate_domain bytea,
|
||||
primary key (repo_id)
|
||||
);
|
||||
|
||||
create table "HostResource_inetAddresses" (
|
||||
host_resource_repo_id text not null,
|
||||
inet_addresses bytea
|
||||
);
|
||||
|
||||
create table "Lock" (
|
||||
resource_name text not null,
|
||||
tld text not null,
|
||||
@@ -201,6 +276,13 @@
|
||||
should_publish boolean not null,
|
||||
primary key (revision_id)
|
||||
);
|
||||
create index IDX3y752kr9uh4kh6uig54vemx0l on "Contact" (creation_time);
|
||||
create index IDXbn8t4wp85fgxjl8q4ctlscx55 on "Contact" (current_sponsor_client_id);
|
||||
create index IDXn1f711wicdnooa2mqb7g1m55o on "Contact" (deletion_time);
|
||||
create index IDX1p3esngcwwu6hstyua6itn6ff on "Contact" (search_name);
|
||||
|
||||
alter table if exists "Contact"
|
||||
add constraint UKoqd7n4hbx86hvlgkilq75olas unique (contact_id);
|
||||
create index IDX8nr0ke9mrrx4ewj6pd2ag4rmr on "Domain" (creation_time);
|
||||
create index IDX8ffrqm27qtj20jac056j7yq07 on "Domain" (current_sponsor_client_id);
|
||||
create index IDX5mnf0wn20tno4b9do88j61klr on "Domain" (deletion_time);
|
||||
@@ -222,6 +304,16 @@ create index reservedlist_name_idx on "ReservedList" (name);
|
||||
foreign key (revision_id)
|
||||
references "ClaimsList";
|
||||
|
||||
alter table if exists "DomainHost"
|
||||
add constraint FKeq1guccbre1yk3oosgp2io554
|
||||
foreign key (domain_repo_id)
|
||||
references "Domain";
|
||||
|
||||
alter table if exists "HostResource_inetAddresses"
|
||||
add constraint FK6unwhfkcu3oq6q347fxvpagv
|
||||
foreign key (host_resource_repo_id)
|
||||
references "HostResource";
|
||||
|
||||
alter table if exists "PremiumEntry"
|
||||
add constraint FKo0gw90lpo1tuee56l0nb6y6g5
|
||||
foreign key (revision_id)
|
||||
|
||||
@@ -75,6 +75,59 @@ CREATE SEQUENCE public."ClaimsList_revision_id_seq"
|
||||
ALTER SEQUENCE public."ClaimsList_revision_id_seq" OWNED BY public."ClaimsList".revision_id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: Contact; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public."Contact" (
|
||||
repo_id text NOT NULL,
|
||||
creation_client_id text NOT NULL,
|
||||
creation_time timestamp with time zone NOT NULL,
|
||||
current_sponsor_client_id text NOT NULL,
|
||||
deletion_time timestamp with time zone,
|
||||
last_epp_update_client_id text,
|
||||
last_epp_update_time timestamp with time zone,
|
||||
statuses text[],
|
||||
auth_info_repo_id text,
|
||||
auth_info_value text,
|
||||
contact_id text,
|
||||
disclose_types_addr text[],
|
||||
disclose_show_email boolean,
|
||||
disclose_show_fax boolean,
|
||||
disclose_mode_flag boolean,
|
||||
disclose_types_name text[],
|
||||
disclose_types_org text[],
|
||||
disclose_show_voice boolean,
|
||||
email text,
|
||||
fax_phone_extension text,
|
||||
fax_phone_number text,
|
||||
addr_i18n_city text,
|
||||
addr_i18n_country_code text,
|
||||
addr_i18n_state text,
|
||||
addr_i18n_street_line1 text,
|
||||
addr_i18n_street_line2 text,
|
||||
addr_i18n_street_line3 text,
|
||||
addr_i18n_zip text,
|
||||
addr_i18n_name text,
|
||||
addr_i18n_org text,
|
||||
addr_i18n_type text,
|
||||
last_transfer_time timestamp with time zone,
|
||||
addr_local_city text,
|
||||
addr_local_country_code text,
|
||||
addr_local_state text,
|
||||
addr_local_street_line1 text,
|
||||
addr_local_street_line2 text,
|
||||
addr_local_street_line3 text,
|
||||
addr_local_zip text,
|
||||
addr_local_name text,
|
||||
addr_local_org text,
|
||||
addr_local_type text,
|
||||
search_name text,
|
||||
voice_phone_extension text,
|
||||
voice_phone_number text
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Cursor; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -93,9 +146,9 @@ CREATE TABLE public."Cursor" (
|
||||
|
||||
CREATE TABLE public."Domain" (
|
||||
repo_id text NOT NULL,
|
||||
creation_client_id text,
|
||||
creation_time timestamp with time zone,
|
||||
current_sponsor_client_id text,
|
||||
creation_client_id text NOT NULL,
|
||||
creation_time timestamp with time zone NOT NULL,
|
||||
current_sponsor_client_id text NOT NULL,
|
||||
deletion_time timestamp with time zone,
|
||||
last_epp_update_client_id text,
|
||||
last_epp_update_time timestamp with time zone,
|
||||
@@ -116,6 +169,46 @@ CREATE TABLE public."Domain" (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: DomainHost; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public."DomainHost" (
|
||||
domain_repo_id text NOT NULL,
|
||||
ns_host_v_keys text
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: HostResource; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public."HostResource" (
|
||||
repo_id text NOT NULL,
|
||||
creation_client_id text,
|
||||
creation_time timestamp with time zone,
|
||||
current_sponsor_client_id text,
|
||||
deletion_time timestamp with time zone,
|
||||
last_epp_update_client_id text,
|
||||
last_epp_update_time timestamp with time zone,
|
||||
statuses text[],
|
||||
fully_qualified_host_name text,
|
||||
last_superordinate_change timestamp with time zone,
|
||||
last_transfer_time timestamp with time zone,
|
||||
superordinate_domain bytea
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: HostResource_inetAddresses; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public."HostResource_inetAddresses" (
|
||||
host_resource_repo_id text NOT NULL,
|
||||
inet_addresses bytea
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Lock; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -374,6 +467,14 @@ ALTER TABLE ONLY public."ClaimsList"
|
||||
ADD CONSTRAINT "ClaimsList_pkey" PRIMARY KEY (revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Contact Contact_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Contact"
|
||||
ADD CONSTRAINT "Contact_pkey" PRIMARY KEY (repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Cursor Cursor_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -390,6 +491,14 @@ ALTER TABLE ONLY public."Domain"
|
||||
ADD CONSTRAINT "Domain_pkey" PRIMARY KEY (repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: HostResource HostResource_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."HostResource"
|
||||
ADD CONSTRAINT "HostResource_pkey" PRIMARY KEY (repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Lock Lock_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -462,6 +571,21 @@ ALTER TABLE ONLY public."RegistryLock"
|
||||
ADD CONSTRAINT idx_registry_lock_repo_id_revision_id UNIQUE (repo_id, revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Contact ukoqd7n4hbx86hvlgkilq75olas; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Contact"
|
||||
ADD CONSTRAINT ukoqd7n4hbx86hvlgkilq75olas UNIQUE (contact_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx1p3esngcwwu6hstyua6itn6ff; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idx1p3esngcwwu6hstyua6itn6ff ON public."Contact" USING btree (search_name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx1rcgkdd777bpvj0r94sltwd5y; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -469,6 +593,13 @@ ALTER TABLE ONLY public."RegistryLock"
|
||||
CREATE INDEX idx1rcgkdd777bpvj0r94sltwd5y ON public."Domain" USING btree (fully_qualified_domain_name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx3y752kr9uh4kh6uig54vemx0l; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idx3y752kr9uh4kh6uig54vemx0l ON public."Contact" USING btree (creation_time);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx5mnf0wn20tno4b9do88j61klr; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -476,13 +607,6 @@ CREATE INDEX idx1rcgkdd777bpvj0r94sltwd5y ON public."Domain" USING btree (fully_
|
||||
CREATE INDEX idx5mnf0wn20tno4b9do88j61klr ON public."Domain" USING btree (deletion_time);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx8ffrqm27qtj20jac056j7yq07; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idx8ffrqm27qtj20jac056j7yq07 ON public."Domain" USING btree (current_sponsor_client_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx8nr0ke9mrrx4ewj6pd2ag4rmr; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -504,6 +628,27 @@ CREATE INDEX idx_registry_lock_registrar_id ON public."RegistryLock" USING btree
|
||||
CREATE INDEX idx_registry_lock_verification_code ON public."RegistryLock" USING btree (verification_code);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idxbn8t4wp85fgxjl8q4ctlscx55; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idxbn8t4wp85fgxjl8q4ctlscx55 ON public."Contact" USING btree (current_sponsor_client_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idxkjt9yaq92876dstimd93hwckh; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idxkjt9yaq92876dstimd93hwckh ON public."Domain" USING btree (current_sponsor_client_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idxn1f711wicdnooa2mqb7g1m55o; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idxn1f711wicdnooa2mqb7g1m55o ON public."Contact" USING btree (deletion_time);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idxrwl38wwkli1j7gkvtywi9jokq; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -546,6 +691,22 @@ CREATE INDEX registrarpoc_gae_user_id_idx ON public."RegistrarPoc" USING btree (
|
||||
CREATE INDEX reservedlist_name_idx ON public."ReservedList" USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Contact fk1sfyj7o7954prbn1exk7lpnoe; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Contact"
|
||||
ADD CONSTRAINT fk1sfyj7o7954prbn1exk7lpnoe FOREIGN KEY (creation_client_id) REFERENCES public."Registrar"(client_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Domain fk2jc69qyg2tv9hhnmif6oa1cx1; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Domain"
|
||||
ADD CONSTRAINT fk2jc69qyg2tv9hhnmif6oa1cx1 FOREIGN KEY (creation_client_id) REFERENCES public."Registrar"(client_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: RegistryLock fk2lhcwpxlnqijr96irylrh1707; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -554,6 +715,14 @@ ALTER TABLE ONLY public."RegistryLock"
|
||||
ADD CONSTRAINT fk2lhcwpxlnqijr96irylrh1707 FOREIGN KEY (relock_revision_id) REFERENCES public."RegistryLock"(revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Domain fk2u3srsfbei272093m3b3xwj23; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Domain"
|
||||
ADD CONSTRAINT fk2u3srsfbei272093m3b3xwj23 FOREIGN KEY (current_sponsor_client_id) REFERENCES public."Registrar"(client_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ClaimsEntry fk6sc6at5hedffc0nhdcab6ivuq; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -562,6 +731,38 @@ ALTER TABLE ONLY public."ClaimsEntry"
|
||||
ADD CONSTRAINT fk6sc6at5hedffc0nhdcab6ivuq FOREIGN KEY (revision_id) REFERENCES public."ClaimsList"(revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: HostResource_inetAddresses fk6unwhfkcu3oq6q347fxvpagv; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."HostResource_inetAddresses"
|
||||
ADD CONSTRAINT fk6unwhfkcu3oq6q347fxvpagv FOREIGN KEY (host_resource_repo_id) REFERENCES public."HostResource"(repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Contact fk93c185fx7chn68uv7nl6uv2s0; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Contact"
|
||||
ADD CONSTRAINT fk93c185fx7chn68uv7nl6uv2s0 FOREIGN KEY (current_sponsor_client_id) REFERENCES public."Registrar"(client_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: DomainHost fk_domainhost_host_valid; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."DomainHost"
|
||||
ADD CONSTRAINT fk_domainhost_host_valid FOREIGN KEY (ns_host_v_keys) REFERENCES public."HostResource"(repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: DomainHost fkfmi7bdink53swivs390m2btxg; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."DomainHost"
|
||||
ADD CONSTRAINT fkfmi7bdink53swivs390m2btxg FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: ReservedEntry fkgq03rk0bt1hb915dnyvd3vnfc; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -570,6 +771,22 @@ ALTER TABLE ONLY public."ReservedEntry"
|
||||
ADD CONSTRAINT fkgq03rk0bt1hb915dnyvd3vnfc FOREIGN KEY (revision_id) REFERENCES public."ReservedList"(revision_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Domain fkjc0r9r5y1lfbt4gpbqw4wsuvq; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Domain"
|
||||
ADD CONSTRAINT fkjc0r9r5y1lfbt4gpbqw4wsuvq FOREIGN KEY (last_epp_update_client_id) REFERENCES public."Registrar"(client_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Contact fkmb7tdiv85863134w1wogtxrb2; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Contact"
|
||||
ADD CONSTRAINT fkmb7tdiv85863134w1wogtxrb2 FOREIGN KEY (last_epp_update_client_id) REFERENCES public."Registrar"(client_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: PremiumEntry fko0gw90lpo1tuee56l0nb6y6g5; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -78,6 +78,7 @@ ext {
|
||||
'com.googlecode.json-simple:json-simple:1.1.1',
|
||||
'com.ibm.icu:icu4j:57.1',
|
||||
'com.jcraft:jsch:0.1.55',
|
||||
'com.squareup:javapoet:1.12.1',
|
||||
'com.sun.activation:javax.activation:1.2.0',
|
||||
'com.sun.xml.bind:jaxb-impl:2.2.11',
|
||||
'com.sun.xml.bind:jaxb-osgi:2.2.11',
|
||||
|
||||
25
processor/build.gradle
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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.
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def deps = rootProject.dependencyMap
|
||||
compile deps['com.google.code.findbugs:jsr305']
|
||||
compile deps['com.google.guava:guava']
|
||||
compile deps['com.squareup:javapoet']
|
||||
compile deps['javax.persistence:javax.persistence-api']
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
3
processor/gradle/dependency-locks/apt.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
3
processor/gradle/dependency-locks/archives.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
18
processor/gradle/dependency-locks/checkstyle.lockfile
Normal file
@@ -0,0 +1,18 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
antlr:antlr:2.7.7
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.2
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.puppycrawl.tools:checkstyle:8.27
|
||||
commons-beanutils:commons-beanutils:1.9.4
|
||||
commons-collections:commons-collections:3.2.2
|
||||
info.picocli:picocli:4.1.1
|
||||
net.sf.saxon:Saxon-HE:9.9.1-5
|
||||
org.antlr:antlr4-runtime:4.7.2
|
||||
org.checkerframework:checker-qual:2.8.1
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.18
|
||||
12
processor/gradle/dependency-locks/compile.lockfile
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
12
processor/gradle/dependency-locks/compileClasspath.lockfile
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
3
processor/gradle/dependency-locks/compileOnly.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
12
processor/gradle/dependency-locks/default.lockfile
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
12
processor/gradle/dependency-locks/deploy_jar.lockfile
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
24
processor/gradle/dependency-locks/errorprone.lockfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
@@ -0,0 +1,4 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.errorprone:javac:9+181-r4173-1
|
||||
4
processor/gradle/dependency-locks/jacocoAgent.lockfile
Normal file
@@ -0,0 +1,4 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
11
processor/gradle/dependency-locks/jacocoAnt.lockfile
Normal file
@@ -0,0 +1,11 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
org.jacoco:org.jacoco.agent:0.8.5
|
||||
org.jacoco:org.jacoco.ant:0.8.5
|
||||
org.jacoco:org.jacoco.core:0.8.5
|
||||
org.jacoco:org.jacoco.report:0.8.5
|
||||
org.ow2.asm:asm-analysis:7.2
|
||||
org.ow2.asm:asm-commons:7.2
|
||||
org.ow2.asm:asm-tree:7.2
|
||||
org.ow2.asm:asm:7.2
|
||||
12
processor/gradle/dependency-locks/runtime.lockfile
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
12
processor/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
@@ -0,0 +1,24 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
3
processor/gradle/dependency-locks/testApt.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
12
processor/gradle/dependency-locks/testCompile.lockfile
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
@@ -0,0 +1,12 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||
@@ -0,0 +1,3 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
12
processor/gradle/dependency-locks/testRuntime.lockfile
Normal file
@@ -0,0 +1,12 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:28.2-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.3
|
||||
com.squareup:javapoet:1.12.1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
org.checkerframework:checker-qual:2.10.0
|
||||