Add RegistryLockVerifyAction (#461)

* Add RegistryLockVerifyAction

The action takes two parameters
- isLock is a boolean, determining whether we're trying to lock or
unlock a domain
- lockVerificationCode is the UUID by which we'll look up the lock
object in question.

The lock in question must not be expired and must be in a valid lockable
/ unlockable state

* Some responses to CR

* Add slash and move test method

* Add more data and tests

* Fix screenshot
This commit is contained in:
gbrodman 2020-01-29 16:36:39 -05:00 committed by GitHub
parent 7f86cab87a
commit af8ef38b0a
13 changed files with 578 additions and 4 deletions

View file

@ -61,6 +61,11 @@
<url-pattern>/registry-lock-get</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registry-lock-verify</url-pattern>
</servlet-mapping>
<!-- Security config -->
<security-constraint>
<web-resource-collection>

View file

@ -31,6 +31,7 @@ import google.registry.ui.server.registrar.OteStatusAction;
import google.registry.ui.server.registrar.RegistrarConsoleModule;
import google.registry.ui.server.registrar.RegistrarSettingsAction;
import google.registry.ui.server.registrar.RegistryLockGetAction;
import google.registry.ui.server.registrar.RegistryLockVerifyAction;
/** Dagger component with per-request lifetime for "default" App Engine module. */
@RequestScope
@ -53,6 +54,8 @@ interface FrontendRequestComponent {
RegistryLockGetAction registryLockGetAction();
RegistryLockVerifyAction registryLockVerifyAction();
@Subcomponent.Builder
abstract class Builder implements RequestComponentBuilder<FrontendRequestComponent> {
@Override public abstract Builder requestModule(RequestModule requestModule);

View file

@ -38,7 +38,7 @@ public abstract class LockOrUnlockDomainCommand extends ConfirmingCommand
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
static final ImmutableSet<StatusValue> REGISTRY_LOCK_STATUSES =
public static final ImmutableSet<StatusValue> REGISTRY_LOCK_STATUSES =
ImmutableSet.of(
SERVER_DELETE_PROHIBITED, SERVER_TRANSFER_PROHIBITED, SERVER_UPDATE_PROHIBITED);

View file

@ -14,7 +14,7 @@
package google.registry.ui.server.registrar;
import static google.registry.request.RequestParameters.extractBooleanParameter;
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
import static google.registry.request.RequestParameters.extractOptionalParameter;
import static google.registry.request.RequestParameters.extractRequiredParameter;
@ -144,4 +144,16 @@ public final class RegistrarConsoleModule {
static Optional<String> provideOptionalPasscode(HttpServletRequest req) {
return extractOptionalParameter(req, "passcode");
}
@Provides
@Parameter("lockVerificationCode")
static String provideLockVerificationCode(HttpServletRequest req) {
return extractRequiredParameter(req, "lockVerificationCode");
}
@Provides
@Parameter("isLock")
static Boolean provideIsLock(HttpServletRequest req) {
return extractBooleanParameter(req, "isLock");
}
}

View file

@ -0,0 +1,97 @@
// 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.ui.server.registrar;
import static google.registry.ui.server.SoyTemplateUtils.CSS_RENAMING_MAP_SUPPLIER;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.flogger.FluentLogger;
import com.google.template.soy.tofu.SoyTofu;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.schema.domain.RegistryLock;
import google.registry.tools.DomainLockUtils;
import google.registry.ui.server.SoyTemplateUtils;
import google.registry.ui.soy.registrar.RegistryLockVerificationSoyInfo;
import google.registry.util.Clock;
import java.util.HashMap;
import javax.inject.Inject;
/** Action that allows for verification of registry lock / unlock requests */
@Action(
service = Action.Service.DEFAULT,
path = RegistryLockVerifyAction.PATH,
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
public final class RegistryLockVerifyAction extends HtmlAction {
public static final String PATH = "/registry-lock-verify";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final Supplier<SoyTofu> TOFU_SUPPLIER =
SoyTemplateUtils.createTofuSupplier(
google.registry.ui.soy.ConsoleSoyInfo.getInstance(),
google.registry.ui.soy.AnalyticsSoyInfo.getInstance(),
google.registry.ui.soy.registrar.RegistryLockVerificationSoyInfo.getInstance());
private final Clock clock;
private final String lockVerificationCode;
private final Boolean isLock;
@Inject
public RegistryLockVerifyAction(
Clock clock,
@Parameter("lockVerificationCode") String lockVerificationCode,
@Parameter("isLock") Boolean isLock) {
this.clock = clock;
this.lockVerificationCode = lockVerificationCode;
this.isLock = isLock;
}
@Override
public void runAfterLogin(HashMap<String, Object> data) {
try {
boolean isAdmin = authResult.userAuthInfo().get().isUserAdmin();
final RegistryLock resultLock;
if (isLock) {
resultLock = DomainLockUtils.verifyAndApplyLock(lockVerificationCode, isAdmin, clock);
} else {
resultLock = DomainLockUtils.verifyAndApplyUnlock(lockVerificationCode, isAdmin, clock);
}
data.put("isLock", isLock);
data.put("success", true);
data.put("fullyQualifiedDomainName", resultLock.getDomainName());
} catch (Throwable t) {
logger.atWarning().withCause(t).log(
"Error when verifying verification code %s", lockVerificationCode);
data.put("success", false);
data.put("errorMessage", Throwables.getRootCause(t).getMessage());
}
response.setPayload(
TOFU_SUPPLIER
.get()
.newRenderer(RegistryLockVerificationSoyInfo.VERIFICATION_PAGE)
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
.setData(data)
.render());
}
@Override
public String getPath() {
return PATH;
}
}

View file

@ -0,0 +1,71 @@
// 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.
{namespace registry.soy.registrar.registrylock.verification}
/**
* Results page for a registry lock/unlock verification.
*/
{template .verificationPage}
{@param username: string} /** Arbitrary username to display. */
{@param analyticsConfig: [googleAnalyticsId: string|null]}
{@param success: bool}
{@param? errorMessage: string}
{@param? isLock: bool}
{@param? fullyQualifiedDomainName: string}
{call registry.soy.console.header}
{param app: 'registrar' /}
{param subtitle: 'Verify Registry Lock' /}
{param analyticsConfig: $analyticsConfig /}
{/call}
{call registry.soy.console.googlebar data="all" /}
<div id="reg-content-and-footer">
<div id="reg-content">
<h1>Registry Lock Verification</h1>
{if $success}
{call .success data="all" /}
{else}
{call .failure data="all" /}
{/if}
<h3><a href="/registrar">Return to Registrar Console</a></h3>
</div>
{call registry.soy.console.footer /}
</div>
{/template}
/**
* Result page for failure, e.g. the UUID was invalid
*/
{template .failure}
{@param? errorMessage: string}
<h2 class="{css('kd-errormessage')}">Failed: {if isNonnull($errorMessage)}
{$errorMessage}
{else}
Undefined error message
{/if}
</h2>
{/template}
/**
* Result page for a successful lock / unlock.
*/
{template .success}
{@param? isLock: bool}
{@param? fullyQualifiedDomainName: string}
<h3>
Success: {if $isLock}lock{else}unlock{/if} has been applied to {$fullyQualifiedDomainName}
</h3>
{/template}

View file

@ -30,6 +30,7 @@ import google.registry.tools.UpdateReservedListCommandTest;
import google.registry.tools.server.CreatePremiumListActionTest;
import google.registry.tools.server.UpdatePremiumListActionTest;
import google.registry.ui.server.registrar.RegistryLockGetActionTest;
import google.registry.ui.server.registrar.RegistryLockVerifyActionTest;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
@ -60,6 +61,7 @@ import org.junit.runners.Suite.SuiteClasses;
PremiumListDaoTest.class,
RegistryLockDaoTest.class,
RegistryLockGetActionTest.class,
RegistryLockVerifyActionTest.class,
ReservedListDaoTest.class,
UnlockDomainCommandTest.class,
UpdatePremiumListActionTest.class,

View file

@ -83,7 +83,8 @@ public final class RegistryTestServer {
route("/registrar-ote-setup", FrontendServlet.class),
route("/registrar-ote-status", FrontendServlet.class),
route("/registrar-settings", FrontendServlet.class),
route("/registry-lock-get", FrontendServlet.class));
route("/registry-lock-get", FrontendServlet.class),
route("/registry-lock-verify", FrontendServlet.class));
private static final ImmutableList<Class<? extends Filter>> FILTERS = ImmutableList.of(
ObjectifyFilter.class,

View file

@ -0,0 +1,345 @@
// 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.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.createTlds;
import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.persistActiveHost;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.common.collect.ImmutableMap;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase;
import google.registry.model.host.HostResource;
import google.registry.model.registry.Registry;
import google.registry.model.registry.RegistryLockDao;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
import google.registry.request.auth.AuthLevel;
import google.registry.request.auth.AuthResult;
import google.registry.request.auth.UserAuthInfo;
import google.registry.schema.domain.RegistryLock;
import google.registry.security.XsrfTokenManager;
import google.registry.testing.AppEngineRule;
import google.registry.testing.DatastoreHelper;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import google.registry.testing.InjectRule;
import google.registry.testing.UserInfo;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.joda.time.Duration;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class RegistryLockVerifyActionTest {
private final FakeClock fakeClock = new FakeClock();
@Rule
public final AppEngineRule appEngineRule =
AppEngineRule.builder()
.withDatastore()
.withUserService(UserInfo.create("marla.singer@example.com", "12345"))
.build();
@Rule
public final JpaIntegrationWithCoverageRule jpaRule =
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule();
@Rule public final InjectRule inject = new InjectRule();
private final HttpServletRequest request = mock(HttpServletRequest.class);
private final UserService userService = UserServiceFactory.getUserService();
private final User user = new User("marla.singer@example.com", "gmail.com", "12345");
private final String lockId = "f1be78a2-2d61-458c-80f0-9dd8f2f8625f";
private FakeResponse response;
private DomainBase domain;
private AuthResult authResult;
private RegistryLockVerifyAction action;
@Before
public void setup() {
createTlds("tld", "net");
HostResource host = persistActiveHost("ns1.example.net");
domain = persistResource(newDomainBase("example.tld", host));
when(request.getRequestURI()).thenReturn("https://registry.example/registry-lock-verification");
action = createAction(lockId, true);
}
@Test
public void testSuccess_lockDomain() {
RegistryLockDao.save(createLock());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(reloadDomain().getStatusValues()).containsExactlyElementsIn(REGISTRY_LOCK_STATUSES);
assertThat(response.getPayload()).contains("Success: lock has been applied to example.tld");
HistoryEntry historyEntry = getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_UPDATE);
assertThat(historyEntry.getRequestedByRegistrar()).isTrue();
assertThat(historyEntry.getBySuperuser()).isFalse();
assertThat(historyEntry.getReason())
.isEqualTo("Lock or unlock of a domain through a RegistryLock operation");
assertBillingEvent(historyEntry);
}
@Test
public void testSuccess_unlockDomain() {
action = createAction(lockId, false);
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
RegistryLockDao.save(
createLock().asBuilder().setUnlockRequestTimestamp(fakeClock.nowUtc()).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(response.getPayload()).contains("Success: unlock has been applied to example.tld");
assertThat(reloadDomain().getStatusValues()).containsNoneIn(REGISTRY_LOCK_STATUSES);
HistoryEntry historyEntry = getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_UPDATE);
assertThat(historyEntry.getRequestedByRegistrar()).isTrue();
assertThat(historyEntry.getBySuperuser()).isFalse();
assertThat(historyEntry.getReason())
.isEqualTo("Lock or unlock of a domain through a RegistryLock operation");
assertBillingEvent(historyEntry);
}
@Test
public void testSuccess_adminLock_createsOnlyHistoryEntry() {
action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, true));
RegistryLockDao.save(createLock().asBuilder().isSuperuser(true).build());
action.run();
HistoryEntry historyEntry = getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_UPDATE);
assertThat(historyEntry.getRequestedByRegistrar()).isFalse();
assertThat(historyEntry.getBySuperuser()).isTrue();
DatastoreHelper.assertNoBillingEvents();
}
@Test
public void testFailure_badVerificationCode() {
RegistryLockDao.save(
createLock().asBuilder().setVerificationCode(UUID.randomUUID().toString()).build());
action.run();
assertThat(response.getPayload()).contains("Failed: Invalid verification code");
assertNoDomainChanges();
}
@Test
public void testFailure_alreadyVerified() {
RegistryLockDao.save(
createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
assertNoDomainChanges();
}
@Test
public void testFailure_expired() {
RegistryLockDao.save(createLock());
fakeClock.advanceBy(Duration.standardHours(2));
action.run();
assertThat(response.getPayload())
.contains("Failed: The pending lock has expired; please try again");
assertNoDomainChanges();
}
@Test
public void testFailure_nonAdmin_verifyingAdminLock() {
RegistryLockDao.save(createLock().asBuilder().isSuperuser(true).build());
action.run();
assertThat(response.getPayload()).contains("Failed: Non-admin user cannot complete admin lock");
assertNoDomainChanges();
}
@Test
public void testFailure_alreadyUnlocked() {
action = createAction(lockId, false);
RegistryLockDao.save(
createLock()
.asBuilder()
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
.build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already unlocked");
assertNoDomainChanges();
}
@Test
public void testFailure_alreadyLocked() {
RegistryLockDao.save(createLock());
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
assertNoDomainChanges();
}
@Test
public void testFailure_notLoggedIn() {
action.authResult = AuthResult.NOT_AUTHENTICATED;
action.run();
assertThat(response.getStatus()).isEqualTo(SC_MOVED_TEMPORARILY);
assertThat(response.getHeaders()).containsKey("Location");
assertNoDomainChanges();
}
@Test
public void testFailure_doesNotChangeLockObject() {
// A failure when performing Datastore actions means that no actions should be taken in the
// Cloud SQL RegistryLock object
RegistryLock lock = createLock();
RegistryLockDao.save(lock);
// reload the lock to pick up creation time
lock = RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get();
fakeClock.advanceOneMilli();
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
action.run();
// we would have failed during the Datastore segment of the action
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
// verify that the changes to the SQL object were rolled back
RegistryLock afterAction =
RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get();
assertThat(afterAction).isEqualTo(lock);
}
@Test
public void testFailure_isLockTrue_shouldBeFalse() {
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
RegistryLockDao.save(
createLock()
.asBuilder()
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
}
@Test
public void testFailure_isLockFalse_shouldBeTrue() {
action = createAction(lockId, false);
RegistryLockDao.save(createLock());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already unlocked");
}
@Test
public void testFailure_lock_unlock_lockAgain() {
RegistryLock lock = RegistryLockDao.save(createLock());
action.run();
assertThat(response.getPayload()).contains("Success: lock has been applied to example.tld");
String unlockVerificationCode = "some-unlock-code";
RegistryLockDao.save(
lock.asBuilder()
.setVerificationCode(unlockVerificationCode)
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.build());
action = createAction(unlockVerificationCode, false);
action.run();
assertThat(response.getPayload()).contains("Success: unlock has been applied to example.tld");
action = createAction(lockId, true);
action.run();
assertThat(response.getPayload()).contains("Failed: Invalid verification code");
}
@Test
public void testFailure_lock_lockAgain() {
RegistryLockDao.save(createLock());
action.run();
assertThat(response.getPayload()).contains("Success: lock has been applied to example.tld");
action = createAction(lockId, true);
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
}
@Test
public void testFailure_unlock_unlockAgain() {
action = createAction(lockId, false);
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
RegistryLockDao.save(
createLock().asBuilder().setUnlockRequestTimestamp(fakeClock.nowUtc()).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(response.getPayload()).contains("Success: unlock has been applied to example.tld");
action = createAction(lockId, false);
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already unlocked");
}
private RegistryLock createLock() {
return new RegistryLock.Builder()
.setDomainName("example.tld")
.setRegistrarId("TheRegistrar")
.setRepoId("repoId")
.setRegistrarPocId("marla.singer@example.com")
.isSuperuser(false)
.setVerificationCode(lockId)
.build();
}
private DomainBase reloadDomain() {
return ofy().load().entity(domain).now();
}
private void assertNoDomainChanges() {
assertThat(reloadDomain()).isEqualTo(domain);
}
private void assertBillingEvent(HistoryEntry historyEntry) {
DatastoreHelper.assertBillingEvents(
new BillingEvent.OneTime.Builder()
.setReason(Reason.SERVER_STATUS)
.setTargetId(domain.getForeignKey())
.setClientId(domain.getCurrentSponsorClientId())
.setCost(Registry.get(domain.getTld()).getServerStatusChangeCost())
.setEventTime(fakeClock.nowUtc())
.setBillingTime(fakeClock.nowUtc())
.setParent(historyEntry)
.build());
}
private RegistryLockVerifyAction createAction(String lockVerificationCode, Boolean isLock) {
response = new FakeResponse();
RegistryLockVerifyAction action =
new RegistryLockVerifyAction(fakeClock, lockVerificationCode, isLock);
authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
action.req = request;
action.response = response;
action.authResult = authResult;
action.userService = userService;
action.logoFilename = "logo.png";
action.productName = "Nomulus";
action.analyticsConfig = ImmutableMap.of("googleAnalyticsId", "sampleId");
action.xsrfTokenManager = new XsrfTokenManager(new FakeClock(), action.userService);
return action;
}
}

View file

@ -18,7 +18,9 @@ import static google.registry.server.Fixture.BASIC;
import static google.registry.server.Route.route;
import static google.registry.testing.AppEngineRule.makeRegistrar2;
import static google.registry.testing.AppEngineRule.makeRegistrarContact2;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.loadRegistrar;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
@ -26,7 +28,9 @@ import com.google.common.collect.ImmutableMap;
import com.googlecode.objectify.ObjectifyFilter;
import google.registry.model.ofy.OfyFilter;
import google.registry.model.registrar.Registrar.State;
import google.registry.model.registry.RegistryLockDao;
import google.registry.module.frontend.FrontendServlet;
import google.registry.schema.domain.RegistryLock;
import google.registry.server.RegistryTestServer;
import google.registry.testing.CertificateSamples;
import org.junit.Rule;
@ -46,7 +50,8 @@ public class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
.setRoutes(
route("/registrar", FrontendServlet.class),
route("/registrar-ote-status", FrontendServlet.class),
route("/registrar-settings", FrontendServlet.class))
route("/registrar-settings", FrontendServlet.class),
route("/registry-lock-verify", FrontendServlet.class))
.setFilters(ObjectifyFilter.class, OfyFilter.class)
.setFixtures(BASIC)
.setEmail("Marla.Singer@google.com")
@ -370,4 +375,36 @@ public class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
Thread.sleep(500);
driver.diffPage("page");
}
@Test
public void registryLockVerify_success() throws Throwable {
String lockVerificationCode = "f1be78a2-2d61-458c-80f0-9dd8f2f8625f";
server.runInAppEngineEnvironment(
() -> {
createTld("tld");
persistResource(newDomainBase("example.tld"));
RegistryLockDao.save(
new RegistryLock.Builder()
.setRegistrarPocId("johndoe@theregistrar.com")
.setRepoId("repoId")
.setRegistrarId("TheRegistrar")
.setVerificationCode("f1be78a2-2d61-458c-80f0-9dd8f2f8625f")
.isSuperuser(false)
.setDomainName("example.tld")
.build());
return null;
});
driver.get(
server.getUrl(
"/registry-lock-verify?isLock=true&lockVerificationCode=" + lockVerificationCode));
driver.waitForElement(By.id("reg-content"));
driver.diffPage("page");
}
@Test
public void registryLockVerify_unknownLock() throws Throwable {
driver.get(server.getUrl("/registry-lock-verify?isLock=true&lockVerificationCode=asdfasdf"));
driver.waitForElement(By.id("reg-content"));
driver.diffPage("page");
}
}

View file

@ -6,3 +6,4 @@ PATH CLASS METHODS OK AUTH_METHODS
/registrar-ote-status OteStatusAction POST n API,LEGACY USER PUBLIC
/registrar-settings RegistrarSettingsAction POST n API,LEGACY USER PUBLIC
/registry-lock-get RegistryLockGetAction GET n API,LEGACY USER PUBLIC
/registry-lock-verify RegistryLockVerifyAction GET n API,LEGACY USER PUBLIC