diff --git a/core/src/main/java/google/registry/module/RequestComponent.java b/core/src/main/java/google/registry/module/RequestComponent.java index 8c819e936..bef4e282c 100644 --- a/core/src/main/java/google/registry/module/RequestComponent.java +++ b/core/src/main/java/google/registry/module/RequestComponent.java @@ -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; diff --git a/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java b/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java index 3960f8f30..0728e4624 100644 --- a/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java +++ b/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java @@ -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; diff --git a/core/src/main/java/google/registry/tools/EppToolCommand.java b/core/src/main/java/google/registry/tools/EppToolCommand.java index c3bdcf69b..fcc22130f 100644 --- a/core/src/main/java/google/registry/tools/EppToolCommand.java +++ b/core/src/main/java/google/registry/tools/EppToolCommand.java @@ -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( diff --git a/core/src/main/java/google/registry/ui/server/console/ConsoleBulkDomainAction.java b/core/src/main/java/google/registry/ui/server/console/ConsoleBulkDomainAction.java deleted file mode 100644 index 375171272..000000000 --- a/core/src/main/java/google/registry/ui/server/console/ConsoleBulkDomainAction.java +++ /dev/null @@ -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. - * - *

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 domainList) {} - - public record BulkDomainDeleteRequest(@Expose String reason) {} - - public record BulkDomainSuspendRequest(@Expose String reason) {} - - private static final String DOMAIN_DELETE_XML = - """ - - - - - - %DOMAIN_NAME% - - - - - %REASON% - true - - - RegistryConsole - -"""; - - private static final String DOMAIN_SUSPEND_XML = - """ - - - - - - %DOMAIN_NAME% - - - - - - - - - - - - - Console suspension: %REASON% - false - - - RegistryTool - -"""; - - private final EppController eppController; - private final String registrarId; - private final String bulkDomainAction; - private final Optional optionalJsonPayload; - - @Inject - public ConsoleBulkDomainAction( - ConsoleApiParams consoleApiParams, - EppController eppController, - @Parameter("registrarId") String registrarId, - @Parameter("bulkDomainAction") String bulkDomainAction, - @OptionalJsonPayload Optional 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 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 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().put("REASON", reason), - user); - } - - private ImmutableMap 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().put("REASON", reason), - user); - } - - /** Runs the provided XML template and substitutions over a provided list of domains. */ - private ImmutableMap runCommandOverDomains( - BulkDomainList domainList, - String xmlTemplate, - ImmutableMap.Builder 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 replacements) { - String xml = xmlTemplate; - for (Map.Entry 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); - } - } -} diff --git a/core/src/main/java/google/registry/ui/server/console/domains/ConsoleBulkDomainAction.java b/core/src/main/java/google/registry/ui/server/console/domains/ConsoleBulkDomainAction.java new file mode 100644 index 000000000..3d9a05ecc --- /dev/null +++ b/core/src/main/java/google/registry/ui/server/console/domains/ConsoleBulkDomainAction.java @@ -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. + * + *

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 domainList) {} + + private final EppController eppController; + private final String registrarId; + private final String bulkDomainAction; + private final Optional optionalJsonPayload; + + @Inject + public ConsoleBulkDomainAction( + ConsoleApiParams consoleApiParams, + EppController eppController, + @Parameter("registrarId") String registrarId, + @Parameter("bulkDomainAction") String bulkDomainAction, + @OptionalJsonPayload Optional 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 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); + } + } +} diff --git a/core/src/main/java/google/registry/ui/server/console/domains/ConsoleBulkDomainDeleteActionType.java b/core/src/main/java/google/registry/ui/server/console/domains/ConsoleBulkDomainDeleteActionType.java new file mode 100644 index 000000000..1e05fa17d --- /dev/null +++ b/core/src/main/java/google/registry/ui/server/console/domains/ConsoleBulkDomainDeleteActionType.java @@ -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 = + """ + + + + + + %DOMAIN_NAME% + + + + + %REASON% + true + + + RegistryConsole + +"""; + + 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; + } +} diff --git a/core/src/main/java/google/registry/ui/server/console/domains/ConsoleBulkDomainSuspendActionType.java b/core/src/main/java/google/registry/ui/server/console/domains/ConsoleBulkDomainSuspendActionType.java new file mode 100644 index 000000000..12c646313 --- /dev/null +++ b/core/src/main/java/google/registry/ui/server/console/domains/ConsoleBulkDomainSuspendActionType.java @@ -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 = + """ + + + + + + %DOMAIN_NAME% + + + + + + + + + + + + + Console suspension: %REASON% + false + + + RegistryConsole + +"""; + + 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; + } +} diff --git a/core/src/main/java/google/registry/ui/server/console/domains/ConsoleDomainActionType.java b/core/src/main/java/google/registry/ui/server/console/domains/ConsoleDomainActionType.java new file mode 100644 index 000000000..0f49c11a7 --- /dev/null +++ b/core/src/main/java/google/registry/ui/server/console/domains/ConsoleDomainActionType.java @@ -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}. + * + *

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 actionClass; + + BulkAction(Class actionClass) { + this.actionClass = actionClass; + } + + public Class getActionClass() { + return actionClass; + } + } + + Escaper XML_ESCAPER = XmlEscapers.xmlContentEscaper(); + + static String fillSubstitutions(String xmlTemplate, ImmutableMap replacements) { + String xml = xmlTemplate; + for (Map.Entry 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 + } + } +} diff --git a/core/src/test/java/google/registry/ui/server/console/ConsoleBulkDomainActionTest.java b/core/src/test/java/google/registry/ui/server/console/domains/ConsoleBulkDomainActionTest.java similarity index 95% rename from core/src/test/java/google/registry/ui/server/console/ConsoleBulkDomainActionTest.java rename to core/src/test/java/google/registry/ui/server/console/domains/ConsoleBulkDomainActionTest.java index d368fcccb..a299c95cc 100644 --- a/core/src/test/java/google/registry/ui/server/console/ConsoleBulkDomainActionTest.java +++ b/core/src/test/java/google/registry/ui/server/console/domains/ConsoleBulkDomainActionTest.java @@ -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", diff --git a/core/src/test/resources/google/registry/module/frontend/frontend_routing.txt b/core/src/test/resources/google/registry/module/frontend/frontend_routing.txt index 4bd9f2ff5..4470947da 100644 --- a/core/src/test/resources/google/registry/module/frontend/frontend_routing.txt +++ b/core/src/test/resources/google/registry/module/frontend/frontend_routing.txt @@ -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 \ No newline at end of file +CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC diff --git a/core/src/test/resources/google/registry/module/routing.txt b/core/src/test/resources/google/registry/module/routing.txt index a616f9c60..4b8a6a77c 100644 --- a/core/src/test/resources/google/registry/module/routing.txt +++ b/core/src/test/resources/google/registry/module/routing.txt @@ -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 \ No newline at end of file +CONSOLE /console-api/users ConsoleUsersAction GET,POST,DELETE,PUT n USER PUBLIC