mirror of
https://github.com/google/nomulus.git
synced 2025-05-22 04:09:46 +02:00
Add a relockDuration to the RegistryLock SQL object (#514)
* Add a relockDuration to the RegistryLock SQL object This is the length of time after an unlock that we will re-lock the domain in question. * Sort by domain name for stability Note: this is likely not the best solution for the UI but we can iterate on this. * Add nullable * Add a converter for Duration
This commit is contained in:
parent
4a1242a299
commit
bdaa598ae1
12 changed files with 174 additions and 18 deletions
|
@ -52,8 +52,10 @@ public final class RegistryLockDao {
|
|||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createQuery(
|
||||
"SELECT lock FROM RegistryLock lock WHERE lock.registrarId = :registrarId"
|
||||
+ " AND lock.unlockCompletionTimestamp IS NULL",
|
||||
"SELECT lock FROM RegistryLock lock"
|
||||
+ " WHERE lock.registrarId = :registrarId"
|
||||
+ " AND lock.unlockCompletionTimestamp IS NULL"
|
||||
+ " ORDER BY lock.domainName ASC",
|
||||
RegistryLock.class)
|
||||
.setParameter("registrarId", registrarId)
|
||||
.getResultList());
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// 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.annotation.Nullable;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** JPA converter to for storing/retrieving {@link org.joda.time.DateTime} objects. */
|
||||
@Converter(autoApply = true)
|
||||
public class DurationConverter implements AttributeConverter<Duration, Long> {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Long convertToDatabaseColumn(@Nullable Duration duration) {
|
||||
return duration == null ? null : duration.getMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Duration convertToEntityAttribute(@Nullable Long dbData) {
|
||||
return dbData == null ? null : new Duration(dbData);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import google.registry.model.UpdateAutoTimestamp;
|
|||
import google.registry.util.DateTimeUtils;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
|
@ -37,6 +38,7 @@ import javax.persistence.JoinColumn;
|
|||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Represents a registry lock/unlock object, meaning that the domain is locked on the registry
|
||||
|
@ -131,6 +133,9 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
|
|||
@JoinColumn(name = "relockRevisionId", referencedColumnName = "revisionId")
|
||||
private RegistryLock relock;
|
||||
|
||||
/** The duration after which we will re-lock this domain after it is unlocked. */
|
||||
private Duration relockDuration;
|
||||
|
||||
/** Time that this entity was last updated. */
|
||||
private UpdateAutoTimestamp lastUpdateTimestamp;
|
||||
|
||||
|
@ -197,6 +202,11 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
|
|||
return relock;
|
||||
}
|
||||
|
||||
/** The duration after which we will re-lock this domain after it is unlocked. */
|
||||
public Optional<Duration> getRelockDuration() {
|
||||
return Optional.ofNullable(relockDuration);
|
||||
}
|
||||
|
||||
public boolean isLocked() {
|
||||
return lockCompletionTimestamp != null && unlockCompletionTimestamp == null;
|
||||
}
|
||||
|
@ -289,5 +299,10 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
|
|||
getInstance().relock = relock;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRelockDuration(@Nullable Duration relockDuration) {
|
||||
getInstance().relockDuration = relockDuration;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<class>google.registry.persistence.converter.CreateAutoTimestampConverter</class>
|
||||
<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.RegistrarPocSetConverter</class>
|
||||
<class>google.registry.persistence.converter.StatusValueSetConverter</class>
|
||||
<class>google.registry.persistence.converter.StringListConverter</class>
|
||||
|
|
|
@ -30,6 +30,7 @@ import google.registry.schema.domain.RegistryLock;
|
|||
import google.registry.testing.AppEngineRule;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -88,12 +89,14 @@ public final class RegistryLockDaoTest {
|
|||
.setLockCompletionTimestamp(fakeClock.nowUtc())
|
||||
.setUnlockRequestTimestamp(fakeClock.nowUtc())
|
||||
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
|
||||
.setRelockDuration(Duration.standardHours(6))
|
||||
.build());
|
||||
RegistryLock fromDatabase = getRegistryLockByVerificationCode(lock.getVerificationCode()).get();
|
||||
assertThat(fromDatabase.getUnlockRequestTimestamp()).isEqualTo(Optional.of(fakeClock.nowUtc()));
|
||||
assertThat(fromDatabase.getUnlockCompletionTimestamp())
|
||||
.isEqualTo(Optional.of(fakeClock.nowUtc()));
|
||||
assertThat(fromDatabase.isLocked()).isFalse();
|
||||
assertThat(fromDatabase.getRelockDuration().get()).isEqualTo(Duration.standardHours(6));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
// 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;
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
// 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.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule;
|
||||
import java.math.BigInteger;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/** Unit tests for {@link DurationConverter}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class DurationConverterTest {
|
||||
|
||||
@Rule
|
||||
public final JpaUnitTestRule jpaRule =
|
||||
new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule();
|
||||
|
||||
private final DurationConverter converter = new DurationConverter();
|
||||
|
||||
@Test
|
||||
public void testNulls() {
|
||||
assertThat(converter.convertToDatabaseColumn(null)).isNull();
|
||||
assertThat(converter.convertToEntityAttribute(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundTrip() {
|
||||
TestEntity entity = new TestEntity(Duration.standardDays(6));
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
|
||||
assertThat(
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.createNativeQuery(
|
||||
"SELECT duration FROM \"TestEntity\" WHERE name = 'id'")
|
||||
.getResultList()))
|
||||
.containsExactly(BigInteger.valueOf(Duration.standardDays(6).getMillis()));
|
||||
TestEntity persisted =
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "id"));
|
||||
assertThat(persisted.duration).isEqualTo(Duration.standardDays(6));
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
public static class TestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
Duration duration;
|
||||
|
||||
public TestEntity() {}
|
||||
|
||||
TestEntity(Duration duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -188,10 +188,10 @@ public final class RegistryLockGetActionTest {
|
|||
"locks",
|
||||
ImmutableList.of(
|
||||
new ImmutableMap.Builder<>()
|
||||
.put("fullyQualifiedDomainName", "expiredunlock.test")
|
||||
.put("lockedTime", "2000-06-08T22:00:00.000Z")
|
||||
.put("lockedBy", "johndoe@theregistrar.com")
|
||||
.put("userCanUnlock", true)
|
||||
.put("fullyQualifiedDomainName", "adminexample.test")
|
||||
.put("lockedTime", "2000-06-09T22:00:00.001Z")
|
||||
.put("lockedBy", "admin")
|
||||
.put("userCanUnlock", false)
|
||||
.put("isLockPending", false)
|
||||
.put("isUnlockPending", false)
|
||||
.build(),
|
||||
|
@ -204,19 +204,11 @@ public final class RegistryLockGetActionTest {
|
|||
.put("isUnlockPending", false)
|
||||
.build(),
|
||||
new ImmutableMap.Builder<>()
|
||||
.put("fullyQualifiedDomainName", "adminexample.test")
|
||||
.put("lockedTime", "2000-06-09T22:00:00.001Z")
|
||||
.put("lockedBy", "admin")
|
||||
.put("userCanUnlock", false)
|
||||
.put("isLockPending", false)
|
||||
.put("isUnlockPending", false)
|
||||
.build(),
|
||||
new ImmutableMap.Builder<>()
|
||||
.put("fullyQualifiedDomainName", "pending.test")
|
||||
.put("lockedTime", "")
|
||||
.put("fullyQualifiedDomainName", "expiredunlock.test")
|
||||
.put("lockedTime", "2000-06-08T22:00:00.000Z")
|
||||
.put("lockedBy", "johndoe@theregistrar.com")
|
||||
.put("userCanUnlock", true)
|
||||
.put("isLockPending", true)
|
||||
.put("isLockPending", false)
|
||||
.put("isUnlockPending", false)
|
||||
.build(),
|
||||
new ImmutableMap.Builder<>()
|
||||
|
@ -226,6 +218,14 @@ public final class RegistryLockGetActionTest {
|
|||
.put("userCanUnlock", true)
|
||||
.put("isLockPending", false)
|
||||
.put("isUnlockPending", true)
|
||||
.build(),
|
||||
new ImmutableMap.Builder<>()
|
||||
.put("fullyQualifiedDomainName", "pending.test")
|
||||
.put("lockedTime", "")
|
||||
.put("lockedBy", "johndoe@theregistrar.com")
|
||||
.put("userCanUnlock", true)
|
||||
.put("isLockPending", true)
|
||||
.put("isUnlockPending", false)
|
||||
.build()))));
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
@ -0,0 +1,15 @@
|
|||
-- 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 "RegistryLock" ADD COLUMN relock_duration bigint;
|
|
@ -176,6 +176,7 @@
|
|||
lock_request_timestamp timestamptz not null,
|
||||
registrar_id text not null,
|
||||
registrar_poc_id text,
|
||||
relock_duration int8,
|
||||
repo_id text not null,
|
||||
unlock_completion_timestamp timestamptz,
|
||||
unlock_request_timestamp timestamptz,
|
||||
|
|
|
@ -262,7 +262,8 @@ CREATE TABLE public."RegistryLock" (
|
|||
unlock_request_timestamp timestamp with time zone,
|
||||
unlock_completion_timestamp timestamp with time zone,
|
||||
last_update_timestamp timestamp with time zone,
|
||||
relock_revision_id bigint
|
||||
relock_revision_id bigint,
|
||||
relock_duration bigint
|
||||
);
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue