mirror of
https://github.com/google/nomulus.git
synced 2025-05-19 10:49:35 +02:00
Add Cloud SQL schema for premium lists (#254)
* Re-add other schema classes * Add Cloud SQL schema for premium lists This won't work quite yet, pending a solution for the type translator issue (which will be needed for the currency field, and potentially others).
This commit is contained in:
parent
859b70098c
commit
ded6d38223
7 changed files with 192 additions and 14 deletions
102
core/src/main/java/google/registry/schema/tld/PremiumList.java
Normal file
102
core/src/main/java/google/registry/schema/tld/PremiumList.java
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
// Copyright 2019 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.tld;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.CollectionTable;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import org.joda.money.CurrencyUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of premium prices for domain names.
|
||||||
|
*
|
||||||
|
* <p>Note that the primary key of this entity is {@link #revisionId}, which is auto-generated by
|
||||||
|
* the database. So, if a retry of insertion happens after the previous attempt unexpectedly
|
||||||
|
* succeeds, we will end up with having two exact same premium lists that differ only by revisionId.
|
||||||
|
* This is fine though, because we only use the list with the highest revisionId.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "PremiumList")
|
||||||
|
public class PremiumList {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "revision_id")
|
||||||
|
private Long revisionId;
|
||||||
|
|
||||||
|
@Column(name = "creation_timestamp", nullable = false)
|
||||||
|
private ZonedDateTime creationTimestamp;
|
||||||
|
|
||||||
|
@Column(name = "currency", nullable = false)
|
||||||
|
private CurrencyUnit currency;
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@CollectionTable(
|
||||||
|
name = "PremiumEntry",
|
||||||
|
joinColumns = @JoinColumn(name = "revision_id", referencedColumnName = "revision_id"))
|
||||||
|
@MapKeyColumn(name = "domain_label")
|
||||||
|
@Column(name = "price", nullable = false)
|
||||||
|
private Map<String, BigDecimal> labelsToPrices;
|
||||||
|
|
||||||
|
private PremiumList(
|
||||||
|
ZonedDateTime creationTimestamp,
|
||||||
|
CurrencyUnit currency,
|
||||||
|
Map<String, BigDecimal> labelsToPrices) {
|
||||||
|
this.creationTimestamp = creationTimestamp;
|
||||||
|
this.currency = currency;
|
||||||
|
this.labelsToPrices = labelsToPrices;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hibernate requires this default constructor.
|
||||||
|
private PremiumList() {}
|
||||||
|
|
||||||
|
// TODO(mcilwain): Change creationTimestamp to Joda DateTime.
|
||||||
|
/** Constructs a {@link PremiumList} object. */
|
||||||
|
public static PremiumList create(
|
||||||
|
ZonedDateTime creationTimestamp,
|
||||||
|
CurrencyUnit currency,
|
||||||
|
Map<String, BigDecimal> labelsToPrices) {
|
||||||
|
return new PremiumList(creationTimestamp, currency, labelsToPrices);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the ID of this revision, or throws if null. */
|
||||||
|
public Long getRevisionId() {
|
||||||
|
checkState(
|
||||||
|
revisionId != null, "revisionId is null because it is not persisted in the database");
|
||||||
|
return revisionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the creation time of this revision of the premium list. */
|
||||||
|
public ZonedDateTime getCreationTimestamp() {
|
||||||
|
return creationTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a {@link Map} of domain labels to prices. */
|
||||||
|
public Map<String, BigDecimal> getLabelsToPrices() {
|
||||||
|
return labelsToPrices;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import com.beust.jcommander.Parameter;
|
import com.beust.jcommander.Parameter;
|
||||||
import com.beust.jcommander.Parameters;
|
import com.beust.jcommander.Parameters;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import google.registry.model.domain.DesignatedContact;
|
import google.registry.model.domain.DesignatedContact;
|
||||||
import google.registry.model.domain.DomainBase;
|
import google.registry.model.domain.DomainBase;
|
||||||
import google.registry.model.domain.GracePeriod;
|
import google.registry.model.domain.GracePeriod;
|
||||||
|
@ -26,6 +27,8 @@ import google.registry.model.domain.secdns.DelegationSignerData;
|
||||||
import google.registry.model.eppcommon.Trid;
|
import google.registry.model.eppcommon.Trid;
|
||||||
import google.registry.model.transfer.BaseTransferObject;
|
import google.registry.model.transfer.BaseTransferObject;
|
||||||
import google.registry.model.transfer.TransferData;
|
import google.registry.model.transfer.TransferData;
|
||||||
|
import google.registry.schema.tld.PremiumList;
|
||||||
|
import google.registry.schema.tmch.ClaimsList;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
@ -49,6 +52,21 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
||||||
@Parameters(separators = " =", commandDescription = "Generate PostgreSQL schema.")
|
@Parameters(separators = " =", commandDescription = "Generate PostgreSQL schema.")
|
||||||
public class GenerateSqlSchemaCommand implements Command {
|
public class GenerateSqlSchemaCommand implements Command {
|
||||||
|
|
||||||
|
// TODO(mmuller): These should be read from persistence.xml so we don't need to maintain two
|
||||||
|
// separate lists of all SQL table classes.
|
||||||
|
private static final ImmutableSet<Class> SQL_TABLE_CLASSES =
|
||||||
|
ImmutableSet.of(
|
||||||
|
BaseTransferObject.class,
|
||||||
|
ClaimsList.class,
|
||||||
|
DelegationSignerData.class,
|
||||||
|
DesignatedContact.class,
|
||||||
|
DomainBase.class,
|
||||||
|
GracePeriod.class,
|
||||||
|
Period.class,
|
||||||
|
PremiumList.class,
|
||||||
|
TransferData.class,
|
||||||
|
Trid.class);
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static final String DB_OPTIONS_CLASH =
|
public static final String DB_OPTIONS_CLASH =
|
||||||
"Database host and port may not be specified along with the option to start a "
|
"Database host and port may not be specified along with the option to start a "
|
||||||
|
@ -109,8 +127,7 @@ public class GenerateSqlSchemaCommand implements Command {
|
||||||
+ " -d postgres:9.6.12\n\n"
|
+ " -d postgres:9.6.12\n\n"
|
||||||
+ "Copy the container id output from the command, then run:\n\n"
|
+ "Copy the container id output from the command, then run:\n\n"
|
||||||
+ " docker inspect <container-id> | grep IPAddress\n\n"
|
+ " docker inspect <container-id> | grep IPAddress\n\n"
|
||||||
+ "To obtain the value for --db-host.\n"
|
+ "To obtain the value for --db-host.\n");
|
||||||
);
|
|
||||||
// TODO(mmuller): need exit(1), see above.
|
// TODO(mmuller): need exit(1), see above.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -134,14 +151,7 @@ public class GenerateSqlSchemaCommand implements Command {
|
||||||
|
|
||||||
MetadataSources metadata =
|
MetadataSources metadata =
|
||||||
new MetadataSources(new StandardServiceRegistryBuilder().applySettings(settings).build());
|
new MetadataSources(new StandardServiceRegistryBuilder().applySettings(settings).build());
|
||||||
metadata.addAnnotatedClass(BaseTransferObject.class);
|
SQL_TABLE_CLASSES.forEach(metadata::addAnnotatedClass);
|
||||||
metadata.addAnnotatedClass(DelegationSignerData.class);
|
|
||||||
metadata.addAnnotatedClass(DesignatedContact.class);
|
|
||||||
metadata.addAnnotatedClass(DomainBase.class);
|
|
||||||
metadata.addAnnotatedClass(GracePeriod.class);
|
|
||||||
metadata.addAnnotatedClass(Period.class);
|
|
||||||
metadata.addAnnotatedClass(TransferData.class);
|
|
||||||
metadata.addAnnotatedClass(Trid.class);
|
|
||||||
SchemaExport schemaExport = new SchemaExport();
|
SchemaExport schemaExport = new SchemaExport();
|
||||||
schemaExport.setHaltOnError(true);
|
schemaExport.setHaltOnError(true);
|
||||||
schemaExport.setFormat(true);
|
schemaExport.setFormat(true);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
<class>google.registry.model.domain.DomainBase</class>
|
<class>google.registry.model.domain.DomainBase</class>
|
||||||
<class>google.registry.schema.tmch.ClaimsList</class>
|
<class>google.registry.schema.tmch.ClaimsList</class>
|
||||||
<class>google.registry.model.transfer.BaseTransferObject</class>
|
<class>google.registry.model.transfer.BaseTransferObject</class>
|
||||||
|
<class>google.registry.schema.tld.PremiumList</class>
|
||||||
<class>google.registry.model.domain.secdns.DelegationSignerData</class>
|
<class>google.registry.model.domain.secdns.DelegationSignerData</class>
|
||||||
<class>google.registry.model.domain.DesignatedContact</class>
|
<class>google.registry.model.domain.DesignatedContact</class>
|
||||||
<class>google.registry.model.domain.DomainBase</class>
|
<class>google.registry.model.domain.DomainBase</class>
|
||||||
|
|
|
@ -27,7 +27,6 @@ import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.JUnit4;
|
import org.junit.runners.JUnit4;
|
||||||
import org.testcontainers.containers.PostgreSQLContainer;
|
import org.testcontainers.containers.PostgreSQLContainer;
|
||||||
|
|
||||||
|
|
||||||
/** Unit tests for {@link google.registry.tools.GenerateSqlSchemaCommand}. */
|
/** Unit tests for {@link google.registry.tools.GenerateSqlSchemaCommand}. */
|
||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
public class GenerateSqlSchemaCommandTest extends CommandTestCase<GenerateSqlSchemaCommand> {
|
public class GenerateSqlSchemaCommandTest extends CommandTestCase<GenerateSqlSchemaCommand> {
|
||||||
|
@ -77,8 +76,7 @@ public class GenerateSqlSchemaCommandTest extends CommandTestCase<GenerateSqlSch
|
||||||
@Test
|
@Test
|
||||||
public void testDockerPostgresql() throws Exception {
|
public void testDockerPostgresql() throws Exception {
|
||||||
runCommand(
|
runCommand(
|
||||||
"--start_postgresql",
|
"--start_postgresql", "--out_file=" + tmp.getRoot() + File.separatorChar + "schema.sql");
|
||||||
"--out_file=" + tmp.getRoot() + File.separatorChar + "schema.sql");
|
|
||||||
assertThat(new File(tmp.getRoot(), "schema.sql").exists()).isTrue();
|
assertThat(new File(tmp.getRoot(), "schema.sql").exists()).isTrue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,9 @@ public class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
|
||||||
@Test
|
@Test
|
||||||
public void settingsContactItem_asAdmin() throws Throwable {
|
public void settingsContactItem_asAdmin() throws Throwable {
|
||||||
server.setIsAdmin(true);
|
server.setIsAdmin(true);
|
||||||
driver.get(server.getUrl("/registrar?clientId=NewRegistrar#contact-settings/janedoe@theregistrar.com"));
|
driver.get(
|
||||||
|
server.getUrl(
|
||||||
|
"/registrar?clientId=NewRegistrar#contact-settings/janedoe@theregistrar.com"));
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
driver.waitForElement(By.tagName("h1"));
|
driver.waitForElement(By.tagName("h1"));
|
||||||
driver.diffPage("page");
|
driver.diffPage("page");
|
||||||
|
|
|
@ -12,6 +12,19 @@
|
||||||
-- See the License for the specific language governing permissions and
|
-- See the License for the specific language governing permissions and
|
||||||
-- limitations under the License.
|
-- limitations under the License.
|
||||||
|
|
||||||
|
create table ClaimsEntry (
|
||||||
|
revision_id int8 not null,
|
||||||
|
claim_key varchar(255) not null,
|
||||||
|
domain_label varchar(255) not null,
|
||||||
|
primary key (revision_id, domain_label)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table ClaimsList (
|
||||||
|
revision_id bigserial not null,
|
||||||
|
creation_timestamp timestamp not null,
|
||||||
|
primary key (revision_id)
|
||||||
|
);
|
||||||
|
|
||||||
create table DelegationSignerData (
|
create table DelegationSignerData (
|
||||||
keyTag int4 not null,
|
keyTag int4 not null,
|
||||||
algorithm int4 not null,
|
algorithm int4 not null,
|
||||||
|
@ -108,6 +121,20 @@
|
||||||
primary key (id)
|
primary key (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create table PremiumEntry (
|
||||||
|
revision_id int8 not null,
|
||||||
|
price numeric(19, 2) not null,
|
||||||
|
domain_label varchar(255) not null,
|
||||||
|
primary key (revision_id, domain_label)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table PremiumList (
|
||||||
|
revision_id bigserial not null,
|
||||||
|
creation_timestamp timestamp not null,
|
||||||
|
currency bytea not null,
|
||||||
|
primary key (revision_id)
|
||||||
|
);
|
||||||
|
|
||||||
alter table domain_DelegationSignerData
|
alter table domain_DelegationSignerData
|
||||||
add constraint UK_q2uk7gpqskey3t2w11w2o7x9f unique (dsData_keyTag);
|
add constraint UK_q2uk7gpqskey3t2w11w2o7x9f unique (dsData_keyTag);
|
||||||
|
|
||||||
|
@ -117,6 +144,11 @@
|
||||||
alter table domain_GracePeriod
|
alter table domain_GracePeriod
|
||||||
add constraint UK_74osb0s7br4x734ecpdk8caxx unique (gracePeriods_id);
|
add constraint UK_74osb0s7br4x734ecpdk8caxx unique (gracePeriods_id);
|
||||||
|
|
||||||
|
alter table ClaimsEntry
|
||||||
|
add constraint FKlugn0q07ayrtar87dqi3vs3c8
|
||||||
|
foreign key (revision_id)
|
||||||
|
references ClaimsList;
|
||||||
|
|
||||||
alter table domain_DelegationSignerData
|
alter table domain_DelegationSignerData
|
||||||
add constraint FK6p262lfef34yht2ok65rqfoiy
|
add constraint FK6p262lfef34yht2ok65rqfoiy
|
||||||
foreign key (dsData_keyTag)
|
foreign key (dsData_keyTag)
|
||||||
|
@ -161,3 +193,8 @@
|
||||||
add constraint FK3p6gm6lbx46s41hl9wfme77sr
|
add constraint FK3p6gm6lbx46s41hl9wfme77sr
|
||||||
foreign key (DomainBase_repoId)
|
foreign key (DomainBase_repoId)
|
||||||
references domain;
|
references domain;
|
||||||
|
|
||||||
|
alter table PremiumEntry
|
||||||
|
add constraint FKqebdja3jkx9c9cnqnrw9g9ocu
|
||||||
|
foreign key (revision_id)
|
||||||
|
references PremiumList;
|
||||||
|
|
28
db/src/main/resources/sql/schema/premium_list.sql
Normal file
28
db/src/main/resources/sql/schema/premium_list.sql
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
-- Copyright 2019 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 "PremiumList" (
|
||||||
|
revision_id BIGSERIAL NOT NULL,
|
||||||
|
creation_timestamp TIMESTAMPTZ NOT NULL,
|
||||||
|
currency TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (revision_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "PremiumEntry" (
|
||||||
|
revision_id BIGSERIAL NOT NULL,
|
||||||
|
price NUMERIC(12, 2) NOT NULL,
|
||||||
|
domain_label TEXT NOT NULL,
|
||||||
|
primary key (revision_id, domain_label),
|
||||||
|
FOREIGN KEY (revision_id) REFERENCES "PremiumList"(revision_id)
|
||||||
|
);
|
Loading…
Add table
Add a link
Reference in a new issue