1
0
mirror of https://github.com/google/nomulus synced 2026-06-09 16:33:02 +00:00

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 955c3d9aeb
commit daaf231d39
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}