diff --git a/core/src/main/java/google/registry/model/reporting/SafeBrowsingThreat.java b/core/src/main/java/google/registry/model/reporting/SafeBrowsingThreat.java new file mode 100644 index 000000000..653835a48 --- /dev/null +++ b/core/src/main/java/google/registry/model/reporting/SafeBrowsingThreat.java @@ -0,0 +1,168 @@ +// 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.model.reporting; + +import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; + +import com.google.common.collect.ImmutableList; +import google.registry.model.Buildable; +import google.registry.model.ImmutableObject; +import google.registry.schema.replay.DatastoreEntity; +import google.registry.schema.replay.SqlEntity; +import google.registry.util.DomainNameUtils; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Index; +import javax.persistence.Table; +import org.joda.time.LocalDate; + +@Entity +@Table( + indexes = { + @Index(name = "safebrowsing_threat_registrar_id_idx", columnList = "registrarId"), + @Index(name = "safebrowsing_threat_tld_idx", columnList = "tld"), + @Index(name = "safebrowsing_threat_check_date_idx", columnList = "checkDate") + }) +public class SafeBrowsingThreat extends ImmutableObject implements Buildable, SqlEntity { + + /** The type of threat detected. */ + public enum ThreatType { + THREAT_TYPE_UNSPECIFIED, + MALWARE, + SOCIAL_ENGINEERING, + UNWANTED_SOFTWARE, + POTENTIALLY_HARMFUL_APPLICATION + } + + /** An auto-generated identifier and unique primary key for this entity. */ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Long id; + + /** The name of the offending domain */ + @Column(nullable = false) + String domainName; + + /** The type of threat detected. */ + @Column(nullable = false) + @Enumerated(EnumType.STRING) + ThreatType threatType; + + /** Primary key of the domain table and unique identifier for all EPP resources. */ + @Column(nullable = false) + String domainRepoId; + + /** ID of the registrar at the moment of the scan. Domains may change registrars over time */ + @Column(nullable = false) + String registrarId; + + /** Date on which the check was run, on which the domain was flagged as abusive. */ + @Column(nullable = false) + LocalDate checkDate; + + /** The domain's top-level domain. */ + @Column(nullable = false) + String tld; + + public Long getId() { + return id; + } + + public String getDomainName() { + return domainName; + } + + public ThreatType getThreatType() { + return threatType; + } + + public String getDomainRepoId() { + return domainRepoId; + } + + public String getRegistrarId() { + return registrarId; + } + + public LocalDate getCheckDate() { + return checkDate; + } + + public String getTld() { + return tld; + } + + @Override + public ImmutableList toDatastoreEntities() { + return ImmutableList.of(); // not stored in Datastore + } + + @Override + public Builder asBuilder() { + return new Builder(clone(this)); + } + + /** A builder for constructing {@link SafeBrowsingThreat}, since it is immutable. */ + public static class Builder extends Buildable.Builder { + public Builder() {} + + private Builder(SafeBrowsingThreat instance) { + super(instance); + } + + @Override + public SafeBrowsingThreat build() { + checkArgumentNotNull(getInstance().domainName, "Domain name cannot be null"); + checkArgumentNotNull(getInstance().threatType, "Threat type cannot be null"); + checkArgumentNotNull(getInstance().domainRepoId, "Repo ID cannot be null"); + checkArgumentNotNull(getInstance().registrarId, "Registrar ID cannot be null"); + checkArgumentNotNull(getInstance().checkDate, "Check date cannot be null"); + checkArgumentNotNull(getInstance().tld, "TLD cannot be null"); + + return super.build(); + } + + public Builder setDomainName(String domainName) { + getInstance().domainName = domainName; + getInstance().tld = DomainNameUtils.getTldFromDomainName(domainName); + return this; + } + + public Builder setThreatType(ThreatType threatType) { + getInstance().threatType = threatType; + return this; + } + + public Builder setDomainRepoId(String domainRepoId) { + getInstance().domainRepoId = domainRepoId; + return this; + } + + public Builder setRegistrarId(String registrarId) { + getInstance().registrarId = registrarId; + return this; + } + + public Builder setCheckDate(LocalDate checkDate) { + getInstance().checkDate = checkDate; + return this; + } + } +} diff --git a/core/src/main/java/google/registry/persistence/converter/LocalDateConverter.java b/core/src/main/java/google/registry/persistence/converter/LocalDateConverter.java new file mode 100644 index 000000000..1721733c0 --- /dev/null +++ b/core/src/main/java/google/registry/persistence/converter/LocalDateConverter.java @@ -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.persistence.converter; + +import javax.persistence.Converter; +import org.joda.time.LocalDate; +import org.joda.time.format.ISODateTimeFormat; + +/** JPA converter for {@link LocalDate}. */ +@Converter(autoApply = true) +public class LocalDateConverter extends ToStringConverterBase { + + /** Converts the string (a date in ISO-8601 format) into a LocalDate. */ + @Override + public LocalDate convertToEntityAttribute(String columnValue) { + return (columnValue == null) ? null : LocalDate.parse(columnValue, ISODateTimeFormat.date()); + } +} diff --git a/core/src/main/resources/META-INF/persistence.xml b/core/src/main/resources/META-INF/persistence.xml index 61e7937b0..10d7c27cc 100644 --- a/core/src/main/resources/META-INF/persistence.xml +++ b/core/src/main/resources/META-INF/persistence.xml @@ -28,6 +28,7 @@ google.registry.model.host.HostResource google.registry.model.registrar.Registrar google.registry.model.registrar.RegistrarContact + google.registry.model.reporting.SafeBrowsingThreat google.registry.schema.domain.RegistryLock google.registry.schema.tmch.ClaimsList google.registry.schema.cursor.Cursor @@ -52,6 +53,7 @@ google.registry.persistence.converter.DateTimeConverter google.registry.persistence.converter.DurationConverter google.registry.persistence.converter.InetAddressSetConverter + google.registry.persistence.converter.LocalDateConverter google.registry.persistence.converter.PostalInfoChoiceListConverter google.registry.persistence.converter.RegistrarPocSetConverter google.registry.persistence.converter.StatusValueSetConverter diff --git a/core/src/test/java/google/registry/model/reporting/SafeBrowsingThreatTest.java b/core/src/test/java/google/registry/model/reporting/SafeBrowsingThreatTest.java new file mode 100644 index 000000000..fed37c19b --- /dev/null +++ b/core/src/test/java/google/registry/model/reporting/SafeBrowsingThreatTest.java @@ -0,0 +1,167 @@ +// 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.model.reporting; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.model.reporting.SafeBrowsingThreat.ThreatType.MALWARE; +import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; +import static google.registry.testing.DatastoreHelper.createTld; +import static google.registry.testing.SqlHelper.assertThrowForeignKeyViolation; +import static google.registry.testing.SqlHelper.saveRegistrar; +import static org.junit.Assert.assertThrows; + +import com.google.common.collect.ImmutableSet; +import google.registry.model.EntityTestCase; +import google.registry.model.contact.ContactResource; +import google.registry.model.domain.DomainBase; +import google.registry.model.host.HostResource; +import google.registry.model.transfer.ContactTransferData; +import google.registry.persistence.VKey; +import org.joda.time.LocalDate; +import org.joda.time.format.ISODateTimeFormat; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** Unit tests for {@link SafeBrowsingThreat}. */ +public class SafeBrowsingThreatTest extends EntityTestCase { + + private static final String REGISTRAR_ID = "registrar"; + private static final LocalDate DATE = LocalDate.parse("2020-06-10", ISODateTimeFormat.date()); + + private SafeBrowsingThreat threat; + private DomainBase domain; + private HostResource host; + private ContactResource registrantContact; + + public SafeBrowsingThreatTest() { + super(true); + } + + @BeforeEach + public void setUp() { + VKey hostVKey = VKey.createSql(HostResource.class, "host"); + VKey registrantContactVKey = + VKey.createSql(ContactResource.class, "contact_id"); + String domainRepoId = "4-TLD"; + createTld("tld"); + + /** Create a domain for the purpose of testing a foreign key reference in the Threat table. */ + domain = + new DomainBase() + .asBuilder() + .setCreationClientId(REGISTRAR_ID) + .setPersistedCurrentSponsorClientId(REGISTRAR_ID) + .setDomainName("foo.tld") + .setRepoId(domainRepoId) + .setNameservers(hostVKey) + .setRegistrant(registrantContactVKey) + .setContacts(ImmutableSet.of()) + .build(); + + /** Create a contact for the purpose of testing a foreign key reference in the Domain table. */ + registrantContact = + new ContactResource.Builder() + .setRepoId("contact_id") + .setCreationClientId(REGISTRAR_ID) + .setTransferData(new ContactTransferData.Builder().build()) + .setPersistedCurrentSponsorClientId(REGISTRAR_ID) + .build(); + + /** Create a host for the purpose of testing a foreign key reference in the Domain table. */ + host = + new HostResource.Builder() + .setRepoId("host") + .setHostName("ns1.example.com") + .setCreationClientId(REGISTRAR_ID) + .setPersistedCurrentSponsorClientId(REGISTRAR_ID) + .build(); + + threat = + new SafeBrowsingThreat.Builder() + .setThreatType(MALWARE) + .setCheckDate(DATE) + .setDomainName("foo.tld") + .setDomainRepoId(domainRepoId) + .setRegistrarId(REGISTRAR_ID) + .build(); + } + + @Test + public void testPersistence() { + saveRegistrar(REGISTRAR_ID); + + jpaTm() + .transact( + () -> { + jpaTm().saveNew(registrantContact); + jpaTm().saveNew(domain); + jpaTm().saveNew(host); + jpaTm().saveNew(threat); + }); + + VKey threatVKey = VKey.createSql(SafeBrowsingThreat.class, threat.getId()); + SafeBrowsingThreat persistedThreat = jpaTm().transact(() -> jpaTm().load(threatVKey)); + threat.id = persistedThreat.id; + assertThat(threat).isEqualTo(persistedThreat); + } + + @Test + public void testThreatForeignKeyConstraints() { + assertThrowForeignKeyViolation( + () -> { + jpaTm() + .transact( + () -> { + // Persist the threat without the associated registrar. + jpaTm().saveNew(host); + jpaTm().saveNew(registrantContact); + jpaTm().saveNew(domain); + jpaTm().saveNew(threat); + }); + }); + + saveRegistrar(REGISTRAR_ID); + + assertThrowForeignKeyViolation( + () -> { + jpaTm() + .transact( + () -> { + // Persist the threat without the associated domain. + jpaTm().saveNew(registrantContact); + jpaTm().saveNew(host); + jpaTm().saveNew(threat); + }); + }); + } + + @Test + public void testFailure_threatsWithNullFields() { + assertThrows( + IllegalArgumentException.class, () -> threat.asBuilder().setRegistrarId(null).build()); + + assertThrows( + IllegalArgumentException.class, () -> threat.asBuilder().setDomainName(null).build()); + + assertThrows( + IllegalArgumentException.class, () -> threat.asBuilder().setCheckDate(null).build()); + + assertThrows( + IllegalArgumentException.class, () -> threat.asBuilder().setThreatType(null).build()); + + assertThrows( + IllegalArgumentException.class, () -> threat.asBuilder().setDomainRepoId(null).build()); + } +} diff --git a/core/src/test/java/google/registry/persistence/converter/LocalDateConverterTest.java b/core/src/test/java/google/registry/persistence/converter/LocalDateConverterTest.java new file mode 100644 index 000000000..2310f2548 --- /dev/null +++ b/core/src/test/java/google/registry/persistence/converter/LocalDateConverterTest.java @@ -0,0 +1,79 @@ +// 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.model.ImmutableObject; +import google.registry.persistence.VKey; +import google.registry.persistence.transaction.JpaTestRules; +import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule; +import google.registry.schema.replay.EntityTest; +import javax.persistence.Entity; +import javax.persistence.Id; +import org.joda.time.LocalDate; +import org.joda.time.format.ISODateTimeFormat; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +/** Unit tests for {@link LocalDateConverter}. */ +public class LocalDateConverterTest { + + @RegisterExtension + public final JpaUnitTestRule jpaRule = + new JpaTestRules.Builder() + .withEntityClass(LocalDateConverterTestEntity.class) + .buildUnitTestRule(); + + private final LocalDate exampleDate = LocalDate.parse("2020-06-10", ISODateTimeFormat.date()); + + @Test + public void testNullInput() { + LocalDateConverterTestEntity retrievedEntity = persistAndLoadTestEntity(null); + assertThat(retrievedEntity.date).isNull(); + } + + @Test + public void testSaveAndLoad_success() { + LocalDateConverterTestEntity retrievedEntity = persistAndLoadTestEntity(exampleDate); + assertThat(retrievedEntity.date).isEqualTo(exampleDate); + } + + private LocalDateConverterTestEntity persistAndLoadTestEntity(LocalDate date) { + LocalDateConverterTestEntity entity = new LocalDateConverterTestEntity(date); + jpaTm().transact(() -> jpaTm().saveNew(entity)); + LocalDateConverterTestEntity retrievedEntity = + jpaTm() + .transact(() -> jpaTm().load(VKey.createSql(LocalDateConverterTestEntity.class, "id"))); + return retrievedEntity; + } + + /** Override entity name to avoid the nested class reference. */ + @Entity(name = "LocalDateConverterTestEntity") + @EntityTest.EntityForTesting + private static class LocalDateConverterTestEntity extends ImmutableObject { + + @Id String name = "id"; + + LocalDate date; + + public LocalDateConverterTestEntity() {} + + LocalDateConverterTestEntity(LocalDate date) { + this.date = date; + } + } +} diff --git a/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java b/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java index 343367115..9119c58ab 100644 --- a/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java +++ b/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java @@ -22,6 +22,7 @@ import google.registry.model.domain.DomainBaseSqlTest; import google.registry.model.history.HostHistoryTest; import google.registry.model.poll.PollMessageTest; import google.registry.model.registry.RegistryLockDaoTest; +import google.registry.model.reporting.SafeBrowsingThreatTest; import google.registry.persistence.transaction.JpaEntityCoverage; import google.registry.schema.cursor.CursorDaoTest; import google.registry.schema.integration.SqlIntegrationTestSuite.AfterSuiteTest; @@ -83,6 +84,7 @@ import org.junit.runner.RunWith; RegistrarDaoTest.class, RegistryLockDaoTest.class, ReservedListDaoTest.class, + SafeBrowsingThreatTest.class, // AfterSuiteTest must be the last entry. See class javadoc for details. AfterSuiteTest.class }) diff --git a/core/src/test/java/google/registry/testing/SqlHelper.java b/core/src/test/java/google/registry/testing/SqlHelper.java index e5f6d3200..52136e76e 100644 --- a/core/src/test/java/google/registry/testing/SqlHelper.java +++ b/core/src/test/java/google/registry/testing/SqlHelper.java @@ -25,7 +25,7 @@ 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 javax.persistence.PersistenceException; import org.junit.function.ThrowingRunnable; /** Static utils for setting up and retrieving test resources from the SQL database. */ @@ -66,7 +66,7 @@ public class SqlHelper { } public static void assertThrowForeignKeyViolation(ThrowingRunnable runnable) { - RollbackException thrown = assertThrows(RollbackException.class, runnable); + PersistenceException thrown = assertThrows(PersistenceException.class, runnable); assertThat(Throwables.getRootCause(thrown)).isInstanceOf(SQLException.class); assertThat(Throwables.getRootCause(thrown)) .hasMessageThat() diff --git a/db/src/main/resources/sql/flyway/V36__create_safebrowsing_threats.sql b/db/src/main/resources/sql/flyway/V36__create_safebrowsing_threats.sql new file mode 100644 index 000000000..9729920ac --- /dev/null +++ b/db/src/main/resources/sql/flyway/V36__create_safebrowsing_threats.sql @@ -0,0 +1,38 @@ +-- 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 "SafeBrowsingThreat" ( + id bigserial not null, + check_date text not null, + domain_name text not null, + domain_repo_id text not null, + registrar_id text not null, + threat_type text not null, + tld text not null, + primary key (id) + ); + +create index safebrowsing_threat_registrar_id_idx on "SafeBrowsingThreat" (registrar_id); +create index safebrowsing_threat_tld_idx on "SafeBrowsingThreat" (tld); +create index safebrowsing_threat_check_date_idx on "SafeBrowsingThreat" (check_date); + +alter table if exists "SafeBrowsingThreat" + add constraint fk_safebrowsing_threat_registrar_id + foreign key (registrar_id) + references "Registrar"; + +alter table if exists "SafeBrowsingThreat" + add constraint fk_safebrowsing_threat_domain_repo_id + foreign key (domain_repo_id) + references "Domain"; diff --git a/db/src/main/resources/sql/schema/db-schema.sql.generated b/db/src/main/resources/sql/schema/db-schema.sql.generated index 6cd40ffcf..c50ffc2f6 100644 --- a/db/src/main/resources/sql/schema/db-schema.sql.generated +++ b/db/src/main/resources/sql/schema/db-schema.sql.generated @@ -407,6 +407,17 @@ create sequence history_id_sequence start 1 increment 1; should_publish boolean not null, primary key (revision_id) ); + + create table "SafeBrowsingThreat" ( + id bigserial not null, + check_date text not null, + domain_name text not null, + domain_repo_id text not null, + registrar_id text not null, + threat_type text not null, + tld text not null, + primary key (id) + ); create index IDXih4b2tea127p5rb61gje6e1y2 on "BillingCancellation" (registrar_id); create index IDX2exdfbx6oiiwnhr8j6gjpqt2j on "BillingCancellation" (event_time); create index IDXqa3g92jc17e8dtiaviy4fet4x on "BillingCancellation" (billing_time); @@ -448,6 +459,9 @@ create index idx_registry_lock_registrar_id on "RegistryLock" (registrar_id); alter table if exists "RegistryLock" add constraint idx_registry_lock_repo_id_revision_id unique (repo_id, revision_id); create index reservedlist_name_idx on "ReservedList" (name); +create index safebrowsing_threat_registrar_id_idx on "SafeBrowsingThreat" (registrar_id); +create index safebrowsing_threat_tld_idx on "SafeBrowsingThreat" (tld); +create index safebrowsing_threat_check_date_idx on "SafeBrowsingThreat" (check_date); alter table if exists "ClaimsEntry" add constraint FK6sc6at5hedffc0nhdcab6ivuq diff --git a/db/src/main/resources/sql/schema/nomulus.golden.sql b/db/src/main/resources/sql/schema/nomulus.golden.sql index 63253c14f..5d781de6c 100644 --- a/db/src/main/resources/sql/schema/nomulus.golden.sql +++ b/db/src/main/resources/sql/schema/nomulus.golden.sql @@ -656,6 +656,40 @@ CREATE SEQUENCE public."ReservedList_revision_id_seq" ALTER SEQUENCE public."ReservedList_revision_id_seq" OWNED BY public."ReservedList".revision_id; +-- +-- Name: SafeBrowsingThreat; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public."SafeBrowsingThreat" ( + id bigint NOT NULL, + check_date text NOT NULL, + domain_name text NOT NULL, + domain_repo_id text NOT NULL, + registrar_id text NOT NULL, + threat_type text NOT NULL, + tld text NOT NULL +); + + +-- +-- Name: SafeBrowsingThreat_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public."SafeBrowsingThreat_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: SafeBrowsingThreat_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public."SafeBrowsingThreat_id_seq" OWNED BY public."SafeBrowsingThreat".id; + + -- -- Name: BillingCancellation billing_cancellation_id; Type: DEFAULT; Schema: public; Owner: - -- @@ -712,6 +746,13 @@ ALTER TABLE ONLY public."RegistryLock" ALTER COLUMN revision_id SET DEFAULT next ALTER TABLE ONLY public."ReservedList" ALTER COLUMN revision_id SET DEFAULT nextval('public."ReservedList_revision_id_seq"'::regclass); +-- +-- Name: SafeBrowsingThreat id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public."SafeBrowsingThreat" ALTER COLUMN id SET DEFAULT nextval('public."SafeBrowsingThreat_id_seq"'::regclass); + + -- -- Name: BillingCancellation BillingCancellation_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -864,6 +905,14 @@ ALTER TABLE ONLY public."ReservedList" ADD CONSTRAINT "ReservedList_pkey" PRIMARY KEY (revision_id); +-- +-- Name: SafeBrowsingThreat SafeBrowsingThreat_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public."SafeBrowsingThreat" + ADD CONSTRAINT "SafeBrowsingThreat_pkey" PRIMARY KEY (id); + + -- -- Name: RegistryLock idx_registry_lock_repo_id_revision_id; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -1125,6 +1174,27 @@ CREATE INDEX registrarpoc_gae_user_id_idx ON public."RegistrarPoc" USING btree ( CREATE INDEX reservedlist_name_idx ON public."ReservedList" USING btree (name); +-- +-- Name: safebrowsing_threat_check_date_idx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX safebrowsing_threat_check_date_idx ON public."SafeBrowsingThreat" USING btree (check_date); + + +-- +-- Name: safebrowsing_threat_registrar_id_idx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX safebrowsing_threat_registrar_id_idx ON public."SafeBrowsingThreat" USING btree (registrar_id); + + +-- +-- Name: safebrowsing_threat_tld_idx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX safebrowsing_threat_tld_idx ON public."SafeBrowsingThreat" USING btree (tld); + + -- -- Name: Contact fk1sfyj7o7954prbn1exk7lpnoe; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -1389,6 +1459,22 @@ ALTER TABLE ONLY public."PollMessage" ADD CONSTRAINT fk_poll_message_transfer_response_losing_registrar_id FOREIGN KEY (transfer_response_losing_registrar_id) REFERENCES public."Registrar"(registrar_id); +-- +-- Name: SafeBrowsingThreat fk_safebrowsing_threat_domain_repo_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public."SafeBrowsingThreat" + ADD CONSTRAINT fk_safebrowsing_threat_domain_repo_id FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id); + + +-- +-- Name: SafeBrowsingThreat fk_safebrowsing_threat_registrar_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public."SafeBrowsingThreat" + ADD CONSTRAINT fk_safebrowsing_threat_registrar_id FOREIGN KEY (registrar_id) REFERENCES public."Registrar"(registrar_id); + + -- -- Name: DomainHost fkfmi7bdink53swivs390m2btxg; Type: FK CONSTRAINT; Schema: public; Owner: - --