1
0
mirror of https://github.com/google/nomulus synced 2025-12-23 06:15:42 +00:00

Refactor console domain actions to exist in separate files (#2638)

This means that we're not storing everything in one file, otherwise it
quickly becomes unwieldy
This commit is contained in:
gbrodman
2025-01-23 11:46:53 -05:00
committed by GitHub
parent 229fcf3946
commit 5e97a8b412
11 changed files with 337 additions and 244 deletions

View File

@@ -109,7 +109,6 @@ import google.registry.tools.server.RefreshDnsForAllDomainsAction;
import google.registry.tools.server.ToolsServerModule;
import google.registry.tools.server.UpdateUserGroupAction;
import google.registry.tools.server.VerifyOteAction;
import google.registry.ui.server.console.ConsoleBulkDomainAction;
import google.registry.ui.server.console.ConsoleDomainGetAction;
import google.registry.ui.server.console.ConsoleDomainListAction;
import google.registry.ui.server.console.ConsoleDumDownloadAction;
@@ -122,6 +121,7 @@ import google.registry.ui.server.console.ConsoleUpdateRegistrarAction;
import google.registry.ui.server.console.ConsoleUserDataAction;
import google.registry.ui.server.console.ConsoleUsersAction;
import google.registry.ui.server.console.RegistrarsAction;
import google.registry.ui.server.console.domains.ConsoleBulkDomainAction;
import google.registry.ui.server.console.settings.ContactAction;
import google.registry.ui.server.console.settings.SecurityAction;
import google.registry.ui.server.console.settings.WhoisRegistrarFieldsAction;

View File

@@ -25,7 +25,6 @@ import google.registry.monitoring.whitebox.WhiteboxModule;
import google.registry.request.RequestComponentBuilder;
import google.registry.request.RequestModule;
import google.registry.request.RequestScope;
import google.registry.ui.server.console.ConsoleBulkDomainAction;
import google.registry.ui.server.console.ConsoleDomainGetAction;
import google.registry.ui.server.console.ConsoleDomainListAction;
import google.registry.ui.server.console.ConsoleDumDownloadAction;
@@ -38,6 +37,7 @@ import google.registry.ui.server.console.ConsoleUpdateRegistrarAction;
import google.registry.ui.server.console.ConsoleUserDataAction;
import google.registry.ui.server.console.ConsoleUsersAction;
import google.registry.ui.server.console.RegistrarsAction;
import google.registry.ui.server.console.domains.ConsoleBulkDomainAction;
import google.registry.ui.server.console.settings.ContactAction;
import google.registry.ui.server.console.settings.SecurityAction;
import google.registry.ui.server.console.settings.WhoisRegistrarFieldsAction;

View File

@@ -136,7 +136,7 @@ abstract class EppToolCommand extends ConfirmingCommand implements CommandWithCo
params.put("dryRun", dryRun);
params.put("clientId", command.clientId);
params.put("superuser", superuser);
params.put("xml", URLEncoder.encode(command.xml, UTF_8.toString()));
params.put("xml", URLEncoder.encode(command.xml, UTF_8));
String requestBody =
Joiner.on('&').withKeyValueSeparator("=").join(filterValues(params, Objects::nonNull));
responses.add(

View File

@@ -1,235 +0,0 @@
// Copyright 2024 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.console;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableMap;
import com.google.common.escape.Escaper;
import com.google.common.xml.XmlEscapers;
import com.google.gson.JsonElement;
import com.google.gson.annotations.Expose;
import google.registry.flows.EppController;
import google.registry.flows.EppRequestSource;
import google.registry.flows.PasswordOnlyTransportCredentials;
import google.registry.flows.StatelessRequestSessionMetadata;
import google.registry.model.console.ConsolePermission;
import google.registry.model.console.User;
import google.registry.model.eppcommon.ProtocolDefinition;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.eppoutput.Result;
import google.registry.request.Action;
import google.registry.request.OptionalJsonPayload;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
/**
* Console endpoint to perform the same action to a list of domains.
*
* <p>All requests must include the {@link BulkAction} to perform as well as a {@link
* BulkDomainList} of domains on which to apply the action. The remaining contents of the request
* body depend on the type of action -- some requests may require more data than others.
*/
@Action(
service = Action.GaeService.DEFAULT,
gkeService = Action.GkeService.CONSOLE,
path = ConsoleBulkDomainAction.PATH,
method = Action.Method.POST,
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
public class ConsoleBulkDomainAction extends ConsoleApiAction {
public static final String PATH = "/console-api/bulk-domain";
private static Escaper XML_ESCAPER = XmlEscapers.xmlContentEscaper();
public enum BulkAction {
DELETE,
SUSPEND
}
/** All requests must include at least a list of domain names on which to perform the action. */
public record BulkDomainList(@Expose List<String> domainList) {}
public record BulkDomainDeleteRequest(@Expose String reason) {}
public record BulkDomainSuspendRequest(@Expose String reason) {}
private static final String DOMAIN_DELETE_XML =
"""
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<delete>
<domain:delete
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>%DOMAIN_NAME%</domain:name>
</domain:delete>
</delete>
<extension>
<metadata:metadata xmlns:metadata="urn:google:params:xml:ns:metadata-1.0">
<metadata:reason>%REASON%</metadata:reason>
<metadata:requestedByRegistrar>true</metadata:requestedByRegistrar>
</metadata:metadata>
</extension>
<clTRID>RegistryConsole</clTRID>
</command>
</epp>""";
private static final String DOMAIN_SUSPEND_XML =
"""
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<epp
xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<domain:update
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>%DOMAIN_NAME%</domain:name>
<domain:add>
<domain:status s="serverDeleteProhibited" lang="en"></domain:status>
<domain:status s="serverHold" lang="en"></domain:status>
<domain:status s="serverRenewProhibited" lang="en"></domain:status>
<domain:status s="serverTransferProhibited" lang="en"></domain:status>
<domain:status s="serverUpdateProhibited" lang="en"></domain:status>
</domain:add>
<domain:rem></domain:rem>
</domain:update>
</update>
<extension>
<metadata:metadata
xmlns:metadata="urn:google:params:xml:ns:metadata-1.0">
<metadata:reason>Console suspension: %REASON%</metadata:reason>
<metadata:requestedByRegistrar>false</metadata:requestedByRegistrar>
</metadata:metadata>
</extension>
<clTRID>RegistryTool</clTRID>
</command>
</epp>""";
private final EppController eppController;
private final String registrarId;
private final String bulkDomainAction;
private final Optional<JsonElement> optionalJsonPayload;
@Inject
public ConsoleBulkDomainAction(
ConsoleApiParams consoleApiParams,
EppController eppController,
@Parameter("registrarId") String registrarId,
@Parameter("bulkDomainAction") String bulkDomainAction,
@OptionalJsonPayload Optional<JsonElement> optionalJsonPayload) {
super(consoleApiParams);
this.eppController = eppController;
this.registrarId = registrarId;
this.bulkDomainAction = bulkDomainAction;
this.optionalJsonPayload = optionalJsonPayload;
}
@Override
protected void postHandler(User user) {
// Temporary flag while testing
if (!user.getUserRoles().isAdmin()) {
consoleApiParams.response().setStatus(SC_FORBIDDEN);
return;
}
BulkAction bulkAction = BulkAction.valueOf(bulkDomainAction);
JsonElement jsonPayload =
optionalJsonPayload.orElseThrow(
() -> new IllegalArgumentException("Bulk action payload must be present"));
BulkDomainList domainList = consoleApiParams.gson().fromJson(jsonPayload, BulkDomainList.class);
checkPermission(user, registrarId, ConsolePermission.EXECUTE_EPP_COMMANDS);
ImmutableMap<String, ConsoleEppOutput> result =
switch (bulkAction) {
case DELETE -> handleBulkDelete(jsonPayload, domainList, user);
case SUSPEND -> handleBulkSuspend(jsonPayload, domainList, user);
};
// Front end should parse situations where only some commands worked
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(result));
consoleApiParams.response().setStatus(SC_OK);
}
private ImmutableMap<String, ConsoleEppOutput> handleBulkDelete(
JsonElement jsonPayload, BulkDomainList domainList, User user) {
String reason =
consoleApiParams.gson().fromJson(jsonPayload, BulkDomainDeleteRequest.class).reason;
return runCommandOverDomains(
domainList,
DOMAIN_DELETE_XML,
new ImmutableMap.Builder<String, String>().put("REASON", reason),
user);
}
private ImmutableMap<String, ConsoleEppOutput> handleBulkSuspend(
JsonElement jsonPayload, BulkDomainList domainList, User user) {
String reason =
consoleApiParams.gson().fromJson(jsonPayload, BulkDomainSuspendRequest.class).reason;
return runCommandOverDomains(
domainList,
DOMAIN_SUSPEND_XML,
new ImmutableMap.Builder<String, String>().put("REASON", reason),
user);
}
/** Runs the provided XML template and substitutions over a provided list of domains. */
private ImmutableMap<String, ConsoleEppOutput> runCommandOverDomains(
BulkDomainList domainList,
String xmlTemplate,
ImmutableMap.Builder<String, String> replacements,
User user) {
return domainList.domainList.stream()
.collect(
toImmutableMap(
d -> d,
d ->
executeEpp(
fillSubstitutions(xmlTemplate, replacements.put("DOMAIN_NAME", d)), user)));
}
private ConsoleEppOutput executeEpp(String xml, User user) {
return ConsoleEppOutput.fromEppOutput(
eppController.handleEppCommand(
new StatelessRequestSessionMetadata(
registrarId, ProtocolDefinition.getVisibleServiceExtensionUris()),
new PasswordOnlyTransportCredentials(),
EppRequestSource.CONSOLE,
false,
user.getUserRoles().isAdmin(),
xml.getBytes(UTF_8)));
}
/** Fills the provided XML template with the replacement values, including escaping the values. */
private String fillSubstitutions(
String xmlTemplate, ImmutableMap.Builder<String, String> replacements) {
String xml = xmlTemplate;
for (Map.Entry<String, String> entry : replacements.buildKeepingLast().entrySet()) {
xml = xml.replaceAll("%" + entry.getKey() + "%", XML_ESCAPER.escape(entry.getValue()));
}
return xml;
}
public record ConsoleEppOutput(@Expose String message, @Expose int responseCode) {
static ConsoleEppOutput fromEppOutput(EppOutput eppOutput) {
Result result = eppOutput.getResponse().getResult();
return new ConsoleEppOutput(result.getMsg(), result.getCode().code);
}
}
}

View File

@@ -0,0 +1,125 @@
// Copyright 2024 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.console.domains;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import com.google.gson.annotations.Expose;
import google.registry.flows.EppController;
import google.registry.flows.EppRequestSource;
import google.registry.flows.PasswordOnlyTransportCredentials;
import google.registry.flows.StatelessRequestSessionMetadata;
import google.registry.model.console.User;
import google.registry.model.eppcommon.ProtocolDefinition;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.eppoutput.Result;
import google.registry.request.Action;
import google.registry.request.OptionalJsonPayload;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.ui.server.console.ConsoleApiAction;
import google.registry.ui.server.console.ConsoleApiParams;
import java.util.List;
import java.util.Optional;
import javax.inject.Inject;
/**
* Console endpoint to perform the same action to a list of domains.
*
* <p>All requests must include the {@link ConsoleDomainActionType.BulkAction} to perform as well as
* a {@link BulkDomainList} of domains on which to apply the action. The remaining contents of the
* request body depend on the type of action -- some requests may require more data than others.
*/
@Action(
service = Action.GaeService.DEFAULT,
gkeService = Action.GkeService.CONSOLE,
path = ConsoleBulkDomainAction.PATH,
method = Action.Method.POST,
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
public class ConsoleBulkDomainAction extends ConsoleApiAction {
public static final String PATH = "/console-api/bulk-domain";
/** All requests must include at least a list of domain names on which to perform the action. */
public record BulkDomainList(@Expose List<String> domainList) {}
private final EppController eppController;
private final String registrarId;
private final String bulkDomainAction;
private final Optional<JsonElement> optionalJsonPayload;
@Inject
public ConsoleBulkDomainAction(
ConsoleApiParams consoleApiParams,
EppController eppController,
@Parameter("registrarId") String registrarId,
@Parameter("bulkDomainAction") String bulkDomainAction,
@OptionalJsonPayload Optional<JsonElement> optionalJsonPayload) {
super(consoleApiParams);
this.eppController = eppController;
this.registrarId = registrarId;
this.bulkDomainAction = bulkDomainAction;
this.optionalJsonPayload = optionalJsonPayload;
}
@Override
protected void postHandler(User user) {
// Temporary flag while testing
if (!user.getUserRoles().isAdmin()) {
consoleApiParams.response().setStatus(SC_FORBIDDEN);
return;
}
JsonElement jsonPayload =
optionalJsonPayload.orElseThrow(
() -> new IllegalArgumentException("Bulk action payload must be present"));
BulkDomainList domainList = consoleApiParams.gson().fromJson(jsonPayload, BulkDomainList.class);
ConsoleDomainActionType actionType =
ConsoleDomainActionType.parseActionType(bulkDomainAction, jsonPayload);
checkPermission(user, registrarId, actionType.getNecessaryPermission());
ImmutableMap<String, ConsoleEppOutput> result =
domainList.domainList.stream()
.collect(
toImmutableMap(d -> d, d -> executeEpp(actionType.getXmlContentsToRun(d), user)));
// Front end should parse situations where only some commands worked
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(result));
consoleApiParams.response().setStatus(SC_OK);
}
private ConsoleEppOutput executeEpp(String xml, User user) {
return ConsoleEppOutput.fromEppOutput(
eppController.handleEppCommand(
new StatelessRequestSessionMetadata(
registrarId, ProtocolDefinition.getVisibleServiceExtensionUris()),
new PasswordOnlyTransportCredentials(),
EppRequestSource.CONSOLE,
false,
user.getUserRoles().isAdmin(),
xml.getBytes(UTF_8)));
}
public record ConsoleEppOutput(@Expose String message, @Expose int responseCode) {
static ConsoleEppOutput fromEppOutput(EppOutput eppOutput) {
Result result = eppOutput.getResponse().getResult();
return new ConsoleEppOutput(result.getMsg(), result.getCode().code);
}
}
}

View File

@@ -0,0 +1,61 @@
// Copyright 2025 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.console.domains;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import google.registry.model.console.ConsolePermission;
/** An action that will run a delete EPP command on the given domain. */
public class ConsoleBulkDomainDeleteActionType implements ConsoleDomainActionType {
private static final String DOMAIN_DELETE_XML =
"""
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<delete>
<domain:delete
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>%DOMAIN_NAME%</domain:name>
</domain:delete>
</delete>
<extension>
<metadata:metadata xmlns:metadata="urn:google:params:xml:ns:metadata-1.0">
<metadata:reason>%REASON%</metadata:reason>
<metadata:requestedByRegistrar>true</metadata:requestedByRegistrar>
</metadata:metadata>
</extension>
<clTRID>RegistryConsole</clTRID>
</command>
</epp>""";
private final String reason;
public ConsoleBulkDomainDeleteActionType(JsonElement jsonElement) {
this.reason = jsonElement.getAsJsonObject().get("reason").getAsString();
}
@Override
public String getXmlContentsToRun(String domainName) {
return ConsoleDomainActionType.fillSubstitutions(
DOMAIN_DELETE_XML, ImmutableMap.of("DOMAIN_NAME", domainName, "REASON", reason));
}
@Override
public ConsolePermission getNecessaryPermission() {
return ConsolePermission.EXECUTE_EPP_COMMANDS;
}
}

View File

@@ -0,0 +1,71 @@
// Copyright 2025 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.console.domains;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import google.registry.model.console.ConsolePermission;
/** An action that will suspend the given domain, assigning all 5 server*Prohibited statuses. */
public class ConsoleBulkDomainSuspendActionType implements ConsoleDomainActionType {
private static final String DOMAIN_SUSPEND_XML =
"""
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<epp
xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<domain:update
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>%DOMAIN_NAME%</domain:name>
<domain:add>
<domain:status s="serverDeleteProhibited" lang="en"></domain:status>
<domain:status s="serverHold" lang="en"></domain:status>
<domain:status s="serverRenewProhibited" lang="en"></domain:status>
<domain:status s="serverTransferProhibited" lang="en"></domain:status>
<domain:status s="serverUpdateProhibited" lang="en"></domain:status>
</domain:add>
<domain:rem></domain:rem>
</domain:update>
</update>
<extension>
<metadata:metadata
xmlns:metadata="urn:google:params:xml:ns:metadata-1.0">
<metadata:reason>Console suspension: %REASON%</metadata:reason>
<metadata:requestedByRegistrar>false</metadata:requestedByRegistrar>
</metadata:metadata>
</extension>
<clTRID>RegistryConsole</clTRID>
</command>
</epp>""";
private final String reason;
public ConsoleBulkDomainSuspendActionType(JsonElement jsonElement) {
this.reason = jsonElement.getAsJsonObject().get("reason").getAsString();
}
@Override
public String getXmlContentsToRun(String domainName) {
return ConsoleDomainActionType.fillSubstitutions(
DOMAIN_SUSPEND_XML, ImmutableMap.of("DOMAIN_NAME", domainName, "REASON", reason));
}
@Override
public ConsolePermission getNecessaryPermission() {
return ConsolePermission.SUSPEND_DOMAIN;
}
}

View File

@@ -0,0 +1,69 @@
// Copyright 2025 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.console.domains;
import com.google.common.collect.ImmutableMap;
import com.google.common.escape.Escaper;
import com.google.common.xml.XmlEscapers;
import com.google.gson.JsonElement;
import google.registry.model.console.ConsolePermission;
import java.util.Map;
/**
* A type of EPP action to perform on domain(s), run by the {@link ConsoleBulkDomainAction}.
*
* <p>Each {@link BulkAction} defines the class that implements that action, including the EPP XML
* that will be run and the permission required.
*/
public interface ConsoleDomainActionType {
enum BulkAction {
DELETE(ConsoleBulkDomainDeleteActionType.class),
SUSPEND(ConsoleBulkDomainSuspendActionType.class);
private final Class<? extends ConsoleDomainActionType> actionClass;
BulkAction(Class<? extends ConsoleDomainActionType> actionClass) {
this.actionClass = actionClass;
}
public Class<? extends ConsoleDomainActionType> getActionClass() {
return actionClass;
}
}
Escaper XML_ESCAPER = XmlEscapers.xmlContentEscaper();
static String fillSubstitutions(String xmlTemplate, ImmutableMap<String, String> replacements) {
String xml = xmlTemplate;
for (Map.Entry<String, String> entry : replacements.entrySet()) {
xml = xml.replaceAll("%" + entry.getKey() + "%", XML_ESCAPER.escape(entry.getValue()));
}
return xml;
}
String getXmlContentsToRun(String domainName);
ConsolePermission getNecessaryPermission();
static ConsoleDomainActionType parseActionType(String bulkDomainAction, JsonElement jsonElement) {
BulkAction bulkAction = BulkAction.valueOf(bulkDomainAction);
try {
return bulkAction.getActionClass().getConstructor(JsonElement.class).newInstance(jsonElement);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e); // shouldn't happen
}
}
}

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.ui.server.console;
package google.registry.ui.server.console.domains;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_OPTIONAL;
@@ -49,6 +49,7 @@ import google.registry.testing.ConsoleApiParamsUtils;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import google.registry.tools.GsonUtils;
import google.registry.ui.server.console.ConsoleApiParams;
import java.util.Optional;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
@@ -166,13 +167,13 @@ public class ConsoleBulkDomainActionTest {
@Test
void testFailure_badActionString() {
ConsoleBulkDomainAction action = createAction("bad", null);
ConsoleBulkDomainAction action = createAction("bad", GSON.toJsonTree(ImmutableMap.of()));
action.run();
assertThat(fakeResponse.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(fakeResponse.getPayload())
.isEqualTo(
"No enum constant"
+ " google.registry.ui.server.console.ConsoleBulkDomainAction.BulkAction.bad");
+ " google.registry.ui.server.console.domains.ConsoleDomainActionType.BulkAction.bad");
}
@Test
@@ -186,7 +187,8 @@ public class ConsoleBulkDomainActionTest {
@Test
void testFailure_noPermission() {
JsonElement payload =
GSON.toJsonTree(ImmutableMap.of("domainList", ImmutableList.of("domain.tld")));
GSON.toJsonTree(
ImmutableMap.of("domainList", ImmutableList.of("domain.tld"), "reason", "reason"));
ConsoleBulkDomainAction action =
createAction(
"DELETE",

View File

@@ -14,4 +14,4 @@ CONSOLE /console-api/settings/contacts ContactAction GET,
CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC
CONSOLE /console-api/settings/whois-fields WhoisRegistrarFieldsAction POST n USER PUBLIC
CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC

View File

@@ -80,4 +80,4 @@ CONSOLE /console-api/settings/contacts ContactAction
CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC
CONSOLE /console-api/settings/whois-fields WhoisRegistrarFieldsAction POST n USER PUBLIC
CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC
CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC