mirror of
https://github.com/google/nomulus.git
synced 2025-05-22 20:29:36 +02:00
Change primary key of DelegationSignerData and add its history table (#841)
* Change primary key of DelegationSignerData and add its history table * Change primary key and resolve comments * Rebase on HEAD
This commit is contained in:
parent
2000ea2d60
commit
b8d913ef64
14 changed files with 4405 additions and 3505 deletions
|
@ -14,14 +14,17 @@
|
||||||
|
|
||||||
package google.registry.model.domain;
|
package google.registry.model.domain;
|
||||||
|
|
||||||
|
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||||
import com.googlecode.objectify.annotation.Ignore;
|
import com.googlecode.objectify.annotation.Ignore;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||||
|
import google.registry.model.domain.secdns.DomainDsDataHistory;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.model.reporting.DomainTransactionRecord;
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
@ -40,10 +43,12 @@ import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.IdClass;
|
import javax.persistence.IdClass;
|
||||||
import javax.persistence.Index;
|
import javax.persistence.Index;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.JoinColumns;
|
||||||
import javax.persistence.JoinTable;
|
import javax.persistence.JoinTable;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.PostLoad;
|
import javax.persistence.PostLoad;
|
||||||
|
@ -95,6 +100,24 @@ public class DomainHistory extends HistoryEntry implements SqlEntity {
|
||||||
@Column(name = "host_repo_id")
|
@Column(name = "host_repo_id")
|
||||||
Set<VKey<HostResource>> nsHosts;
|
Set<VKey<HostResource>> nsHosts;
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
cascade = {CascadeType.ALL},
|
||||||
|
fetch = FetchType.EAGER,
|
||||||
|
orphanRemoval = true)
|
||||||
|
@JoinColumns({
|
||||||
|
@JoinColumn(
|
||||||
|
name = "domainHistoryRevisionId",
|
||||||
|
referencedColumnName = "historyRevisionId",
|
||||||
|
insertable = false,
|
||||||
|
updatable = false),
|
||||||
|
@JoinColumn(
|
||||||
|
name = "domainRepoId",
|
||||||
|
referencedColumnName = "domainRepoId",
|
||||||
|
insertable = false,
|
||||||
|
updatable = false)
|
||||||
|
})
|
||||||
|
Set<DomainDsDataHistory> dsDataHistories;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
@Access(AccessType.PROPERTY)
|
@Access(AccessType.PROPERTY)
|
||||||
|
@ -162,6 +185,11 @@ public class DomainHistory extends HistoryEntry implements SqlEntity {
|
||||||
return nsHosts;
|
return nsHosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the collection of {@link DomainDsDataHistory} instances. */
|
||||||
|
public ImmutableSet<DomainDsDataHistory> getDsDataHistories() {
|
||||||
|
return nullToEmptyImmutableCopy(dsDataHistories);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The values of all the fields on the {@link DomainContent} object after the action represented
|
* The values of all the fields on the {@link DomainContent} object after the action represented
|
||||||
* by this history object was executed.
|
* by this history object was executed.
|
||||||
|
@ -278,9 +306,6 @@ public class DomainHistory extends HistoryEntry implements SqlEntity {
|
||||||
|
|
||||||
public Builder setDomainContent(DomainContent domainContent) {
|
public Builder setDomainContent(DomainContent domainContent) {
|
||||||
getInstance().domainContent = domainContent;
|
getInstance().domainContent = domainContent;
|
||||||
if (domainContent != null) {
|
|
||||||
getInstance().nsHosts = nullToEmptyImmutableCopy(domainContent.nsHosts);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,5 +313,22 @@ public class DomainHistory extends HistoryEntry implements SqlEntity {
|
||||||
getInstance().parent = Key.create(DomainBase.class, domainRepoId);
|
getInstance().parent = Key.create(DomainBase.class, domainRepoId);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainHistory build() {
|
||||||
|
DomainHistory instance = super.build();
|
||||||
|
// TODO(b/171990736): Assert instance.domainContent is not null after database migration.
|
||||||
|
// Note that we cannot assert that instance.domainContent is not null here because this
|
||||||
|
// builder is also used to convert legacy HistoryEntry objects to DomainHistory, when
|
||||||
|
// domainContent is not available.
|
||||||
|
if (instance.domainContent != null) {
|
||||||
|
instance.nsHosts = nullToEmptyImmutableCopy(instance.domainContent.nsHosts);
|
||||||
|
instance.dsDataHistories =
|
||||||
|
nullToEmptyImmutableCopy(instance.domainContent.getDsData()).stream()
|
||||||
|
.map(dsData -> DomainDsDataHistory.createFrom(instance.id, dsData))
|
||||||
|
.collect(toImmutableSet());
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,89 +17,68 @@ package google.registry.model.domain.secdns;
|
||||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||||
|
|
||||||
import com.googlecode.objectify.annotation.Embed;
|
import com.googlecode.objectify.annotation.Embed;
|
||||||
import com.googlecode.objectify.annotation.Ignore;
|
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.domain.secdns.DelegationSignerData.DelegationSignerDataId;
|
import google.registry.model.domain.secdns.DelegationSignerData.DomainDsDataId;
|
||||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Access;
|
||||||
|
import javax.persistence.AccessType;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
import javax.persistence.IdClass;
|
import javax.persistence.IdClass;
|
||||||
import javax.persistence.Index;
|
import javax.persistence.Index;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
|
||||||
import javax.xml.bind.annotation.XmlTransient;
|
|
||||||
import javax.xml.bind.annotation.XmlType;
|
import javax.xml.bind.annotation.XmlType;
|
||||||
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
|
|
||||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the data necessary to construct a single Delegation Signer (DS) record for a domain.
|
* Holds the data necessary to construct a single Delegation Signer (DS) record for a domain.
|
||||||
*
|
*
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc5910">RFC 5910</a>
|
* @see <a href="http://tools.ietf.org/html/rfc5910">RFC 5910</a>
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc4034">RFC 4034</a>
|
* @see <a href="http://tools.ietf.org/html/rfc4034">RFC 4034</a>
|
||||||
|
* <p>TODO(shicong): Rename this class to DomainDsData.
|
||||||
*/
|
*/
|
||||||
@Embed
|
@Embed
|
||||||
@XmlType(name = "dsData")
|
@XmlType(name = "dsData")
|
||||||
@Entity
|
@Entity
|
||||||
|
@IdClass(DomainDsDataId.class)
|
||||||
@Table(indexes = @Index(columnList = "domainRepoId"))
|
@Table(indexes = @Index(columnList = "domainRepoId"))
|
||||||
@IdClass(DelegationSignerDataId.class)
|
public class DelegationSignerData extends DomainDsDataBase {
|
||||||
public class DelegationSignerData extends ImmutableObject implements DatastoreAndSqlEntity {
|
|
||||||
|
|
||||||
private DelegationSignerData() {}
|
private DelegationSignerData() {}
|
||||||
|
|
||||||
@Ignore @XmlTransient @javax.persistence.Id String domainRepoId;
|
@Override
|
||||||
|
@Id
|
||||||
/** The identifier for this particular key in the domain. */
|
@Access(AccessType.PROPERTY)
|
||||||
@javax.persistence.Id
|
public String getDomainRepoId() {
|
||||||
@Column(nullable = false)
|
return super.getDomainRepoId();
|
||||||
int keyTag;
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The algorithm used by this key.
|
|
||||||
*
|
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.1">RFC 4034 Appendix A.1</a>
|
|
||||||
*/
|
|
||||||
@Column(nullable = false)
|
|
||||||
@XmlElement(name = "alg")
|
|
||||||
int algorithm;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The algorithm used to generate the digest.
|
|
||||||
*
|
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.2">RFC 4034 Appendix A.2</a>
|
|
||||||
*/
|
|
||||||
@Column(nullable = false)
|
|
||||||
int digestType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The hexBinary digest of the public key.
|
|
||||||
*
|
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc4034#section-5.1.4">RFC 4034 Section 5.1.4</a>
|
|
||||||
*/
|
|
||||||
@Column(nullable = false)
|
|
||||||
@XmlJavaTypeAdapter(HexBinaryAdapter.class)
|
|
||||||
byte[] digest;
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Id
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
public int getKeyTag() {
|
public int getKeyTag() {
|
||||||
return keyTag;
|
return super.getKeyTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Id
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
public int getAlgorithm() {
|
public int getAlgorithm() {
|
||||||
return algorithm;
|
return super.getAlgorithm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Id
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
public int getDigestType() {
|
public int getDigestType() {
|
||||||
return digestType;
|
return super.getDigestType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Id
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
public byte[] getDigest() {
|
public byte[] getDigest() {
|
||||||
return digest;
|
return super.getDigest();
|
||||||
}
|
|
||||||
|
|
||||||
public String getDigestAsString() {
|
|
||||||
return digest == null ? "" : DatatypeConverter.printHexBinary(digest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DelegationSignerData cloneWithDomainRepoId(String domainRepoId) {
|
public DelegationSignerData cloneWithDomainRepoId(String domainRepoId) {
|
||||||
|
@ -135,30 +114,135 @@ public class DelegationSignerData extends ImmutableObject implements DatastoreAn
|
||||||
return create(keyTag, algorithm, digestType, DatatypeConverter.parseHexBinary(digestAsHex));
|
return create(keyTag, algorithm, digestType, DatatypeConverter.parseHexBinary(digestAsHex));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Class to represent the composite primary key of {@link DelegationSignerData} entity. */
|
||||||
* Returns the presentation format of this DS record.
|
static class DomainDsDataId extends ImmutableObject implements Serializable {
|
||||||
*
|
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc4034#section-5.3">RFC 4034 Section 5.3</a>
|
|
||||||
*/
|
|
||||||
public String toRrData() {
|
|
||||||
return String.format(
|
|
||||||
"%d %d %d %s",
|
|
||||||
this.keyTag, this.algorithm, this.digestType, DatatypeConverter.printHexBinary(digest));
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DelegationSignerDataId extends ImmutableObject implements Serializable {
|
|
||||||
String domainRepoId;
|
String domainRepoId;
|
||||||
|
|
||||||
int keyTag;
|
int keyTag;
|
||||||
|
|
||||||
private DelegationSignerDataId() {}
|
int algorithm;
|
||||||
|
|
||||||
private DelegationSignerDataId(String domainRepoId, int keyTag) {
|
int digestType;
|
||||||
|
|
||||||
|
byte[] digest;
|
||||||
|
|
||||||
|
/** Hibernate requires this default constructor. */
|
||||||
|
private DomainDsDataId() {}
|
||||||
|
|
||||||
|
/** Constructs a {link DomainDsDataId} instance. */
|
||||||
|
DomainDsDataId(String domainRepoId, int keyTag, int algorithm, int digestType, byte[] digest) {
|
||||||
this.domainRepoId = domainRepoId;
|
this.domainRepoId = domainRepoId;
|
||||||
this.keyTag = keyTag;
|
this.keyTag = keyTag;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.digestType = digestType;
|
||||||
|
this.digest = digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the domain repository ID.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private String getDomainRepoId() {
|
||||||
|
return domainRepoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key tag.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private int getKeyTag() {
|
||||||
|
return keyTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the algorithm.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private int getAlgorithm() {
|
||||||
|
return algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the digest type.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private int getDigestType() {
|
||||||
|
return digestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the digest.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private byte[] getDigest() {
|
||||||
|
return digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the domain repository ID.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setDomainRepoId(String domainRepoId) {
|
||||||
|
this.domainRepoId = domainRepoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key tag.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setKeyTag(int keyTag) {
|
||||||
|
this.keyTag = keyTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DelegationSignerDataId create(String domainRepoId, int keyTag) {
|
/**
|
||||||
return new DelegationSignerDataId(checkArgumentNotNull(domainRepoId), keyTag);
|
* Sets the algorithm.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setAlgorithm(int algorithm) {
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the digest type.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setDigestType(int digestType) {
|
||||||
|
this.digestType = digestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the digest.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setDigest(byte[] digest) {
|
||||||
|
this.digest = digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DomainDsDataId create(
|
||||||
|
String domainRepoId, int keyTag, int algorithm, int digestType, byte[] digest) {
|
||||||
|
return new DomainDsDataId(
|
||||||
|
domainRepoId, keyTag, algorithm, digestType, checkArgumentNotNull(digest));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
// 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.domain.secdns;
|
||||||
|
|
||||||
|
import com.googlecode.objectify.annotation.Embed;
|
||||||
|
import com.googlecode.objectify.annotation.Ignore;
|
||||||
|
import google.registry.model.ImmutableObject;
|
||||||
|
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||||
|
import javax.persistence.Access;
|
||||||
|
import javax.persistence.AccessType;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import javax.persistence.Transient;
|
||||||
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlTransient;
|
||||||
|
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
|
||||||
|
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||||
|
|
||||||
|
/** Base class for {@link DelegationSignerData} and {@link DomainDsDataHistory}. */
|
||||||
|
@Embed
|
||||||
|
@MappedSuperclass
|
||||||
|
@Access(AccessType.FIELD)
|
||||||
|
public abstract class DomainDsDataBase extends ImmutableObject implements DatastoreAndSqlEntity {
|
||||||
|
|
||||||
|
@Ignore @XmlTransient @Transient String domainRepoId;
|
||||||
|
|
||||||
|
/** The identifier for this particular key in the domain. */
|
||||||
|
@Transient int keyTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The algorithm used by this key.
|
||||||
|
*
|
||||||
|
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.1">RFC 4034 Appendix A.1</a>
|
||||||
|
*/
|
||||||
|
@Transient
|
||||||
|
@XmlElement(name = "alg")
|
||||||
|
int algorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The algorithm used to generate the digest.
|
||||||
|
*
|
||||||
|
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.2">RFC 4034 Appendix A.2</a>
|
||||||
|
*/
|
||||||
|
@Transient int digestType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hexBinary digest of the public key.
|
||||||
|
*
|
||||||
|
* @see <a href="http://tools.ietf.org/html/rfc4034#section-5.1.4">RFC 4034 Section 5.1.4</a>
|
||||||
|
*/
|
||||||
|
@Transient
|
||||||
|
@XmlJavaTypeAdapter(HexBinaryAdapter.class)
|
||||||
|
byte[] digest;
|
||||||
|
|
||||||
|
public String getDomainRepoId() {
|
||||||
|
return domainRepoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKeyTag() {
|
||||||
|
return keyTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAlgorithm() {
|
||||||
|
return algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDigestType() {
|
||||||
|
return digestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getDigest() {
|
||||||
|
return digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the domain repository ID.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setDomainRepoId(String domainRepoId) {
|
||||||
|
this.domainRepoId = domainRepoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key tag.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setKeyTag(int keyTag) {
|
||||||
|
this.keyTag = keyTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the algorithm.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setAlgorithm(int algorithm) {
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the digest type.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setDigestType(int digestType) {
|
||||||
|
this.digestType = digestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the digest.
|
||||||
|
*
|
||||||
|
* <p>This method is private because it is only used by Hibernate.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void setDigest(byte[] digest) {
|
||||||
|
this.digest = digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDigestAsString() {
|
||||||
|
return digest == null ? "" : DatatypeConverter.printHexBinary(digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the presentation format of this DS record.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc4034#section-5.3">RFC 4034 Section 5.3</a>
|
||||||
|
*/
|
||||||
|
public String toRrData() {
|
||||||
|
return String.format(
|
||||||
|
"%d %d %d %s",
|
||||||
|
this.keyTag, this.algorithm, this.digestType, DatatypeConverter.printHexBinary(digest));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
// 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.domain.secdns;
|
||||||
|
|
||||||
|
import google.registry.model.domain.DomainHistory;
|
||||||
|
import google.registry.model.ofy.ObjectifyService;
|
||||||
|
import javax.persistence.Access;
|
||||||
|
import javax.persistence.AccessType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
/** Entity class to represent a historic {@link DelegationSignerData}. */
|
||||||
|
@Entity
|
||||||
|
public class DomainDsDataHistory extends DomainDsDataBase {
|
||||||
|
|
||||||
|
@Id Long dsDataHistoryRevisionId;
|
||||||
|
|
||||||
|
/** ID of the {@link DomainHistory} entity that this entity is associated with. */
|
||||||
|
@Column(nullable = false)
|
||||||
|
Long domainHistoryRevisionId;
|
||||||
|
|
||||||
|
private DomainDsDataHistory() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link DomainDsDataHistory} instance from given {@link #domainHistoryRevisionId} and
|
||||||
|
* {@link DelegationSignerData} instance.
|
||||||
|
*/
|
||||||
|
public static DomainDsDataHistory createFrom(
|
||||||
|
long domainHistoryRevisionId, DelegationSignerData dsData) {
|
||||||
|
DomainDsDataHistory instance = new DomainDsDataHistory();
|
||||||
|
instance.domainHistoryRevisionId = domainHistoryRevisionId;
|
||||||
|
instance.domainRepoId = dsData.domainRepoId;
|
||||||
|
instance.keyTag = dsData.getKeyTag();
|
||||||
|
instance.algorithm = dsData.getAlgorithm();
|
||||||
|
instance.digestType = dsData.getDigestType();
|
||||||
|
instance.digest = dsData.getDigest();
|
||||||
|
instance.dsDataHistoryRevisionId = ObjectifyService.allocateId();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
|
public String getDomainRepoId() {
|
||||||
|
return super.getDomainRepoId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
|
public int getKeyTag() {
|
||||||
|
return super.getKeyTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
|
public int getAlgorithm() {
|
||||||
|
return super.getAlgorithm();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
|
public int getDigestType() {
|
||||||
|
return super.getDigestType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
|
@Column(nullable = false)
|
||||||
|
public byte[] getDigest() {
|
||||||
|
return super.getDigest();
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,6 +47,7 @@
|
||||||
<class>google.registry.model.domain.DomainHistory</class>
|
<class>google.registry.model.domain.DomainHistory</class>
|
||||||
<class>google.registry.model.domain.GracePeriod</class>
|
<class>google.registry.model.domain.GracePeriod</class>
|
||||||
<class>google.registry.model.domain.secdns.DelegationSignerData</class>
|
<class>google.registry.model.domain.secdns.DelegationSignerData</class>
|
||||||
|
<class>google.registry.model.domain.secdns.DomainDsDataHistory</class>
|
||||||
<class>google.registry.model.domain.token.AllocationToken</class>
|
<class>google.registry.model.domain.token.AllocationToken</class>
|
||||||
<class>google.registry.model.host.HostHistory</class>
|
<class>google.registry.model.host.HostHistory</class>
|
||||||
<class>google.registry.model.host.HostResource</class>
|
<class>google.registry.model.host.HostResource</class>
|
||||||
|
|
|
@ -34,6 +34,7 @@ import google.registry.model.domain.DomainBase;
|
||||||
import google.registry.model.domain.DomainContent;
|
import google.registry.model.domain.DomainContent;
|
||||||
import google.registry.model.domain.DomainHistory;
|
import google.registry.model.domain.DomainHistory;
|
||||||
import google.registry.model.domain.Period;
|
import google.registry.model.domain.Period;
|
||||||
|
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||||
import google.registry.model.eppcommon.Trid;
|
import google.registry.model.eppcommon.Trid;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.model.reporting.DomainTransactionRecord;
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
|
@ -141,6 +142,7 @@ public class DomainHistoryTest extends EntityTestCase {
|
||||||
newDomainBase("example.tld", "domainRepoId", contact)
|
newDomainBase("example.tld", "domainRepoId", contact)
|
||||||
.asBuilder()
|
.asBuilder()
|
||||||
.setNameservers(host.createVKey())
|
.setNameservers(host.createVKey())
|
||||||
|
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
|
||||||
.build();
|
.build();
|
||||||
jpaTm().transact(() -> jpaTm().insert(domain));
|
jpaTm().transact(() -> jpaTm().insert(domain));
|
||||||
return domain;
|
return domain;
|
||||||
|
|
|
@ -116,7 +116,8 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
|
||||||
// The objects will be mostly the same, but the DomainHistory object has a couple extra fields
|
// The objects will be mostly the same, but the DomainHistory object has a couple extra fields
|
||||||
assertAboutImmutableObjects()
|
assertAboutImmutableObjects()
|
||||||
.that(legacyHistoryEntry)
|
.that(legacyHistoryEntry)
|
||||||
.isEqualExceptFields(fromObjectify, "domainContent", "domainRepoId", "nsHosts");
|
.isEqualExceptFields(
|
||||||
|
fromObjectify, "domainContent", "domainRepoId", "nsHosts", "dsDataHistories");
|
||||||
assertThat(fromObjectify instanceof DomainHistory).isTrue();
|
assertThat(fromObjectify instanceof DomainHistory).isTrue();
|
||||||
DomainHistory legacyDomainHistory = (DomainHistory) fromObjectify;
|
DomainHistory legacyDomainHistory = (DomainHistory) fromObjectify;
|
||||||
|
|
||||||
|
@ -129,7 +130,12 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
|
||||||
.that(legacyDomainHistory)
|
.that(legacyDomainHistory)
|
||||||
.isEqualExceptFields(
|
.isEqualExceptFields(
|
||||||
// NB: period, transaction records, and other client ID are added in #794
|
// NB: period, transaction records, and other client ID are added in #794
|
||||||
legacyHistoryFromSql, "period", "domainTransactionRecords", "otherClientId", "nsHosts");
|
legacyHistoryFromSql,
|
||||||
|
"period",
|
||||||
|
"domainTransactionRecords",
|
||||||
|
"otherClientId",
|
||||||
|
"nsHosts",
|
||||||
|
"dsDataHistories");
|
||||||
assertThat(nullToEmpty(legacyDomainHistory.getNsHosts()))
|
assertThat(nullToEmpty(legacyDomainHistory.getNsHosts()))
|
||||||
.isEqualTo(nullToEmpty(legacyHistoryFromSql.getNsHosts()));
|
.isEqualTo(nullToEmpty(legacyHistoryFromSql.getNsHosts()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,6 +273,7 @@ class google.registry.model.domain.DomainHistory {
|
||||||
java.lang.String clientId;
|
java.lang.String clientId;
|
||||||
java.lang.String otherClientId;
|
java.lang.String otherClientId;
|
||||||
java.lang.String reason;
|
java.lang.String reason;
|
||||||
|
java.util.Set<google.registry.model.domain.secdns.DomainDsDataHistory> dsDataHistories;
|
||||||
java.util.Set<google.registry.model.reporting.DomainTransactionRecord> domainTransactionRecords;
|
java.util.Set<google.registry.model.reporting.DomainTransactionRecord> domainTransactionRecords;
|
||||||
org.joda.time.DateTime modificationTime;
|
org.joda.time.DateTime modificationTime;
|
||||||
}
|
}
|
||||||
|
@ -315,6 +316,14 @@ class google.registry.model.domain.secdns.DelegationSignerData {
|
||||||
int digestType;
|
int digestType;
|
||||||
int keyTag;
|
int keyTag;
|
||||||
}
|
}
|
||||||
|
class google.registry.model.domain.secdns.DomainDsDataHistory {
|
||||||
|
byte[] digest;
|
||||||
|
int algorithm;
|
||||||
|
int digestType;
|
||||||
|
int keyTag;
|
||||||
|
java.lang.Long domainHistoryRevisionId;
|
||||||
|
java.lang.Long dsDataHistoryRevisionId;
|
||||||
|
}
|
||||||
class google.registry.model.domain.token.AllocationToken {
|
class google.registry.model.domain.token.AllocationToken {
|
||||||
@Id java.lang.String token;
|
@Id java.lang.String token;
|
||||||
boolean discountPremiums;
|
boolean discountPremiums;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -66,3 +66,4 @@ V65__local_date_date_type.sql
|
||||||
V66__create_rde_revision.sql
|
V66__create_rde_revision.sql
|
||||||
V67__grace_period_history_ids.sql
|
V67__grace_period_history_ids.sql
|
||||||
V68__make_reserved_list_nullable_in_registry.sql
|
V68__make_reserved_list_nullable_in_registry.sql
|
||||||
|
V69__change_primary_key_and_add_history_table_for_delegation_signer.sql
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
-- Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||||
|
--
|
||||||
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
-- you may not use this file except in compliance with the License.
|
||||||
|
-- You may obtain a copy of the License at
|
||||||
|
--
|
||||||
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
--
|
||||||
|
-- Unless required by applicable law or agreed to in writing, software
|
||||||
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
-- See the License for the specific language governing permissions and
|
||||||
|
-- limitations under the License.
|
||||||
|
|
||||||
|
alter table "DelegationSignerData" drop constraint "DelegationSignerData_pkey";
|
||||||
|
|
||||||
|
alter table "DelegationSignerData"
|
||||||
|
add constraint "DelegationSignerData_pkey"
|
||||||
|
primary key (domain_repo_id, key_tag, algorithm, digest_type, digest);
|
||||||
|
|
||||||
|
create table "DomainDsDataHistory" (
|
||||||
|
ds_data_history_revision_id int8 not null,
|
||||||
|
algorithm int4 not null,
|
||||||
|
digest bytea not null,
|
||||||
|
digest_type int4 not null,
|
||||||
|
domain_history_revision_id int8 not null,
|
||||||
|
key_tag int4 not null,
|
||||||
|
domain_repo_id text,
|
||||||
|
primary key (ds_data_history_revision_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
alter table if exists "DomainDsDataHistory"
|
||||||
|
add constraint FKo4ilgyyfnvppbpuivus565i0j
|
||||||
|
foreign key (domain_repo_id, domain_history_revision_id)
|
||||||
|
references "DomainHistory";
|
|
@ -227,12 +227,12 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
create table "DelegationSignerData" (
|
create table "DelegationSignerData" (
|
||||||
domain_repo_id text not null,
|
algorithm int4 not null,
|
||||||
key_tag int4 not null,
|
|
||||||
algorithm int4 not null,
|
|
||||||
digest bytea not null,
|
digest bytea not null,
|
||||||
digest_type int4 not null,
|
digest_type int4 not null,
|
||||||
primary key (domain_repo_id, key_tag)
|
domain_repo_id text not null,
|
||||||
|
key_tag int4 not null,
|
||||||
|
primary key (algorithm, digest, digest_type, domain_repo_id, key_tag)
|
||||||
);
|
);
|
||||||
|
|
||||||
create table "Domain" (
|
create table "Domain" (
|
||||||
|
@ -291,6 +291,17 @@
|
||||||
primary key (repo_id)
|
primary key (repo_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create table "DomainDsDataHistory" (
|
||||||
|
ds_data_history_revision_id int8 not null,
|
||||||
|
algorithm int4 not null,
|
||||||
|
digest bytea not null,
|
||||||
|
digest_type int4 not null,
|
||||||
|
domain_history_revision_id int8 not null,
|
||||||
|
domain_repo_id text,
|
||||||
|
key_tag int4 not null,
|
||||||
|
primary key (ds_data_history_revision_id)
|
||||||
|
);
|
||||||
|
|
||||||
create table "DomainHistory" (
|
create table "DomainHistory" (
|
||||||
domain_repo_id text not null,
|
domain_repo_id text not null,
|
||||||
history_revision_id int8 not null,
|
history_revision_id int8 not null,
|
||||||
|
@ -729,6 +740,11 @@ create index spec11threatmatch_check_date_idx on "Spec11ThreatMatch" (check_date
|
||||||
foreign key (domain_repo_id)
|
foreign key (domain_repo_id)
|
||||||
references "Domain";
|
references "Domain";
|
||||||
|
|
||||||
|
alter table if exists "DomainDsDataHistory"
|
||||||
|
add constraint FKo4ilgyyfnvppbpuivus565i0j
|
||||||
|
foreign key (domain_repo_id, domain_history_revision_id)
|
||||||
|
references "DomainHistory";
|
||||||
|
|
||||||
alter table if exists "DomainHistoryHost"
|
alter table if exists "DomainHistoryHost"
|
||||||
add constraint FKa9woh3hu8gx5x0vly6bai327n
|
add constraint FKa9woh3hu8gx5x0vly6bai327n
|
||||||
foreign key (domain_history_domain_repo_id, domain_history_history_revision_id)
|
foreign key (domain_history_domain_repo_id, domain_history_history_revision_id)
|
||||||
|
|
|
@ -376,6 +376,21 @@ CREATE TABLE public."Domain" (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: DomainDsDataHistory; Type: TABLE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public."DomainDsDataHistory" (
|
||||||
|
ds_data_history_revision_id bigint NOT NULL,
|
||||||
|
algorithm integer NOT NULL,
|
||||||
|
digest bytea NOT NULL,
|
||||||
|
digest_type integer NOT NULL,
|
||||||
|
domain_history_revision_id bigint NOT NULL,
|
||||||
|
key_tag integer NOT NULL,
|
||||||
|
domain_repo_id text
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: DomainHistory; Type: TABLE; Schema: public; Owner: -
|
-- Name: DomainHistory; Type: TABLE; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -1072,7 +1087,15 @@ ALTER TABLE ONLY public."Cursor"
|
||||||
--
|
--
|
||||||
|
|
||||||
ALTER TABLE ONLY public."DelegationSignerData"
|
ALTER TABLE ONLY public."DelegationSignerData"
|
||||||
ADD CONSTRAINT "DelegationSignerData_pkey" PRIMARY KEY (domain_repo_id, key_tag);
|
ADD CONSTRAINT "DelegationSignerData_pkey" PRIMARY KEY (domain_repo_id, key_tag, algorithm, digest_type, digest);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: DomainDsDataHistory DomainDsDataHistory_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."DomainDsDataHistory"
|
||||||
|
ADD CONSTRAINT "DomainDsDataHistory_pkey" PRIMARY KEY (ds_data_history_revision_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
|
@ -2016,6 +2039,14 @@ ALTER TABLE ONLY public."PremiumEntry"
|
||||||
ADD CONSTRAINT fko0gw90lpo1tuee56l0nb6y6g5 FOREIGN KEY (revision_id) REFERENCES public."PremiumList"(revision_id);
|
ADD CONSTRAINT fko0gw90lpo1tuee56l0nb6y6g5 FOREIGN KEY (revision_id) REFERENCES public."PremiumList"(revision_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: DomainDsDataHistory fko4ilgyyfnvppbpuivus565i0j; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."DomainDsDataHistory"
|
||||||
|
ADD CONSTRAINT fko4ilgyyfnvppbpuivus565i0j FOREIGN KEY (domain_repo_id, domain_history_revision_id) REFERENCES public."DomainHistory"(domain_repo_id, history_revision_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: DelegationSignerData fktr24j9v14ph2mfuw2gsmt12kq; Type: FK CONSTRAINT; Schema: public; Owner: -
|
-- Name: DelegationSignerData fktr24j9v14ph2mfuw2gsmt12kq; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue