diff --git a/java/google/registry/env/common/default/WEB-INF/web.xml b/java/google/registry/env/common/default/WEB-INF/web.xml index de631d77a..dc37a1e7f 100644 --- a/java/google/registry/env/common/default/WEB-INF/web.xml +++ b/java/google/registry/env/common/default/WEB-INF/web.xml @@ -49,18 +49,6 @@ /registrar-settings - - - frontend-servlet - /registrar-premium-price-ack - - frontend-servlet diff --git a/java/google/registry/module/frontend/FrontendRequestComponent.java b/java/google/registry/module/frontend/FrontendRequestComponent.java index 52d504b54..118343789 100644 --- a/java/google/registry/module/frontend/FrontendRequestComponent.java +++ b/java/google/registry/module/frontend/FrontendRequestComponent.java @@ -40,7 +40,6 @@ import google.registry.request.RequestScope; import google.registry.ui.server.registrar.ConsoleUiAction; import google.registry.ui.server.registrar.RegistrarPaymentAction; import google.registry.ui.server.registrar.RegistrarPaymentSetupAction; -import google.registry.ui.server.registrar.RegistrarPremiumPriceAckAction; import google.registry.ui.server.registrar.RegistrarSettingsAction; import google.registry.whois.WhoisAction; import google.registry.whois.WhoisHttpAction; @@ -67,7 +66,6 @@ interface FrontendRequestComponent { RdapAutnumAction rdapAutnumAction(); RegistrarPaymentAction registrarPaymentAction(); RegistrarPaymentSetupAction registrarPaymentSetupAction(); - RegistrarPremiumPriceAckAction registrarPremiumPriceAckAction(); RegistrarSettingsAction registrarSettingsAction(); RdapDomainAction rdapDomainAction(); RdapDomainSearchAction rdapDomainSearchAction(); diff --git a/java/google/registry/ui/js/registrar/resources.js b/java/google/registry/ui/js/registrar/resources.js index a5e393725..003636b90 100644 --- a/java/google/registry/ui/js/registrar/resources.js +++ b/java/google/registry/ui/js/registrar/resources.js @@ -37,7 +37,7 @@ registry.registrar.Resources = function(console, xsrfToken) { this, 'constructor', console, - new registry.Resource(new goog.Uri('/registrar-premium-price-ack'), xsrfToken), + new registry.Resource(new goog.Uri('/registrar-settings'), xsrfToken), registry.soy.registrar.console.resources, null); }; diff --git a/java/google/registry/ui/server/registrar/RegistrarPremiumPriceAckAction.java b/java/google/registry/ui/server/registrar/RegistrarPremiumPriceAckAction.java deleted file mode 100644 index 5079f4560..000000000 --- a/java/google/registry/ui/server/registrar/RegistrarPremiumPriceAckAction.java +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2017 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.model.ofy.ObjectifyService.ofy; -import static google.registry.security.JsonResponseHelper.Status.ERROR; -import static google.registry.security.JsonResponseHelper.Status.SUCCESS; -import static google.registry.ui.server.registrar.RegistrarSettingsAction.ARGS_PARAM; -import static google.registry.ui.server.registrar.RegistrarSettingsAction.OP_PARAM; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import google.registry.config.RegistryConfig.Config; -import google.registry.export.sheet.SyncRegistrarsSheetAction; -import google.registry.model.registrar.Registrar; -import google.registry.request.Action; -import google.registry.request.HttpException.BadRequestException; -import google.registry.request.JsonActionRunner; -import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthResult; -import google.registry.security.JsonResponseHelper; -import google.registry.ui.forms.FormException; -import google.registry.ui.forms.FormFieldException; -import google.registry.ui.server.RegistrarFormFields; -import google.registry.util.CollectionUtils; -import google.registry.util.DiffUtils; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; - -/** - * Action handler for toggling the "Premium Price Ack Required" flag. - * - *

This class exists to supplement RegistrarSettings, which is supposed to take care of - * everything but mostly doesn't work. - */ -@Action( - path = RegistrarPremiumPriceAckAction.PATH, - method = Action.Method.POST, - auth = Auth.AUTH_PUBLIC_LOGGED_IN -) -public class RegistrarPremiumPriceAckAction implements Runnable, JsonActionRunner.JsonAction { - public static final String PATH = "/registrar-premium-price-ack"; - - @Inject AuthResult authResult; - @Inject HttpServletRequest request; - @Inject JsonActionRunner jsonActionRunner; - @Inject SendEmailUtils sendEmailUtils; - @Inject SessionUtils sessionUtils; - - @Inject - @Config("registrarChangesNotificationEmailAddresses") - ImmutableList registrarChangesNotificationEmailAddresses; - - @Inject - RegistrarPremiumPriceAckAction() {} - - @Override - public void run() { - jsonActionRunner.run(this); - } - - @Override - public Map handleJsonRequest(Map input) { - if (input == null) { - throw new BadRequestException("Malformed JSON"); - } - - // Get the registrar - Registrar initialRegistrar = sessionUtils.getRegistrarForAuthResult(request, authResult); - - // Process the operation. Though originally derived from a CRUD handler, registrar-settings - // and registrar-premium-price-action really only support read and update. - String op = Optional.ofNullable((String) input.get(OP_PARAM)).orElse("read"); - @SuppressWarnings("unchecked") - Map args = - (Map) - Optional.ofNullable(input.get(ARGS_PARAM)).orElse(ImmutableMap.of()); - try { - switch (op) { - case "update": - return update(args, initialRegistrar); - case "read": - // Though this class only exists to support update of the premiumPriceAckRequired flag, - // "read" gives back a javascript representation of the entire registrar object to support - // the architecture of the console. - return JsonResponseHelper.create(SUCCESS, "Success", initialRegistrar.toJsonMap()); - default: - return JsonResponseHelper.create(ERROR, "Unknown or unsupported operation: " + op); - } - } catch (FormFieldException e) { - return JsonResponseHelper.createFormFieldError(e.getMessage(), e.getFieldName()); - } catch (FormException e) { - return JsonResponseHelper.create(ERROR, e.getMessage()); - } - } - - Map update(final Map args, final Registrar registrar) { - final String clientId = sessionUtils.getRegistrarClientId(request); - return ofy() - .transact( - () -> { - // Verify that the registrar hasn't been changed. - Optional latest = Registrar.loadByClientId(registrar.getClientId()); - if (!latest.isPresent() - || latest.get().getPremiumPriceAckRequired() - != registrar.getPremiumPriceAckRequired()) { - return JsonResponseHelper.create( - ERROR, - "Premium price ack has changed (or registrar no longer exists). " - + "Please reload."); - } - Registrar reg = latest.get(); - - Optional premiumPriceAckRequired = - RegistrarFormFields.PREMIUM_PRICE_ACK_REQUIRED.extractUntyped(args); - if (premiumPriceAckRequired.isPresent() - && premiumPriceAckRequired.get() != reg.getPremiumPriceAckRequired()) { - Registrar updatedRegistrar = - reg.asBuilder() - .setPremiumPriceAckRequired(premiumPriceAckRequired.get()) - .build(); - ofy().save().entity(updatedRegistrar); - sendExternalUpdatesIfNecessary(reg, updatedRegistrar); - return JsonResponseHelper.create( - SUCCESS, "Saved " + clientId, updatedRegistrar.toJsonMap()); - } else { - return JsonResponseHelper.create(SUCCESS, "Unchanged " + clientId, reg.toJsonMap()); - } - }); - } - - private void sendExternalUpdatesIfNecessary( - Registrar existingRegistrar, Registrar updatedRegistrar) { - if (registrarChangesNotificationEmailAddresses.isEmpty()) { - return; - } - - Map diffs = - DiffUtils.deepDiff( - existingRegistrar.toDiffableFieldMap(), updatedRegistrar.toDiffableFieldMap(), true); - @SuppressWarnings("unchecked") - Set changedKeys = (Set) diffs.keySet(); - if (CollectionUtils.difference(changedKeys, "lastUpdateTime").isEmpty()) { - return; - } - SyncRegistrarsSheetAction.enqueueBackendTask(); - if (!registrarChangesNotificationEmailAddresses.isEmpty()) { - sendEmailUtils.sendEmail( - registrarChangesNotificationEmailAddresses, - String.format("Registrar %s updated", existingRegistrar.getRegistrarName()), - "The following changes were made to the registrar:\n" - + DiffUtils.prettyPrintDiffedMap(diffs, null)); - } - } -} diff --git a/javatests/google/registry/module/frontend/testdata/frontend_routing.txt b/javatests/google/registry/module/frontend/testdata/frontend_routing.txt index a0f942d3d..d95557c10 100644 --- a/javatests/google/registry/module/frontend/testdata/frontend_routing.txt +++ b/javatests/google/registry/module/frontend/testdata/frontend_routing.txt @@ -1,20 +1,19 @@ -PATH CLASS METHODS OK AUTH_METHODS MIN USER_POLICY -/_dr/epp EppTlsAction POST n INTERNAL,API APP ADMIN -/_dr/whois WhoisAction POST n INTERNAL,API APP ADMIN -/check CheckApiAction GET n INTERNAL NONE PUBLIC -/rdap/autnum/(*) RdapAutnumAction GET,HEAD n INTERNAL NONE PUBLIC -/rdap/domain/(*) RdapDomainAction GET,HEAD n INTERNAL,API,LEGACY NONE PUBLIC -/rdap/domains RdapDomainSearchAction GET,HEAD n INTERNAL,API,LEGACY NONE PUBLIC -/rdap/entities RdapEntitySearchAction GET,HEAD n INTERNAL,API,LEGACY NONE PUBLIC -/rdap/entity/(*) RdapEntityAction GET,HEAD n INTERNAL,API,LEGACY NONE PUBLIC -/rdap/help(*) RdapHelpAction GET,HEAD n INTERNAL NONE PUBLIC -/rdap/ip/(*) RdapIpAction GET,HEAD n INTERNAL NONE PUBLIC -/rdap/nameserver/(*) RdapNameserverAction GET,HEAD n INTERNAL NONE PUBLIC -/rdap/nameservers RdapNameserverSearchAction GET,HEAD n INTERNAL NONE PUBLIC -/registrar ConsoleUiAction GET n INTERNAL,API,LEGACY NONE PUBLIC -/registrar-payment RegistrarPaymentAction POST n API,LEGACY USER PUBLIC -/registrar-payment-setup RegistrarPaymentSetupAction POST n API,LEGACY USER PUBLIC -/registrar-premium-price-ack RegistrarPremiumPriceAckAction POST n API,LEGACY USER PUBLIC -/registrar-settings RegistrarSettingsAction POST n API,LEGACY USER PUBLIC -/registrar-xhr EppConsoleAction POST n API,LEGACY USER PUBLIC -/whois/(*) WhoisHttpAction GET n INTERNAL NONE PUBLIC +PATH CLASS METHODS OK AUTH_METHODS MIN USER_POLICY +/_dr/epp EppTlsAction POST n INTERNAL,API APP ADMIN +/_dr/whois WhoisAction POST n INTERNAL,API APP ADMIN +/check CheckApiAction GET n INTERNAL NONE PUBLIC +/rdap/autnum/(*) RdapAutnumAction GET,HEAD n INTERNAL NONE PUBLIC +/rdap/domain/(*) RdapDomainAction GET,HEAD n INTERNAL,API,LEGACY NONE PUBLIC +/rdap/domains RdapDomainSearchAction GET,HEAD n INTERNAL,API,LEGACY NONE PUBLIC +/rdap/entities RdapEntitySearchAction GET,HEAD n INTERNAL,API,LEGACY NONE PUBLIC +/rdap/entity/(*) RdapEntityAction GET,HEAD n INTERNAL,API,LEGACY NONE PUBLIC +/rdap/help(*) RdapHelpAction GET,HEAD n INTERNAL NONE PUBLIC +/rdap/ip/(*) RdapIpAction GET,HEAD n INTERNAL NONE PUBLIC +/rdap/nameserver/(*) RdapNameserverAction GET,HEAD n INTERNAL NONE PUBLIC +/rdap/nameservers RdapNameserverSearchAction GET,HEAD n INTERNAL NONE PUBLIC +/registrar ConsoleUiAction GET n INTERNAL,API,LEGACY NONE PUBLIC +/registrar-payment RegistrarPaymentAction POST n API,LEGACY USER PUBLIC +/registrar-payment-setup RegistrarPaymentSetupAction POST n API,LEGACY USER PUBLIC +/registrar-settings RegistrarSettingsAction POST n API,LEGACY USER PUBLIC +/registrar-xhr EppConsoleAction POST n API,LEGACY USER PUBLIC +/whois/(*) WhoisHttpAction GET n INTERNAL NONE PUBLIC diff --git a/javatests/google/registry/server/RegistryTestServer.java b/javatests/google/registry/server/RegistryTestServer.java index 4cf4c95fb..911eb7a52 100644 --- a/javatests/google/registry/server/RegistryTestServer.java +++ b/javatests/google/registry/server/RegistryTestServer.java @@ -88,8 +88,6 @@ public final class RegistryTestServer { route("/registrar", google.registry.module.frontend.FrontendServlet.class), route("/registrar-settings", google.registry.module.frontend.FrontendServlet.class), - route("/registrar-premium-price-ack", - google.registry.module.frontend.FrontendServlet.class), route("/registrar-payment", google.registry.module.frontend.FrontendServlet.class), route("/registrar-payment-setup", diff --git a/javatests/google/registry/ui/js/registrar/console_test.js b/javatests/google/registry/ui/js/registrar/console_test.js index b02b65238..074829925 100644 --- a/javatests/google/registry/ui/js/registrar/console_test.js +++ b/javatests/google/registry/ui/js/registrar/console_test.js @@ -134,7 +134,7 @@ function testNavToResources() { }); var xhr = goog.testing.net.XhrIo.getSendInstances().pop(); assertTrue(xhr.isActive()); - assertEquals('/registrar-premium-price-ack', xhr.getLastUri()); + assertEquals('/registrar-settings', xhr.getLastUri()); assertEquals(test.testXsrfToken, xhr.getLastRequestHeaders().get('X-CSRF-Token')); xhr.simulateResponse(200, goog.json.serialize({ diff --git a/javatests/google/registry/ui/server/registrar/RegistrarPremiumPriceAckActionTest.java b/javatests/google/registry/ui/server/registrar/RegistrarPremiumPriceAckActionTest.java deleted file mode 100644 index bd08a09ca..000000000 --- a/javatests/google/registry/ui/server/registrar/RegistrarPremiumPriceAckActionTest.java +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2017 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.config.RegistryConfig.getGSuiteOutgoingEmailAddress; -import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailDisplayName; -import static google.registry.security.JsonHttpTestUtils.createJsonPayload; -import static google.registry.testing.DatastoreHelper.loadRegistrar; -import static google.registry.testing.DatastoreHelper.persistResource; -import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued; -import static google.registry.testing.TestDataHelper.loadFile; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.appengine.api.modules.ModulesService; -import com.google.appengine.api.users.User; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import google.registry.export.sheet.SyncRegistrarsSheetAction; -import google.registry.model.registrar.Registrar; -import google.registry.model.registrar.RegistrarContact; -import google.registry.request.JsonActionRunner; -import google.registry.request.JsonResponse; -import google.registry.request.ResponseImpl; -import google.registry.request.auth.AuthLevel; -import google.registry.request.auth.AuthResult; -import google.registry.request.auth.UserAuthInfo; -import google.registry.testing.AppEngineRule; -import google.registry.testing.FakeHttpSession; -import google.registry.testing.InjectRule; -import google.registry.testing.TaskQueueHelper.TaskMatcher; -import google.registry.util.SendEmailService; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Map; -import java.util.Properties; -import javax.mail.Message; -import javax.mail.Session; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -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 class RegistrarPremiumPriceAckActionTest { - - private static final String CLIENT_ID = "NewRegistrar"; - - private final RegistrarPremiumPriceAckAction action = new RegistrarPremiumPriceAckAction(); - - public RegistrarPremiumPriceAckActionTest() {} - - @Rule - public final AppEngineRule appEngine = - AppEngineRule.builder().withDatastore().withTaskQueue().build(); - - @Rule public final InjectRule inject = new InjectRule(); - - final HttpServletRequest req = mock(HttpServletRequest.class); - final HttpServletResponse rsp = mock(HttpServletResponse.class); - final SendEmailService emailService = mock(SendEmailService.class); - final ModulesService modulesService = mock(ModulesService.class); - final User user = - new User("janedoe", "theregistrar.com", AppEngineRule.NEW_REGISTRAR_GAE_USER_ID); - - Message message; - - final StringWriter writer = new StringWriter(); - - @Before - public void setUp() throws Exception { - action.request = req; - action.sessionUtils = new SessionUtils(); - action.sessionUtils.registryAdminClientId = CLIENT_ID; - action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false)); - action.jsonActionRunner = - new JsonActionRunner(ImmutableMap.of(), new JsonResponse(new ResponseImpl(rsp))); - action.registrarChangesNotificationEmailAddresses = - ImmutableList.of("notification@test.example", "notification2@test.example"); - action.sendEmailUtils = - new SendEmailUtils(getGSuiteOutgoingEmailAddress(), getGSuiteOutgoingEmailDisplayName()); - - message = new MimeMessage(Session.getDefaultInstance(new Properties(), null)); - when(emailService.createMessage()).thenReturn(message); - when(req.getMethod()).thenReturn("POST"); - when(rsp.getWriter()).thenReturn(new PrintWriter(writer)); - when(req.getContentType()).thenReturn("application/json"); - when(req.getReader()).thenReturn(createJsonPayload(ImmutableMap.of("op", "read"))); - when(modulesService.getVersionHostname("backend", null)).thenReturn("backend.hostname"); - FakeHttpSession session = new FakeHttpSession(); - when(req.getSession()).thenReturn(session); - session.setAttribute(SessionUtils.CLIENT_ID_ATTRIBUTE, CLIENT_ID); - - inject.setStaticField(SendEmailUtils.class, "emailService", emailService); - inject.setStaticField(SyncRegistrarsSheetAction.class, "modulesService", modulesService); - - Registrar registrar = AppEngineRule.makeRegistrar1(); - RegistrarContact contact = AppEngineRule.makeRegistrarContact1(); - persistResource(registrar); - persistResource(contact); - } - - @Test - public void testPost_updatePremiumPriceAckRequired() throws Exception { - Registrar registrar = loadRegistrar(CLIENT_ID); - - Registrar modified = registrar.asBuilder().setPremiumPriceAckRequired(true).build(); - Map reqJson = modified.toJsonMap(); - Map response = - action.handleJsonRequest(ImmutableMap.of("op", "update", "args", reqJson)); - assertThat(response).containsEntry("status", "SUCCESS"); - assertThat(loadRegistrar(CLIENT_ID).getPremiumPriceAckRequired()).isTrue(); - - // Verify that we sent notification emails. - String expectedEmailBody = loadFile(getClass(), "update_ppa_email.txt"); - verify(rsp, never()).setStatus(anyInt()); - verify(emailService).createMessage(); - verify(emailService).sendMessage(message); - assertThat(message.getAllRecipients()) - .asList() - .containsExactly( - new InternetAddress("notification@test.example"), - new InternetAddress("notification2@test.example")); - assertThat(message.getContent()).isEqualTo(expectedEmailBody); - assertTasksEnqueued( - "sheet", - new TaskMatcher() - .url(SyncRegistrarsSheetAction.PATH) - .method("GET") - .header("Host", "backend.hostname")); - - // Verify that switching back also works. - modified = modified.asBuilder().setPremiumPriceAckRequired(false).build(); - reqJson = modified.toJsonMap(); - response = action.handleJsonRequest(ImmutableMap.of("op", "update", "args", reqJson)); - assertThat(response).containsEntry("status", "SUCCESS"); - assertThat(loadRegistrar(CLIENT_ID).getPremiumPriceAckRequired()).isFalse(); - } -}