From 8ae2260ed1f23a174d373e71503063dd664725a0 Mon Sep 17 00:00:00 2001 From: mcilwain Date: Thu, 21 Mar 2019 09:07:17 -0700 Subject: [PATCH] Allow registrars to be completely DISABLED Disabled registrar cannot perform any actions via EPP and cannot log in to the registrar web console. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=239606389 --- .../registry/flows/session/LoginFlow.java | 2 +- .../registry/model/registrar/Registrar.java | 8 ++- .../auth/AuthenticatedRegistrarAccessor.java | 49 ++++++++++-------- java/google/registry/request/auth/BUILD | 1 + .../ValidateLoginCredentialsCommand.java | 3 +- .../flows/domain/DomainCreateFlowTest.java | 22 ++++---- .../flows/domain/DomainRenewFlowTest.java | 21 ++++---- .../flows/session/LoginFlowTestCase.java | 6 +++ .../google/registry/model/testdata/schema.txt | 1 + .../AuthenticatedRegistrarAccessorTest.java | 31 +++++++++++ .../ValidateLoginCredentialsCommandTest.java | 25 +++++++++ .../google/registry/ui/server/registrar/BUILD | 1 + .../server/registrar/ConsoleUiActionTest.java | 2 +- .../RegistrarConsoleScreenshotTest.java | 12 +++++ ...nshotTest_index_registrarDisabled_view.png | Bin 0 -> 33082 bytes 15 files changed, 138 insertions(+), 46 deletions(-) create mode 100644 javatests/google/registry/webdriver/goldens/chrome-linux/RegistrarConsoleScreenshotTest_index_registrarDisabled_view.png diff --git a/java/google/registry/flows/session/LoginFlow.java b/java/google/registry/flows/session/LoginFlow.java index ea02e8438..bf78555ca 100644 --- a/java/google/registry/flows/session/LoginFlow.java +++ b/java/google/registry/flows/session/LoginFlow.java @@ -130,7 +130,7 @@ public class LoginFlow implements Flow { throw e; } } - if (registrar.get().getState().equals(Registrar.State.PENDING)) { + if (!registrar.get().isLive()) { throw new RegistrarAccountNotActiveException(); } if (login.getNewPassword() != null) { // We don't support in-band password changes. diff --git a/java/google/registry/model/registrar/Registrar.java b/java/google/registry/model/registrar/Registrar.java index 0fb34cf63..019ccd549 100644 --- a/java/google/registry/model/registrar/Registrar.java +++ b/java/google/registry/model/registrar/Registrar.java @@ -159,7 +159,13 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable * This is a suspended account which is disallowed from provisioning new domains, but can * otherwise still perform other operations to continue operations. */ - SUSPENDED; + SUSPENDED, + + /** + * This registrar is completely disabled and cannot perform any EPP actions whatsoever, nor log + * in to the registrar console. + */ + DISABLED; } /** Regex for E.164 phone number format specified by {@code contact.xsd}. */ diff --git a/java/google/registry/request/auth/AuthenticatedRegistrarAccessor.java b/java/google/registry/request/auth/AuthenticatedRegistrarAccessor.java index 51ec7415b..520638d50 100644 --- a/java/google/registry/request/auth/AuthenticatedRegistrarAccessor.java +++ b/java/google/registry/request/auth/AuthenticatedRegistrarAccessor.java @@ -16,18 +16,22 @@ package google.registry.request.auth; import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.common.collect.Streams.stream; import static google.registry.model.ofy.ObjectifyService.ofy; import com.google.appengine.api.users.User; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.flogger.FluentLogger; +import com.googlecode.objectify.Key; import dagger.Lazy; import google.registry.config.RegistryConfig.Config; import google.registry.groups.GroupsConnection; import google.registry.model.registrar.Registrar; +import google.registry.model.registrar.Registrar.State; import google.registry.model.registrar.RegistrarContact; import java.util.Optional; import javax.annotation.concurrent.Immutable; @@ -297,6 +301,9 @@ public class AuthenticatedRegistrarAccessor { lazyGroupsConnection, user.getEmail(), gSuiteSupportGroupEmailAddress); } + /** + * Returns a map of registrar client IDs to roles for all registrars that the user has access to. + */ private static ImmutableSetMultimap createRoleMap( AuthResult authResult, boolean isAdmin, @@ -305,36 +312,36 @@ public class AuthenticatedRegistrarAccessor { if (!authResult.userAuthInfo().isPresent()) { return ImmutableSetMultimap.of(); } - UserAuthInfo userAuthInfo = authResult.userAuthInfo().get(); - User user = userAuthInfo.user(); - ImmutableSetMultimap.Builder builder = new ImmutableSetMultimap.Builder<>(); - logger.atInfo().log("Checking registrar contacts for user ID %s", user.getUserId()); - ofy() - .load() - .type(RegistrarContact.class) - .filter("gaeUserId", user.getUserId()) - .forEach(contact -> builder.put(contact.getParent().getName(), Role.OWNER)); - if (isAdmin && !Strings.isNullOrEmpty(registryAdminClientId)) { - builder.put(registryAdminClientId, Role.OWNER); - } + // Find all registrars that have a registrar contact with this user's ID. + ImmutableList> accessibleClientIds = + stream(ofy().load().type(RegistrarContact.class).filter("gaeUserId", user.getUserId())) + .map(RegistrarContact::getParent) + .collect(toImmutableList()); + // Filter out disabled registrars (note that pending registrars still allow console login). + ofy().load().keys(accessibleClientIds).values().stream() + .filter(registrar -> registrar.getState() != State.DISABLED) + .forEach(registrar -> builder.put(registrar.getClientId(), Role.OWNER)); + // Admins have ADMIN access to all registrars, and also OWNER access to the registry registrar + // and all non-REAL or non-live registrars. if (isAdmin) { - // Admins have ADMIN access to all registrars, and OWNER access to all non-REAL registrars ofy() .load() .type(Registrar.class) - .forEach(registrar -> { - if (registrar.getType() != Registrar.Type.REAL - || registrar.getState() == Registrar.State.PENDING) { - builder.put(registrar.getClientId(), Role.OWNER); - } - builder.put(registrar.getClientId(), Role.ADMIN); - }); + .forEach( + registrar -> { + if (registrar.getType() != Registrar.Type.REAL + || !registrar.isLive() + || registrar.getClientId().equals(registryAdminClientId)) { + builder.put(registrar.getClientId(), Role.OWNER); + } + builder.put(registrar.getClientId(), Role.ADMIN); + }); } return builder.build(); diff --git a/java/google/registry/request/auth/BUILD b/java/google/registry/request/auth/BUILD index ac1ff20de..f32f990fe 100644 --- a/java/google/registry/request/auth/BUILD +++ b/java/google/registry/request/auth/BUILD @@ -12,6 +12,7 @@ java_library( "//java/google/registry/groups", "//java/google/registry/model", "//java/google/registry/security", + "//third_party/objectify:objectify-v4_1", "@com_google_appengine_api_1_0_sdk", "@com_google_auto_value", "@com_google_code_findbugs_jsr305", diff --git a/java/google/registry/tools/ValidateLoginCredentialsCommand.java b/java/google/registry/tools/ValidateLoginCredentialsCommand.java index b4c771217..8e53a5fcc 100644 --- a/java/google/registry/tools/ValidateLoginCredentialsCommand.java +++ b/java/google/registry/tools/ValidateLoginCredentialsCommand.java @@ -80,6 +80,7 @@ final class ValidateLoginCredentialsCommand implements CommandWithRemoteApi { Registrar.loadByClientId(clientId), "Registrar %s not found", clientId); new TlsCredentials(true, clientCertificateHash, Optional.of(clientIpAddress)) .validate(registrar, password); - checkState(!registrar.getState().equals(Registrar.State.PENDING), "Account pending"); + checkState( + registrar.isLive(), "Registrar %s has non-live state: %s", clientId, registrar.getState()); } } diff --git a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java index 32df35918..74e7cc73f 100644 --- a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java @@ -1467,26 +1467,26 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase { doFailingTest("login_valid.xml", RegistrarAccountNotActiveException.class); } + @Test + public void testFailure_disabledRegistrar() { + persistResource(getRegistrarBuilder().setState(State.DISABLED).build()); + doFailingTest("login_valid.xml", RegistrarAccountNotActiveException.class); + } + @Test public void testFailure_incorrectPassword() { persistResource(getRegistrarBuilder().setPassword("diff password").build()); diff --git a/javatests/google/registry/model/testdata/schema.txt b/javatests/google/registry/model/testdata/schema.txt index fb6342cf4..bc48d9813 100644 --- a/javatests/google/registry/model/testdata/schema.txt +++ b/javatests/google/registry/model/testdata/schema.txt @@ -424,6 +424,7 @@ class google.registry.model.registrar.Registrar$BillingAccountEntry { } enum google.registry.model.registrar.Registrar$State { ACTIVE; + DISABLED; PENDING; SUSPENDED; } diff --git a/javatests/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java b/javatests/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java index 4912222fd..c3e4f64f3 100644 --- a/javatests/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java +++ b/javatests/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java @@ -35,6 +35,7 @@ import com.google.common.testing.TestLogHandler; import dagger.Lazy; import google.registry.groups.GroupsConnection; import google.registry.model.registrar.Registrar; +import google.registry.model.registrar.Registrar.State; import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException; import google.registry.testing.AppEngineRule; import google.registry.testing.InjectRule; @@ -252,6 +253,21 @@ public class AuthenticatedRegistrarAccessorTest { verify(lazyGroupsConnection).get(); } + @Test + public void testGetRegistrarForUser_registrarIsDisabled_isNotAdmin() { + persistResource( + Registrar.loadByClientId("TheRegistrar") + .get() + .asBuilder() + .setState(State.DISABLED) + .build()); + expectGetRegistrarFailure( + CLIENT_ID_WITH_CONTACT, + USER, + "user user@gmail.com doesn't have access to registrar TheRegistrar"); + verify(lazyGroupsConnection).get(); + } + /** Fail loading registrar if user doesn't have access to it, even if it's not REAL. */ @Test public void testGetRegistrarForUser_noAccess_isNotAdmin_notReal() { @@ -302,6 +318,21 @@ public class AuthenticatedRegistrarAccessorTest { verifyZeroInteractions(lazyGroupsConnection); } + @Test + public void testGetRegistrarForUser_registrarIsDisabled_isAdmin() throws Exception { + persistResource( + Registrar.loadByClientId("NewRegistrar") + .get() + .asBuilder() + .setState(State.DISABLED) + .build()); + expectGetRegistrarSuccess( + REAL_CLIENT_ID_WITHOUT_CONTACT, + GAE_ADMIN, + "admin admin@gmail.com has [OWNER, ADMIN] access to registrar NewRegistrar."); + verifyZeroInteractions(lazyGroupsConnection); + } + /** Succeed loading non-REAL registrar for admin. */ @Test public void testGetRegistrarForUser_notInContacts_isAdmin_notReal() throws Exception { diff --git a/javatests/google/registry/tools/ValidateLoginCredentialsCommandTest.java b/javatests/google/registry/tools/ValidateLoginCredentialsCommandTest.java index c715a051e..366c85f41 100644 --- a/javatests/google/registry/tools/ValidateLoginCredentialsCommandTest.java +++ b/javatests/google/registry/tools/ValidateLoginCredentialsCommandTest.java @@ -14,6 +14,7 @@ package google.registry.tools; +import static com.google.common.truth.Truth.assertThat; import static google.registry.model.registrar.Registrar.State.ACTIVE; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.loadRegistrar; @@ -26,6 +27,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import google.registry.flows.EppException; import google.registry.flows.TransportCredentials.BadRegistrarPasswordException; +import google.registry.model.registrar.Registrar; +import google.registry.model.registrar.Registrar.State; import google.registry.testing.CertificateSamples; import google.registry.util.CidrAddressBlock; import org.junit.Before; @@ -62,6 +65,28 @@ public class ValidateLoginCredentialsCommandTest "--ip_address=" + CLIENT_IP); } + @Test + public void testFailure_registrarIsDisabled() { + persistResource( + Registrar.loadByClientId("NewRegistrar") + .get() + .asBuilder() + .setState(State.DISABLED) + .build()); + IllegalStateException thrown = + assertThrows( + IllegalStateException.class, + () -> + runCommand( + "--client=NewRegistrar", + "--password=" + PASSWORD, + "--cert_hash=" + CERT_HASH, + "--ip_address=" + CLIENT_IP)); + assertThat(thrown) + .hasMessageThat() + .isEqualTo("Registrar NewRegistrar has non-live state: DISABLED"); + } + @Test public void testFailure_loginWithBadPassword() { EppException thrown = diff --git a/javatests/google/registry/ui/server/registrar/BUILD b/javatests/google/registry/ui/server/registrar/BUILD index abe4269cd..b8ac359a1 100644 --- a/javatests/google/registry/ui/server/registrar/BUILD +++ b/javatests/google/registry/ui/server/registrar/BUILD @@ -27,6 +27,7 @@ java_library( "//javatests/google/registry/testing", "//third_party/objectify:objectify-v4_1", "@com_google_appengine_api_1_0_sdk", + "@com_google_dagger", "@com_google_flogger", "@com_google_flogger_system_backend", "@com_google_guava", diff --git a/javatests/google/registry/ui/server/registrar/ConsoleUiActionTest.java b/javatests/google/registry/ui/server/registrar/ConsoleUiActionTest.java index 29a6c389e..c82a5153a 100644 --- a/javatests/google/registry/ui/server/registrar/ConsoleUiActionTest.java +++ b/javatests/google/registry/ui/server/registrar/ConsoleUiActionTest.java @@ -92,7 +92,7 @@ public class ConsoleUiActionTest { } @After - public void tearDown() throws Exception { + public void tearDown() { assertThat(RegistrarConsoleMetrics.consoleRequestMetric).hasNoOtherValues(); } diff --git a/javatests/google/registry/webdriver/RegistrarConsoleScreenshotTest.java b/javatests/google/registry/webdriver/RegistrarConsoleScreenshotTest.java index 3c0bb608b..8eb46bb93 100644 --- a/javatests/google/registry/webdriver/RegistrarConsoleScreenshotTest.java +++ b/javatests/google/registry/webdriver/RegistrarConsoleScreenshotTest.java @@ -23,6 +23,7 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME; import com.google.common.collect.ImmutableMap; import com.googlecode.objectify.ObjectifyFilter; import google.registry.model.ofy.OfyFilter; +import google.registry.model.registrar.Registrar.State; import google.registry.module.frontend.FrontendServlet; import google.registry.server.RegistryTestServer; import google.registry.testing.CertificateSamples; @@ -257,6 +258,17 @@ public class RegistrarConsoleScreenshotTest { driver.diffPage("edit"); } + @Test + public void index_registrarDisabled() throws Throwable { + server.runInAppEngineEnvironment( + () -> + persistResource( + loadRegistrar("TheRegistrar").asBuilder().setState(State.DISABLED).build())); + driver.get(server.getUrl("/registrar")); + driver.waitForElement(By.tagName("h1")); + driver.diffPage("view"); + } + @Test public void settingsWhois() throws Throwable { driver.get(server.getUrl("/registrar#whois-settings")); diff --git a/javatests/google/registry/webdriver/goldens/chrome-linux/RegistrarConsoleScreenshotTest_index_registrarDisabled_view.png b/javatests/google/registry/webdriver/goldens/chrome-linux/RegistrarConsoleScreenshotTest_index_registrarDisabled_view.png new file mode 100644 index 0000000000000000000000000000000000000000..cf40cb49c34cedec3fd2089dd705ac325639afd8 GIT binary patch literal 33082 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 literal 0 HcmV?d00001