From 0e808a4c010f01a67e775a46c8491d9e047bd76b Mon Sep 17 00:00:00 2001 From: Pavlo Tkach <3469726+ptkach@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:03:56 -0400 Subject: [PATCH] Add OT&E create and status to the new console (#2534) --- .../model/registrar/RegistrarBase.java | 1 + .../registry/module/RequestComponent.java | 3 + .../frontend/FrontendRequestComponent.java | 3 + .../ui/server/console/ConsoleModule.java | 8 + .../ui/server/console/ConsoleOteAction.java | 174 ++++++++++++ .../server/console/ConsoleOteActionTest.java | 255 ++++++++++++++++++ .../module/frontend/frontend_routing.txt | 3 +- .../google/registry/module/routing.txt | 3 +- 8 files changed, 448 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/google/registry/ui/server/console/ConsoleOteAction.java create mode 100644 core/src/test/java/google/registry/ui/server/console/ConsoleOteActionTest.java diff --git a/core/src/main/java/google/registry/model/registrar/RegistrarBase.java b/core/src/main/java/google/registry/model/registrar/RegistrarBase.java index b659682d2..be5b41f4c 100644 --- a/core/src/main/java/google/registry/model/registrar/RegistrarBase.java +++ b/core/src/main/java/google/registry/model/registrar/RegistrarBase.java @@ -233,6 +233,7 @@ public class RegistrarBase extends UpdateAutoTimestampEntity implements Buildabl String registrarName; /** The type of this registrar. */ + @Expose @Column(nullable = false) @Enumerated(EnumType.STRING) Type type; diff --git a/core/src/main/java/google/registry/module/RequestComponent.java b/core/src/main/java/google/registry/module/RequestComponent.java index dc1e0bf2b..858474687 100644 --- a/core/src/main/java/google/registry/module/RequestComponent.java +++ b/core/src/main/java/google/registry/module/RequestComponent.java @@ -114,6 +114,7 @@ import google.registry.ui.server.console.ConsoleDomainListAction; import google.registry.ui.server.console.ConsoleDumDownloadAction; import google.registry.ui.server.console.ConsoleEppPasswordAction; import google.registry.ui.server.console.ConsoleModule; +import google.registry.ui.server.console.ConsoleOteAction; import google.registry.ui.server.console.ConsoleRegistryLockAction; import google.registry.ui.server.console.ConsoleRegistryLockVerifyAction; import google.registry.ui.server.console.ConsoleUpdateRegistrarAction; @@ -178,6 +179,8 @@ interface RequestComponent { ConsoleEppPasswordAction consoleEppPasswordAction(); + ConsoleOteAction consoleOteAction(); + ConsoleRegistryLockAction consoleRegistryLockAction(); ConsoleRegistryLockVerifyAction consoleRegistryLockVerifyAction(); 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 50d78ce08..30c20b5c4 100644 --- a/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java +++ b/core/src/main/java/google/registry/module/frontend/FrontendRequestComponent.java @@ -30,6 +30,7 @@ import google.registry.ui.server.console.ConsoleDomainListAction; import google.registry.ui.server.console.ConsoleDumDownloadAction; import google.registry.ui.server.console.ConsoleEppPasswordAction; import google.registry.ui.server.console.ConsoleModule; +import google.registry.ui.server.console.ConsoleOteAction; import google.registry.ui.server.console.ConsoleRegistryLockAction; import google.registry.ui.server.console.ConsoleRegistryLockVerifyAction; import google.registry.ui.server.console.ConsoleUpdateRegistrarAction; @@ -65,6 +66,8 @@ public interface FrontendRequestComponent { ConsoleEppPasswordAction consoleEppPasswordAction(); + ConsoleOteAction consoleOteAction(); + ConsoleOteSetupAction consoleOteSetupAction(); ConsoleRegistrarCreatorAction consoleRegistrarCreatorAction(); diff --git a/core/src/main/java/google/registry/ui/server/console/ConsoleModule.java b/core/src/main/java/google/registry/ui/server/console/ConsoleModule.java index d8fd8efe4..181d84cf0 100644 --- a/core/src/main/java/google/registry/ui/server/console/ConsoleModule.java +++ b/core/src/main/java/google/registry/ui/server/console/ConsoleModule.java @@ -34,6 +34,7 @@ import google.registry.request.auth.AuthResult; import google.registry.security.XsrfTokenManager; import google.registry.ui.server.SendEmailUtils; import google.registry.ui.server.console.ConsoleEppPasswordAction.EppPasswordData; +import google.registry.ui.server.console.ConsoleOteAction.OteCreateData; import google.registry.ui.server.console.ConsoleRegistryLockAction.ConsoleRegistryLockPostInput; import jakarta.servlet.http.HttpServletRequest; import java.util.Optional; @@ -244,6 +245,13 @@ public final class ConsoleModule { return payload.map(s -> gson.fromJson(s, EppPasswordData.class)); } + @Provides + @Parameter("oteCreateData") + public static Optional provideOteCreateData( + Gson gson, @OptionalJsonPayload Optional payload) { + return payload.map(s -> gson.fromJson(s, OteCreateData.class)); + } + @Provides @Parameter("consoleRegistryLockPostInput") public static Optional provideRegistryLockPostInput( diff --git a/core/src/main/java/google/registry/ui/server/console/ConsoleOteAction.java b/core/src/main/java/google/registry/ui/server/console/ConsoleOteAction.java new file mode 100644 index 000000000..b98a4a27d --- /dev/null +++ b/core/src/main/java/google/registry/ui/server/console/ConsoleOteAction.java @@ -0,0 +1,174 @@ +// 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.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.ImmutableList.toImmutableList; +import static google.registry.persistence.transaction.TransactionManagerFactory.tm; +import static google.registry.request.Action.Method.GET; +import static google.registry.request.Action.Method.POST; +import static google.registry.util.RegistryEnvironment.PRODUCTION; +import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN; +import static jakarta.servlet.http.HttpServletResponse.SC_OK; + +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; +import com.google.gson.annotations.Expose; +import google.registry.config.RegistryConfig.Config; +import google.registry.model.OteAccountBuilder; +import google.registry.model.OteStats; +import google.registry.model.OteStats.StatType; +import google.registry.model.console.ConsolePermission; +import google.registry.model.console.User; +import google.registry.model.registrar.Registrar; +import google.registry.model.registrar.RegistrarBase; +import google.registry.request.Action; +import google.registry.request.Action.GkeService; +import google.registry.request.Parameter; +import google.registry.request.auth.Auth; +import google.registry.tools.IamClient; +import google.registry.util.RegistryEnvironment; +import google.registry.util.StringGenerator; +import java.util.Map; +import java.util.Optional; +import javax.inject.Inject; +import javax.inject.Named; + +@Action( + service = Action.Service.DEFAULT, + gkeService = GkeService.CONSOLE, + path = ConsoleOteAction.PATH, + method = {GET, POST}, + auth = Auth.AUTH_PUBLIC_LOGGED_IN) +public class ConsoleOteAction extends ConsoleApiAction { + static final String PATH = "/console-api/ote"; + private static final int PASSWORD_LENGTH = 16; + private static final String COMPLETED_PARAM = "completed"; + private static final String STAT_TYPE_DESCRIPTION_PARAM = "description"; + private static final String STAT_TYPE_REQUIREMENT_PARAM = "requirement"; + private static final String STAT_TYPE_TIMES_PERFORMED_PARAM = "timesPerformed"; + private final Gson gson; + private final StringGenerator passwordGenerator; + private final Optional oteCreateData; + private final Optional maybeGroupEmailAddress; + private final IamClient iamClient; + private final String registrarId; + + @Inject + public ConsoleOteAction( + ConsoleApiParams consoleApiParams, + Gson gson, + IamClient iamClient, + @Parameter("registrarId") String registrarId, // Get request param + @Config("gSuiteConsoleUserGroupEmailAddress") Optional maybeGroupEmailAddress, + @Named("base58StringGenerator") StringGenerator passwordGenerator, + @Parameter("oteCreateData") Optional oteCreateData) { + super(consoleApiParams); + this.gson = gson; + this.passwordGenerator = passwordGenerator; + this.oteCreateData = oteCreateData; + this.maybeGroupEmailAddress = maybeGroupEmailAddress; + this.iamClient = iamClient; + this.registrarId = registrarId; + } + + @Override + protected void postHandler(User user) { + checkState(!RegistryEnvironment.get().equals(PRODUCTION), "Can't create OT&E in prod"); + + if (!user.getUserRoles().hasGlobalPermission(ConsolePermission.EDIT_REGISTRAR_DETAILS)) { + setFailedResponse("User doesn't have a permission to create OT&E accounts", SC_FORBIDDEN); + return; + } + + boolean isBodyValid = + this.oteCreateData.isPresent() + && !this.oteCreateData.get().registrarId.isEmpty() + && !this.oteCreateData.get().registrarEmail.isEmpty(); + + checkArgument(isBodyValid, "OT&E create body is invalid"); + + String password = passwordGenerator.createString(PASSWORD_LENGTH); + + OteAccountBuilder oteAccountBuilder = + OteAccountBuilder.forRegistrarId(this.oteCreateData.get().registrarId) + .addUser(this.oteCreateData.get().registrarEmail) + .setPassword(password); + + ImmutableMap registrarIdToTld = oteAccountBuilder.buildAndPersist(); + oteAccountBuilder.grantIapPermission(maybeGroupEmailAddress, cloudTasksUtils, iamClient); + consoleApiParams.response().setStatus(SC_OK); + consoleApiParams + .response() + .setPayload( + gson.toJson( + ImmutableMap.builder().putAll(registrarIdToTld).put("password", password).build())); + } + + @Override + protected void getHandler(User user) { + checkArgument(!Strings.isNullOrEmpty(registrarId), "Missing registrarId parameter"); + + if (!user.getUserRoles().hasGlobalPermission(ConsolePermission.EDIT_REGISTRAR_DETAILS)) { + setFailedResponse("User doesn't have a permission to check OT&E status", SC_BAD_REQUEST); + return; + } + + String baseRegistrarId = OteAccountBuilder.getBaseRegistrarId(registrarId); + tm().transact( + () -> { + Optional registrar = Registrar.loadByRegistrarId(registrarId); + if (registrar.isEmpty()) { + setFailedResponse( + String.format("Registrar with ID %s is not present", registrarId), + SC_BAD_REQUEST); + return; + } + if (!RegistrarBase.Type.OTE.equals(registrar.get().getType())) { + setFailedResponse( + String.format("Registrar with ID %s is not an OT&E registrar", registrarId), + SC_BAD_REQUEST); + return; + } + OteStats oteStats = OteStats.getFromRegistrar(baseRegistrarId); + var stats = + StatType.REQUIRED_STAT_TYPES.stream() + .map( + statType -> + convertSingleRequirement(statType, oteStats.getCount(statType))) + .collect(toImmutableList()); + consoleApiParams.response().setStatus(SC_OK); + consoleApiParams.response().setPayload(gson.toJson(stats)); + }); + } + + private Map convertSingleRequirement(StatType statType, int count) { + int requirement = statType.getRequirement(); + return ImmutableMap.of( + STAT_TYPE_DESCRIPTION_PARAM, + statType.getDescription(), + STAT_TYPE_REQUIREMENT_PARAM, + requirement, + STAT_TYPE_TIMES_PERFORMED_PARAM, + count, + COMPLETED_PARAM, + count >= requirement); + } + + public record OteCreateData(@Expose String registrarId, @Expose String registrarEmail) {} +} diff --git a/core/src/test/java/google/registry/ui/server/console/ConsoleOteActionTest.java b/core/src/test/java/google/registry/ui/server/console/ConsoleOteActionTest.java new file mode 100644 index 000000000..6c5c0693f --- /dev/null +++ b/core/src/test/java/google/registry/ui/server/console/ConsoleOteActionTest.java @@ -0,0 +1,255 @@ +// 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.truth.Truth.assertThat; +import static google.registry.model.OteAccountBuilderTest.verifyIapPermission; +import static google.registry.testing.DatabaseHelper.persistPremiumList; +import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN; +import static jakarta.servlet.http.HttpServletResponse.SC_OK; +import static org.joda.money.CurrencyUnit.USD; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; +import google.registry.model.OteStatsTestHelper; +import google.registry.model.console.GlobalRole; +import google.registry.model.console.User; +import google.registry.model.console.UserRoles; +import google.registry.persistence.transaction.JpaTestExtensions; +import google.registry.request.Action; +import google.registry.request.auth.AuthResult; +import google.registry.testing.CloudTasksHelper; +import google.registry.testing.ConsoleApiParamsUtils; +import google.registry.testing.DeterministicStringGenerator; +import google.registry.testing.FakeResponse; +import google.registry.tools.GsonUtils; +import google.registry.tools.IamClient; +import google.registry.ui.server.console.ConsoleOteAction.OteCreateData; +import google.registry.util.StringGenerator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import org.json.simple.JSONArray; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class ConsoleOteActionTest { + + @RegisterExtension + final JpaTestExtensions.JpaIntegrationTestExtension jpa = + new JpaTestExtensions.Builder().buildIntegrationTestExtension(); + + private static final Gson GSON = GsonUtils.provideGson(); + private final IamClient iamClient = mock(IamClient.class); + private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper(); + private FakeResponse response; + private ConsoleApiParams consoleApiParams; + + private StringGenerator passwordGenerator = + new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz"); + + private User user = + new User.Builder() + .setEmailAddress("marla.singer@example.com") + .setUserRoles(new UserRoles()) + .build(); + + @BeforeEach + void beforeEach() throws Exception { + persistPremiumList("default_sandbox_list", USD, "sandbox,USD 1000"); + } + + @Test + void testFailure_missingGlobalPermission() { + AuthResult authResult = AuthResult.createUser(user); + consoleApiParams = ConsoleApiParamsUtils.createFake(authResult); + ConsoleOteAction action = + createAction( + Action.Method.POST, + authResult, + "testRegistrarId", + Optional.of("someRandomString"), + Optional.of(new OteCreateData("testRegistrarId", "tescontact@registry.example"))); + action.run(); + assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_FORBIDDEN); + } + + @Test + void testFailure_invalidParamsNoRegistrarId() { + user = + user.asBuilder() + .setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()) + .build(); + AuthResult authResult = AuthResult.createUser(user); + consoleApiParams = ConsoleApiParamsUtils.createFake(authResult); + ConsoleOteAction action = + createAction( + Action.Method.POST, + authResult, + "testRegistrarId", + Optional.of("someRandomString"), + Optional.of(new OteCreateData("", "test@email.com"))); + action.run(); + assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST); + assertThat(((FakeResponse) consoleApiParams.response()).getPayload()) + .isEqualTo("OT&E create body is invalid"); + } + + @Test + void testFailure_invalidParamsNoEmail() { + user = + user.asBuilder() + .setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()) + .build(); + AuthResult authResult = AuthResult.createUser(user); + consoleApiParams = ConsoleApiParamsUtils.createFake(authResult); + ConsoleOteAction action = + createAction( + Action.Method.POST, + authResult, + "testRegistrarId", + Optional.of("someRandomString"), + Optional.of(new OteCreateData("testRegistrarId", ""))); + action.run(); + assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST); + assertThat(((FakeResponse) consoleApiParams.response()).getPayload()) + .isEqualTo("OT&E create body is invalid"); + } + + @Test + void testSuccess_oteCreated() { + user = + user.asBuilder() + .setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()) + .build(); + AuthResult authResult = AuthResult.createUser(user); + consoleApiParams = ConsoleApiParamsUtils.createFake(authResult); + ConsoleOteAction action = + createAction( + Action.Method.POST, + authResult, + "theregistrar", + Optional.of("someRandomString@email.test"), + Optional.of(new OteCreateData("theregistrar", "contact@registry.example"))); + action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils(); + action.run(); + String response = ((FakeResponse) consoleApiParams.response()).getPayload(); + var obsResponse = GSON.fromJson(response, Map.class); + assertThat( + ImmutableMap.of( + "theregistrar-1", "theregistrar-sunrise", + "theregistrar-3", "theregistrar-ga", + "theregistrar-4", "theregistrar-ga", + "theregistrar-5", "theregistrar-eap", + "password", "abcdefghijklmnop")) + .containsExactlyEntriesIn(obsResponse); + assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK); + verifyIapPermission( + "contact@registry.example", + Optional.of("someRandomString@email.test"), + cloudTasksHelper, + iamClient); + } + + @Test + void testFail_statusMissingParam() { + AuthResult authResult = AuthResult.createUser(user); + consoleApiParams = ConsoleApiParamsUtils.createFake(authResult); + ConsoleOteAction action = + createAction( + Action.Method.GET, + authResult, + "", + Optional.of("someRandomString@email.test"), + Optional.of(new OteCreateData("theregistrar", "contact@registry.example"))); + action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils(); + action.run(); + assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST); + assertThat(((FakeResponse) consoleApiParams.response()).getPayload()) + .isEqualTo("Missing registrarId parameter"); + } + + @Test + void testSuccess_finishedOte() throws Exception { + OteStatsTestHelper.setupCompleteOte("theregistrar"); + user = + user.asBuilder() + .setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()) + .build(); + AuthResult authResult = AuthResult.createUser(user); + consoleApiParams = ConsoleApiParamsUtils.createFake(authResult); + ConsoleOteAction action = + createAction( + Action.Method.GET, authResult, "theregistrar-1", Optional.empty(), Optional.empty()); + action.run(); + + List> response = + GSON.fromJson(((FakeResponse) consoleApiParams.response()).getPayload(), JSONArray.class); + assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK); + assertTrue(response.stream().allMatch(status -> Boolean.TRUE.equals(status.get("completed")))); + } + + @Test + void testSuccess_unfinishedOte() throws Exception { + OteStatsTestHelper.setupIncompleteOte("theregistrar"); + user = + user.asBuilder() + .setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build()) + .build(); + AuthResult authResult = AuthResult.createUser(user); + consoleApiParams = ConsoleApiParamsUtils.createFake(authResult); + ConsoleOteAction action = + createAction( + Action.Method.GET, authResult, "theregistrar-1", Optional.empty(), Optional.empty()); + action.run(); + + List> response = + GSON.fromJson(((FakeResponse) consoleApiParams.response()).getPayload(), JSONArray.class); + assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK); + assertThat( + response.stream() + .filter(status -> Boolean.FALSE.equals(status.get("completed"))) + .map(status -> status.get("description")) + .collect(Collectors.toList())) + .containsExactlyElementsIn( + ImmutableList.of("domain creates idn", "domain restores", "host deletes")); + } + + private ConsoleOteAction createAction( + Action.Method method, + AuthResult authResult, + String registrarId, + Optional maybeGroupEmailAddress, + Optional oteCreateData) { + response = new FakeResponse(); + consoleApiParams = ConsoleApiParamsUtils.createFake(authResult); + when(consoleApiParams.request().getMethod()).thenReturn(method.toString()); + return new ConsoleOteAction( + consoleApiParams, + GSON, + iamClient, + registrarId, + maybeGroupEmailAddress, + passwordGenerator, + oteCreateData); + } +} 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 6e32e058c..c955841fd 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 @@ -12,6 +12,7 @@ CONSOLE /console-api/domain ConsoleDomainGetAction GET CONSOLE /console-api/domain-list ConsoleDomainListAction GET n USER PUBLIC CONSOLE /console-api/dum-download ConsoleDumDownloadAction GET n USER PUBLIC CONSOLE /console-api/eppPassword ConsoleEppPasswordAction POST n USER PUBLIC +CONSOLE /console-api/ote ConsoleOteAction GET,POST n USER PUBLIC CONSOLE /console-api/registrar ConsoleUpdateRegistrarAction POST n USER PUBLIC CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC @@ -19,4 +20,4 @@ CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC 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/userdata ConsoleUserDataAction GET n USER PUBLIC \ No newline at end of file diff --git a/core/src/test/resources/google/registry/module/routing.txt b/core/src/test/resources/google/registry/module/routing.txt index 1bb3633a0..c86c57c34 100644 --- a/core/src/test/resources/google/registry/module/routing.txt +++ b/core/src/test/resources/google/registry/module/routing.txt @@ -70,6 +70,7 @@ CONSOLE /console-api/domain ConsoleDomainGetActi CONSOLE /console-api/domain-list ConsoleDomainListAction GET n USER PUBLIC CONSOLE /console-api/dum-download ConsoleDumDownloadAction GET n USER PUBLIC CONSOLE /console-api/eppPassword ConsoleEppPasswordAction POST n USER PUBLIC +CONSOLE /console-api/ote ConsoleOteAction GET,POST n USER PUBLIC CONSOLE /console-api/registrar ConsoleUpdateRegistrarAction POST n USER PUBLIC CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC @@ -77,4 +78,4 @@ CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockV CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC 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/userdata ConsoleUserDataAction GET n USER PUBLIC \ No newline at end of file