diff --git a/core/src/main/java/google/registry/rdap/RdapModule.java b/core/src/main/java/google/registry/rdap/RdapModule.java index 9149d1e09..b54c9336f 100644 --- a/core/src/main/java/google/registry/rdap/RdapModule.java +++ b/core/src/main/java/google/registry/rdap/RdapModule.java @@ -108,7 +108,7 @@ public final class RdapModule { if (userAuthInfo.isUserAdmin()) { return RdapAuthorization.ADMINISTRATOR_AUTHORIZATION; } - ImmutableSet clientIds = registrarAccessor.getAllClientIdWithRoles().keySet(); + ImmutableSet clientIds = registrarAccessor.getAllRegistrarIdsWithRoles().keySet(); if (clientIds.isEmpty()) { logger.atWarning().log("Couldn't find registrar for User %s.", authResult.userIdForLogging()); return RdapAuthorization.PUBLIC_AUTHORIZATION; diff --git a/core/src/main/java/google/registry/request/auth/AuthResult.java b/core/src/main/java/google/registry/request/auth/AuthResult.java index c2e4bc585..41f94900a 100644 --- a/core/src/main/java/google/registry/request/auth/AuthResult.java +++ b/core/src/main/java/google/registry/request/auth/AuthResult.java @@ -42,7 +42,7 @@ public abstract class AuthResult { userAuthInfo -> String.format( "%s %s", - userAuthInfo.isUserAdmin() ? "admin" : "user", userAuthInfo.user().getEmail())) + userAuthInfo.isUserAdmin() ? "admin" : "user", userAuthInfo.getEmailAddress())) .orElse(""); } diff --git a/core/src/main/java/google/registry/request/auth/AuthenticatedRegistrarAccessor.java b/core/src/main/java/google/registry/request/auth/AuthenticatedRegistrarAccessor.java index 882204b26..60f982655 100644 --- a/core/src/main/java/google/registry/request/auth/AuthenticatedRegistrarAccessor.java +++ b/core/src/main/java/google/registry/request/auth/AuthenticatedRegistrarAccessor.java @@ -40,8 +40,8 @@ import javax.inject.Inject; *

A user has OWNER role on a Registrar if there exists a {@link RegistrarPoc} with that user's * gaeId and the registrar as a parent. * - *

An "admin" has in addition OWNER role on {@code #registryAdminClientId} and to all non-{@code - * REAL} registrars (see {@link Registrar#getType}). + *

An "admin" has in addition OWNER role on {@code #registryAdminRegistrarId} and to all + * non-{@code REAL} registrars (see {@link Registrar#getType}). * *

An "admin" also has ADMIN role on ALL registrars. * @@ -76,7 +76,7 @@ public class AuthenticatedRegistrarAccessor { private final boolean isAdmin; /** - * Gives all roles a user has for a given clientId. + * Gives all roles a user has for a given registrar ID. * *

The order is significant, with "more specific to this user" coming first. * @@ -107,13 +107,13 @@ public class AuthenticatedRegistrarAccessor { @Inject public AuthenticatedRegistrarAccessor( AuthResult authResult, - @Config("registryAdminClientId") String registryAdminClientId, + @Config("registryAdminClientId") String registryAdminRegistrarId, @Config("gSuiteSupportGroupEmailAddress") Optional gSuiteSupportGroupEmailAddress, Lazy lazyGroupsConnection) { this.isAdmin = userIsAdmin(authResult, gSuiteSupportGroupEmailAddress, lazyGroupsConnection); this.userIdForLogging = authResult.userIdForLogging(); - this.roleMap = createRoleMap(authResult, this.isAdmin, registryAdminClientId); + this.roleMap = createRoleMap(authResult, this.isAdmin, registryAdminRegistrarId); logger.atInfo().log("%s has the following roles: %s", userIdForLogging(), roleMap); } @@ -129,7 +129,7 @@ public class AuthenticatedRegistrarAccessor { * Creates a "logged-in user" accessor with a given role map, used for tests. * *

The user will be allowed to create Registrars (and hence do OT&E setup) iff they have - * the role of ADMIN for at least one clientId. + * the role of ADMIN for at least one registrar ID. * *

The user's "name" in logs and exception messages is "TestUserId". */ @@ -148,59 +148,62 @@ public class AuthenticatedRegistrarAccessor { } /** - * A map that gives all roles a user has for a given clientId. + * A map that gives all roles a user has for a given registrar ID. * *

Throws a {@link RegistrarAccessDeniedException} if the user is not logged in. * *

The result is ordered starting from "most specific to this user". * - *

If you want to load the {@link Registrar} object from these (or any other) {@code clientId}, - * in order to perform actions on behalf of a user, you must use {@link #getRegistrar} which makes - * sure the user has permissions. + *

If you want to load the {@link Registrar} object from these (or any other) {@code + * registrarId}, in order to perform actions on behalf of a user, you must use {@link + * #getRegistrar} which makes sure the user has permissions. * *

Note that this is an OPTIONAL step in the authentication - only used if we don't have any - * other clue as to the requested {@code clientId}. It is perfectly OK to get a {@code clientId} - * from any other source, as long as the registrar is then loaded using {@link #getRegistrar}. + * other clue as to the requested {@code registrarId}. It is perfectly OK to get a {@code + * registrarId} from any other source, as long as the registrar is then loaded using {@link + * #getRegistrar}. */ - public ImmutableSetMultimap getAllClientIdWithRoles() { + public ImmutableSetMultimap getAllRegistrarIdsWithRoles() { return roleMap; } /** * Returns all the roles the current user has on the given registrar. * - *

This is syntactic sugar for {@code getAllClientIdWithRoles().get(clientId)}. + *

This is syntactic sugar for {@code getAllRegistrarIdsWithRoles().get(registrarId)}. */ - public ImmutableSet getRolesForRegistrar(String clientId) { - return getAllClientIdWithRoles().get(clientId); + public ImmutableSet getRolesForRegistrar(String registrarId) { + return getAllRegistrarIdsWithRoles().get(registrarId); } /** * Checks if we have a given role for a given registrar. * - *

This is syntactic sugar for {@code getAllClientIdWithRoles().containsEntry(clientId, role)}. + *

This is syntactic sugar for {@code getAllRegistrarIdsWithRoles().containsEntry(registrarId, + * role)}. */ - public boolean hasRoleOnRegistrar(Role role, String clientId) { - return getAllClientIdWithRoles().containsEntry(clientId, role); + public boolean hasRoleOnRegistrar(Role role, String registrarId) { + return getAllRegistrarIdsWithRoles().containsEntry(registrarId, role); } /** * "Guesses" which client ID the user wants from all those they have access to. * - *

If no such ClientIds exist, throws a RegistrarAccessDeniedException. + *

If no such registrar IDs exist, throws a RegistrarAccessDeniedException. * - *

This should be the ClientId "most likely wanted by the user". + *

This should be the registrar ID "most likely wanted by the user". * - *

If you want to load the {@link Registrar} object from this (or any other) {@code clientId}, - * in order to perform actions on behalf of a user, you must use {@link #getRegistrar} which makes - * sure the user has permissions. + *

If you want to load the {@link Registrar} object from this (or any other) {@code + * registrarId}, in order to perform actions on behalf of a user, you must use {@link + * #getRegistrar} which makes sure the user has permissions. * *

Note that this is an OPTIONAL step in the authentication - only used if we don't have any - * other clue as to the requested {@code clientId}. It is perfectly OK to get a {@code clientId} - * from any other source, as long as the registrar is then loaded using {@link #getRegistrar}. + * other clue as to the requested {@code registrarId}. It is perfectly OK to get a {@code + * registrarId} from any other source, as long as the registrar is then loaded using {@link + * #getRegistrar}. */ - public String guessClientId() throws RegistrarAccessDeniedException { - return getAllClientIdWithRoles().keySet().stream() + public String guessRegistrarId() throws RegistrarAccessDeniedException { + return getAllRegistrarIdsWithRoles().keySet().stream() .findFirst() .orElseThrow( () -> @@ -227,7 +230,7 @@ public class AuthenticatedRegistrarAccessor { if (!registrarId.equals(registrar.getRegistrarId())) { logger.atSevere().log( - "registrarLoader.apply(clientId) returned a Registrar with a different clientId. " + "registrarLoader.apply(registrarId) returned a Registrar with a different registrarId. " + "Requested: %s, returned: %s.", registrarId, registrar.getRegistrarId()); throw new RegistrarAccessDeniedException("Internal error - please check logs"); @@ -237,7 +240,7 @@ public class AuthenticatedRegistrarAccessor { } public void verifyAccess(String registrarId) throws RegistrarAccessDeniedException { - ImmutableSet roles = getAllClientIdWithRoles().get(registrarId); + ImmutableSet roles = getAllRegistrarIdsWithRoles().get(registrarId); if (roles.isEmpty()) { throw new RegistrarAccessDeniedException( @@ -279,53 +282,55 @@ public class AuthenticatedRegistrarAccessor { AuthResult authResult, Optional gSuiteSupportGroupEmailAddress, Lazy lazyGroupsConnection) { - if (!authResult.userAuthInfo().isPresent()) { return false; } UserAuthInfo userAuthInfo = authResult.userAuthInfo().get(); - - User user = userAuthInfo.user(); - // both GAE project admin and members of the gSuiteSupportGroupEmailAddress are considered // admins for the RegistrarConsole. return !bypassAdminCheck && (userAuthInfo.isUserAdmin() || checkIsSupport( - lazyGroupsConnection, user.getEmail(), gSuiteSupportGroupEmailAddress)); + lazyGroupsConnection, + userAuthInfo.getEmailAddress(), + gSuiteSupportGroupEmailAddress)); } - /** - * Returns a map of registrar client IDs to roles for all registrars that the user has access to. - */ + /** Returns a map of registrar IDs to roles for all registrars that the user has access to. */ private static ImmutableSetMultimap createRoleMap( - AuthResult authResult, - boolean isAdmin, - String registryAdminClientId) { - + AuthResult authResult, boolean isAdmin, String registryAdminRegistrarId) { 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()); + UserAuthInfo userAuthInfo = authResult.userAuthInfo().get(); + if (userAuthInfo.appEngineUser().isPresent()) { + User user = userAuthInfo.appEngineUser().get(); + logger.atInfo().log("Checking registrar contacts for user ID %s.", user.getUserId()); - // Find all registrars that have a registrar contact with this user's ID. - jpaTm() - .transact( - () -> - jpaTm() - .query( - "SELECT r FROM Registrar r INNER JOIN RegistrarPoc rp ON " - + "r.clientIdentifier = rp.registrarId WHERE rp.gaeUserId = " - + ":gaeUserId AND r.state != :state", - Registrar.class) - .setParameter("gaeUserId", user.getUserId()) - .setParameter("state", State.DISABLED) - .getResultStream() - .forEach(registrar -> builder.put(registrar.getRegistrarId(), Role.OWNER))); + // Find all registrars that have a registrar contact with this user's ID. + jpaTm() + .transact( + () -> + jpaTm() + .query( + "SELECT r FROM Registrar r INNER JOIN RegistrarPoc rp ON " + + "r.clientIdentifier = rp.registrarId WHERE rp.gaeUserId = " + + ":gaeUserId AND r.state != :state", + Registrar.class) + .setParameter("gaeUserId", user.getUserId()) + .setParameter("state", State.DISABLED) + .getResultStream() + .forEach(registrar -> builder.put(registrar.getRegistrarId(), Role.OWNER))); + } else { + userAuthInfo + .consoleUser() + .get() + .getUserRoles() + .getRegistrarRoles() + .forEach((k, v) -> builder.put(k, 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. @@ -337,7 +342,7 @@ public class AuthenticatedRegistrarAccessor { registrar -> { if (registrar.getType() != Registrar.Type.REAL || !registrar.isLive() - || registrar.getRegistrarId().equals(registryAdminClientId)) { + || registrar.getRegistrarId().equals(registryAdminRegistrarId)) { builder.put(registrar.getRegistrarId(), Role.OWNER); } builder.put(registrar.getRegistrarId(), Role.ADMIN); diff --git a/core/src/main/java/google/registry/request/auth/UserAuthInfo.java b/core/src/main/java/google/registry/request/auth/UserAuthInfo.java index e5383b23f..54d1fb98c 100644 --- a/core/src/main/java/google/registry/request/auth/UserAuthInfo.java +++ b/core/src/main/java/google/registry/request/auth/UserAuthInfo.java @@ -23,7 +23,7 @@ import java.util.Optional; public abstract class UserAuthInfo { /** User object from the AppEngine Users API. */ - public abstract User user(); + public abstract Optional appEngineUser(); /** * Whether the user is an admin. @@ -34,16 +34,37 @@ public abstract class UserAuthInfo { */ public abstract boolean isUserAdmin(); + public abstract Optional consoleUser(); + /** Used by the OAuth authentication mechanism (only) to return information about the session. */ public abstract Optional oauthTokenInfo(); + public String getEmailAddress() { + return appEngineUser() + .map(User::getEmail) + .orElseGet(() -> consoleUser().get().getEmailAddress()); + } + + public String getUsername() { + return appEngineUser() + .map(User::getNickname) + .orElseGet(() -> consoleUser().get().getEmailAddress()); + } + public static UserAuthInfo create( User user, boolean isUserAdmin) { - return new AutoValue_UserAuthInfo(user, isUserAdmin, Optional.empty()); + return new AutoValue_UserAuthInfo( + Optional.of(user), isUserAdmin, Optional.empty(), Optional.empty()); } public static UserAuthInfo create( User user, boolean isUserAdmin, OAuthTokenInfo oauthTokenInfo) { - return new AutoValue_UserAuthInfo(user, isUserAdmin, Optional.of(oauthTokenInfo)); + return new AutoValue_UserAuthInfo( + Optional.of(user), isUserAdmin, Optional.empty(), Optional.of(oauthTokenInfo)); + } + + public static UserAuthInfo create(google.registry.model.console.User user) { + return new AutoValue_UserAuthInfo( + Optional.empty(), user.getUserRoles().isAdmin(), Optional.of(user), Optional.empty()); } } diff --git a/core/src/main/java/google/registry/ui/server/registrar/ConsoleUiAction.java b/core/src/main/java/google/registry/ui/server/registrar/ConsoleUiAction.java index e27c5bc02..859271609 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/ConsoleUiAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/ConsoleUiAction.java @@ -109,13 +109,13 @@ public final class ConsoleUiAction extends HtmlAction { .render()); return; } - ImmutableSetMultimap roleMap = registrarAccessor.getAllClientIdWithRoles(); + ImmutableSetMultimap roleMap = registrarAccessor.getAllRegistrarIdsWithRoles(); soyMapData.put("allClientIds", roleMap.keySet()); soyMapData.put("environment", RegistryEnvironment.get().toString()); // We set the initial value to the value that will show if guessClientId throws. String clientId = ""; try { - clientId = paramClientId.orElse(registrarAccessor.guessClientId()); + clientId = paramClientId.orElse(registrarAccessor.guessRegistrarId()); soyMapData.put("clientId", clientId); soyMapData.put("isOwner", roleMap.containsEntry(clientId, OWNER)); soyMapData.put("isAdmin", roleMap.containsEntry(clientId, ADMIN)); diff --git a/core/src/main/java/google/registry/ui/server/registrar/HtmlAction.java b/core/src/main/java/google/registry/ui/server/registrar/HtmlAction.java index d684647fd..e878be9ef 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/HtmlAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/HtmlAction.java @@ -18,7 +18,6 @@ import static com.google.common.net.HttpHeaders.LOCATION; import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS; import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY; -import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.common.flogger.FluentLogger; import com.google.common.net.MediaType; @@ -27,6 +26,7 @@ import google.registry.request.Action; import google.registry.request.RequestMethod; import google.registry.request.Response; import google.registry.request.auth.AuthResult; +import google.registry.request.auth.UserAuthInfo; import google.registry.security.XsrfTokenManager; import java.util.HashMap; import java.util.Map; @@ -86,16 +86,15 @@ public abstract class HtmlAction implements Runnable { } response.setContentType(MediaType.HTML_UTF_8); - User user = authResult.userAuthInfo().get().user(); - + UserAuthInfo authInfo = authResult.userAuthInfo().get(); // Using HashMap to allow null values HashMap data = new HashMap<>(); data.put("logoFilename", logoFilename); data.put("productName", productName); - data.put("username", user.getNickname()); + data.put("username", authInfo.getUsername()); data.put("logoutUrl", userService.createLogoutURL(getPath())); data.put("analyticsConfig", analyticsConfig); - data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail())); + data.put("xsrfToken", xsrfTokenManager.generateToken(authInfo.getEmailAddress())); logger.atInfo().log( "User %s is accessing %s with method %s.", diff --git a/core/src/main/java/google/registry/ui/server/registrar/RegistryLockGetAction.java b/core/src/main/java/google/registry/ui/server/registrar/RegistryLockGetAction.java index 09f7c3154..fb440496c 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/RegistryLockGetAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/RegistryLockGetAction.java @@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.flogger.FluentLogger; import com.google.common.net.MediaType; import com.google.gson.Gson; +import google.registry.model.console.ConsolePermission; import google.registry.model.domain.RegistryLock; import google.registry.model.registrar.Registrar; import google.registry.model.registrar.RegistrarPoc; @@ -42,6 +43,7 @@ import google.registry.request.auth.Auth; import google.registry.request.auth.AuthResult; import google.registry.request.auth.AuthenticatedRegistrarAccessor; import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException; +import google.registry.request.auth.UserAuthInfo; import google.registry.security.JsonResponseHelper; import java.util.Objects; import java.util.Optional; @@ -153,24 +155,35 @@ public final class RegistryLockGetAction implements JsonGetAction { boolean isAdmin = registrarAccessor.isAdmin(); Registrar registrar = getRegistrarAndVerifyLockAccess(registrarAccessor, registrarId, isAdmin); - User user = authResult.userAuthInfo().get().user(); - Optional contactOptional = getContactMatchingLogin(user, registrar); - boolean isRegistryLockAllowed = - isAdmin || contactOptional.map(RegistrarPoc::isRegistryLockAllowed).orElse(false); + UserAuthInfo userAuthInfo = authResult.userAuthInfo().get(); + // Split logic depending on whether we are using the old auth system or the new one + boolean isRegistryLockAllowed; + String relevantEmail; + if (userAuthInfo.appEngineUser().isPresent()) { + User user = userAuthInfo.appEngineUser().get(); + Optional contactOptional = getContactMatchingLogin(user, registrar); + isRegistryLockAllowed = + isAdmin || contactOptional.map(RegistrarPoc::isRegistryLockAllowed).orElse(false); + relevantEmail = + isAdmin + ? user.getEmail() + // if the contact isn't present, we shouldn't display the email anyway + : contactOptional.flatMap(RegistrarPoc::getRegistryLockEmailAddress).orElse(""); + } else { + google.registry.model.console.User user = userAuthInfo.consoleUser().get(); + isRegistryLockAllowed = + user.getUserRoles().hasPermission(registrarId, ConsolePermission.REGISTRY_LOCK); + relevantEmail = user.getEmailAddress(); + } // Use the contact's registry lock email if it's present, else use the login email (for admins) - String relevantEmail = - isAdmin - ? user.getEmail() - // if the contact isn't present, we shouldn't display the email anyway so empty is fine - : contactOptional.flatMap(RegistrarPoc::getRegistryLockEmailAddress).orElse(""); return ImmutableMap.of( LOCK_ENABLED_FOR_CONTACT_PARAM, isRegistryLockAllowed, EMAIL_PARAM, relevantEmail, PARAM_CLIENT_ID, - registrar.getRegistrarId(), + registrarId, LOCKS_PARAM, getLockedDomains(registrarId, isAdmin)); } diff --git a/core/src/main/java/google/registry/ui/server/registrar/RegistryLockPostAction.java b/core/src/main/java/google/registry/ui/server/registrar/RegistryLockPostAction.java index 144340938..84e35c1fb 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/RegistryLockPostAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/RegistryLockPostAction.java @@ -184,10 +184,29 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc private String verifyPasswordAndGetEmail( UserAuthInfo userAuthInfo, RegistryLockPostInput postInput) throws RegistrarAccessDeniedException { - User user = userAuthInfo.user(); if (registrarAccessor.isAdmin()) { - return user.getEmail(); + return userAuthInfo.getEmailAddress(); } + if (userAuthInfo.appEngineUser().isPresent()) { + return verifyPasswordAndGetEmailLegacyUser(userAuthInfo.appEngineUser().get(), postInput); + } else { + return verifyPasswordAndGetEmailConsoleUser(userAuthInfo.consoleUser().get(), postInput); + } + } + + private String verifyPasswordAndGetEmailConsoleUser( + google.registry.model.console.User user, RegistryLockPostInput postInput) + throws RegistrarAccessDeniedException { + // Verify that the registrar has locking enabled + getRegistrarAndVerifyLockAccess(registrarAccessor, postInput.registrarId, false); + checkArgument( + user.verifyRegistryLockPassword(postInput.password), + "Incorrect registry lock password for user"); + return user.getEmailAddress(); + } + + private String verifyPasswordAndGetEmailLegacyUser(User user, RegistryLockPostInput postInput) + throws RegistrarAccessDeniedException { // Verify that the user can access the registrar, that the user has // registry lock enabled, and that the user provided a correct password Registrar registrar = diff --git a/core/src/test/java/google/registry/request/RequestHandlerTest.java b/core/src/test/java/google/registry/request/RequestHandlerTest.java index b1f884aef..cf29e3199 100644 --- a/core/src/test/java/google/registry/request/RequestHandlerTest.java +++ b/core/src/test/java/google/registry/request/RequestHandlerTest.java @@ -474,7 +474,7 @@ public final class RequestHandlerTest { assertThat(providedAuthResult).isNotNull(); assertThat(providedAuthResult.authLevel()).isEqualTo(AuthLevel.USER); assertThat(providedAuthResult.userAuthInfo()).isPresent(); - assertThat(providedAuthResult.userAuthInfo().get().user()).isEqualTo(testUser); + assertThat(providedAuthResult.userAuthInfo().get().appEngineUser()).hasValue(testUser); assertThat(providedAuthResult.userAuthInfo().get().oauthTokenInfo()).isEmpty(); assertMetric("/auth/adminUser", GET, AuthLevel.USER, true); } diff --git a/core/src/test/java/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java b/core/src/test/java/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java index a0f794ddc..813bb3f90 100644 --- a/core/src/test/java/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java +++ b/core/src/test/java/google/registry/request/auth/AuthenticatedRegistrarAccessorTest.java @@ -28,11 +28,15 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import com.google.appengine.api.users.User; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.testing.NullPointerTester; import com.google.common.testing.TestLogHandler; import dagger.Lazy; import google.registry.groups.GroupsConnection; +import google.registry.model.console.GlobalRole; +import google.registry.model.console.RegistrarRole; +import google.registry.model.console.UserRoles; import google.registry.model.registrar.Registrar; import google.registry.model.registrar.Registrar.State; import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException; @@ -71,14 +75,14 @@ class AuthenticatedRegistrarAccessorTest { private static final AuthResult GAE_ADMIN = createAuthResult(true); private static final AuthResult NO_USER = AuthResult.create(AuthLevel.NONE); private static final Optional SUPPORT_GROUP = Optional.of("support@registry.example"); - /** Client ID of a REAL registrar with a RegistrarContact for USER and GAE_ADMIN. */ - private static final String CLIENT_ID_WITH_CONTACT = "TheRegistrar"; - /** Client ID of a REAL registrar without a RegistrarContact. */ - private static final String REAL_CLIENT_ID_WITHOUT_CONTACT = "NewRegistrar"; - /** Client ID of an OTE registrar without a RegistrarContact. */ - private static final String OTE_CLIENT_ID_WITHOUT_CONTACT = "OteRegistrar"; - /** Client ID of the Admin registrar without a RegistrarContact. */ - private static final String ADMIN_CLIENT_ID = "AdminRegistrar"; + /** Registrar ID of a REAL registrar with a RegistrarContact for USER and GAE_ADMIN. */ + private static final String REGISTRAR_ID_WITH_CONTACT = "TheRegistrar"; + /** Registrar ID of a REAL registrar without a RegistrarContact. */ + private static final String REAL_REGISTRAR_ID_WITHOUT_CONTACT = "NewRegistrar"; + /** Registrar ID of an OTE registrar without a RegistrarContact. */ + private static final String OTE_REGISTRAR_ID_WITHOUT_CONTACT = "OteRegistrar"; + /** Registrar ID of the Admin registrar without a RegistrarContact. */ + private static final String ADMIN_REGISTRAR_ID = "AdminRegistrar"; /** * Creates an AuthResult for a fake user. @@ -104,18 +108,17 @@ class AuthenticatedRegistrarAccessorTest { void beforeEach() { when(lazyGroupsConnection.get()).thenReturn(groupsConnection); JdkLoggerConfig.getConfig(AuthenticatedRegistrarAccessor.class).addHandler(testLogHandler); - // persistResource(loadRegistrar(ADMIN_CLIENT_ID)); persistResource( - loadRegistrar(REAL_CLIENT_ID_WITHOUT_CONTACT) + loadRegistrar(REAL_REGISTRAR_ID_WITHOUT_CONTACT) .asBuilder() - .setRegistrarId(OTE_CLIENT_ID_WITHOUT_CONTACT) + .setRegistrarId(OTE_REGISTRAR_ID_WITHOUT_CONTACT) .setType(Registrar.Type.OTE) .setIanaIdentifier(null) .build()); persistResource( - loadRegistrar(REAL_CLIENT_ID_WITHOUT_CONTACT) + loadRegistrar(REAL_REGISTRAR_ID_WITHOUT_CONTACT) .asBuilder() - .setRegistrarId(ADMIN_CLIENT_ID) + .setRegistrarId(ADMIN_REGISTRAR_ID) .setType(Registrar.Type.OTE) .setIanaIdentifier(null) .build()); @@ -129,24 +132,24 @@ class AuthenticatedRegistrarAccessorTest { /** Users are owners for registrars if and only if they are in the contacts for that registrar. */ @Test - void getAllClientIdWithAccess_user() { + void getAllRegistrarIdWithAccess_user() { AuthenticatedRegistrarAccessor registrarAccessor = new AuthenticatedRegistrarAccessor( - USER, ADMIN_CLIENT_ID, SUPPORT_GROUP, lazyGroupsConnection); + USER, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); - assertThat(registrarAccessor.getAllClientIdWithRoles()) - .containsExactly(CLIENT_ID_WITH_CONTACT, OWNER); + assertThat(registrarAccessor.getAllRegistrarIdsWithRoles()) + .containsExactly(REGISTRAR_ID_WITH_CONTACT, OWNER); verify(lazyGroupsConnection).get(); } /** Logged-out users don't have access to anything. */ @Test - void getAllClientIdWithAccess_loggedOutUser() { + void getAllRegistrarIdWithAccess_loggedOutUser() { AuthenticatedRegistrarAccessor registrarAccessor = new AuthenticatedRegistrarAccessor( - NO_USER, ADMIN_CLIENT_ID, SUPPORT_GROUP, lazyGroupsConnection); + NO_USER, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); - assertThat(registrarAccessor.getAllClientIdWithRoles()).isEmpty(); + assertThat(registrarAccessor.getAllRegistrarIdsWithRoles()).isEmpty(); verifyNoInteractions(lazyGroupsConnection); } @@ -162,23 +165,20 @@ class AuthenticatedRegistrarAccessorTest { *

(in other words - they don't have OWNER access only to REAL registrars owned by others) */ @Test - void getAllClientIdWithAccess_gaeAdmin() { + void getAllRegistrarIdWithAccess_gaeAdmin() { AuthenticatedRegistrarAccessor registrarAccessor = new AuthenticatedRegistrarAccessor( - GAE_ADMIN, ADMIN_CLIENT_ID, SUPPORT_GROUP, lazyGroupsConnection); + GAE_ADMIN, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); - assertThat(registrarAccessor.getAllClientIdWithRoles()) + assertThat(registrarAccessor.getAllRegistrarIdsWithRoles()) .containsExactly( - CLIENT_ID_WITH_CONTACT, ADMIN, - CLIENT_ID_WITH_CONTACT, OWNER, - - REAL_CLIENT_ID_WITHOUT_CONTACT, ADMIN, - - OTE_CLIENT_ID_WITHOUT_CONTACT, ADMIN, - OTE_CLIENT_ID_WITHOUT_CONTACT, OWNER, - - ADMIN_CLIENT_ID, ADMIN, - ADMIN_CLIENT_ID, OWNER); + REGISTRAR_ID_WITH_CONTACT, ADMIN, + REGISTRAR_ID_WITH_CONTACT, OWNER, + REAL_REGISTRAR_ID_WITHOUT_CONTACT, ADMIN, + OTE_REGISTRAR_ID_WITHOUT_CONTACT, ADMIN, + OTE_REGISTRAR_ID_WITHOUT_CONTACT, OWNER, + ADMIN_REGISTRAR_ID, ADMIN, + ADMIN_REGISTRAR_ID, OWNER); verifyNoInteractions(lazyGroupsConnection); } @@ -194,51 +194,48 @@ class AuthenticatedRegistrarAccessorTest { *

(in other words - they don't have OWNER access only to REAL registrars owned by others) */ @Test - void getAllClientIdWithAccess_userInSupportGroup() { + void getAllRegistrarIdWithAccess_userInSupportGroup() { when(groupsConnection.isMemberOfGroup("user@gmail.com", SUPPORT_GROUP.get())).thenReturn(true); AuthenticatedRegistrarAccessor registrarAccessor = new AuthenticatedRegistrarAccessor( - USER, ADMIN_CLIENT_ID, SUPPORT_GROUP, lazyGroupsConnection); + USER, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); - assertThat(registrarAccessor.getAllClientIdWithRoles()) + assertThat(registrarAccessor.getAllRegistrarIdsWithRoles()) .containsExactly( - CLIENT_ID_WITH_CONTACT, ADMIN, - CLIENT_ID_WITH_CONTACT, OWNER, - - REAL_CLIENT_ID_WITHOUT_CONTACT, ADMIN, - - OTE_CLIENT_ID_WITHOUT_CONTACT, ADMIN, - OTE_CLIENT_ID_WITHOUT_CONTACT, OWNER, - - ADMIN_CLIENT_ID, ADMIN, - ADMIN_CLIENT_ID, OWNER); + REGISTRAR_ID_WITH_CONTACT, ADMIN, + REGISTRAR_ID_WITH_CONTACT, OWNER, + REAL_REGISTRAR_ID_WITHOUT_CONTACT, ADMIN, + OTE_REGISTRAR_ID_WITHOUT_CONTACT, ADMIN, + OTE_REGISTRAR_ID_WITHOUT_CONTACT, OWNER, + ADMIN_REGISTRAR_ID, ADMIN, + ADMIN_REGISTRAR_ID, OWNER); verify(lazyGroupsConnection).get(); } /** Empty Support group email - skips check and doesn't generate the lazy. */ @Test - void getAllClientIdWithAccess_emptySupportEmail_works() { + void getAllRegistrarIdWithAccess_emptySupportEmail_works() { AuthenticatedRegistrarAccessor registrarAccessor = new AuthenticatedRegistrarAccessor( - USER, ADMIN_CLIENT_ID, Optional.empty(), lazyGroupsConnection); + USER, ADMIN_REGISTRAR_ID, Optional.empty(), lazyGroupsConnection); - assertThat(registrarAccessor.getAllClientIdWithRoles()) - .containsExactly(CLIENT_ID_WITH_CONTACT, OWNER); + assertThat(registrarAccessor.getAllRegistrarIdsWithRoles()) + .containsExactly(REGISTRAR_ID_WITH_CONTACT, OWNER); // Make sure we didn't instantiate the lazyGroupsConnection verifyNoInteractions(lazyGroupsConnection); } /** Support group check throws - continue anyway. */ @Test - void getAllClientIdWithAccess_throwingGroupCheck_stillWorks() { + void getAllRegistrarIdWithAccess_throwingGroupCheck_stillWorks() { when(groupsConnection.isMemberOfGroup(any(), any())).thenThrow(new RuntimeException("blah")); AuthenticatedRegistrarAccessor registrarAccessor = new AuthenticatedRegistrarAccessor( - USER, ADMIN_CLIENT_ID, SUPPORT_GROUP, lazyGroupsConnection); + USER, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); verify(groupsConnection).isMemberOfGroup("user@gmail.com", SUPPORT_GROUP.get()); - assertThat(registrarAccessor.getAllClientIdWithRoles()) - .containsExactly(CLIENT_ID_WITH_CONTACT, OWNER); + assertThat(registrarAccessor.getAllRegistrarIdsWithRoles()) + .containsExactly(REGISTRAR_ID_WITH_CONTACT, OWNER); verify(lazyGroupsConnection).get(); } @@ -246,7 +243,7 @@ class AuthenticatedRegistrarAccessorTest { @Test void testGetRegistrarForUser_noAccess_isNotAdmin() { expectGetRegistrarFailure( - REAL_CLIENT_ID_WITHOUT_CONTACT, + REAL_REGISTRAR_ID_WITHOUT_CONTACT, USER, "user user@gmail.com doesn't have access to registrar NewRegistrar"); verify(lazyGroupsConnection).get(); @@ -261,7 +258,7 @@ class AuthenticatedRegistrarAccessorTest { .setState(State.DISABLED) .build()); expectGetRegistrarFailure( - CLIENT_ID_WITH_CONTACT, + REGISTRAR_ID_WITH_CONTACT, USER, "user user@gmail.com doesn't have access to registrar TheRegistrar"); verify(lazyGroupsConnection).get(); @@ -271,7 +268,7 @@ class AuthenticatedRegistrarAccessorTest { @Test void testGetRegistrarForUser_noAccess_isNotAdmin_notReal() { expectGetRegistrarFailure( - OTE_CLIENT_ID_WITHOUT_CONTACT, + OTE_REGISTRAR_ID_WITHOUT_CONTACT, USER, "user user@gmail.com doesn't have access to registrar OteRegistrar"); verify(lazyGroupsConnection).get(); @@ -281,7 +278,7 @@ class AuthenticatedRegistrarAccessorTest { @Test void testGetRegistrarForUser_noUser() { expectGetRegistrarFailure( - CLIENT_ID_WITH_CONTACT, + REGISTRAR_ID_WITH_CONTACT, NO_USER, " doesn't have access to registrar TheRegistrar"); verifyNoInteractions(lazyGroupsConnection); @@ -291,7 +288,7 @@ class AuthenticatedRegistrarAccessorTest { @Test void testGetRegistrarForUser_inContacts_isNotAdmin() throws Exception { expectGetRegistrarSuccess( - CLIENT_ID_WITH_CONTACT, + REGISTRAR_ID_WITH_CONTACT, USER, "user user@gmail.com has [OWNER] access to registrar TheRegistrar"); verify(lazyGroupsConnection).get(); @@ -301,7 +298,7 @@ class AuthenticatedRegistrarAccessorTest { @Test void testGetRegistrarForUser_inContacts_isAdmin() throws Exception { expectGetRegistrarSuccess( - CLIENT_ID_WITH_CONTACT, + REGISTRAR_ID_WITH_CONTACT, GAE_ADMIN, "admin admin@gmail.com has [OWNER, ADMIN] access to registrar TheRegistrar"); verifyNoInteractions(lazyGroupsConnection); @@ -311,7 +308,7 @@ class AuthenticatedRegistrarAccessorTest { @Test void testGetRegistrarForUser_notInContacts_isAdmin() throws Exception { expectGetRegistrarSuccess( - REAL_CLIENT_ID_WITHOUT_CONTACT, + REAL_REGISTRAR_ID_WITHOUT_CONTACT, GAE_ADMIN, "admin admin@gmail.com has [ADMIN] access to registrar NewRegistrar."); verifyNoInteractions(lazyGroupsConnection); @@ -326,7 +323,7 @@ class AuthenticatedRegistrarAccessorTest { .setState(State.DISABLED) .build()); expectGetRegistrarSuccess( - REAL_CLIENT_ID_WITHOUT_CONTACT, + REAL_REGISTRAR_ID_WITHOUT_CONTACT, GAE_ADMIN, "admin admin@gmail.com has [OWNER, ADMIN] access to registrar NewRegistrar."); verifyNoInteractions(lazyGroupsConnection); @@ -336,7 +333,7 @@ class AuthenticatedRegistrarAccessorTest { @Test void testGetRegistrarForUser_notInContacts_isAdmin_notReal() throws Exception { expectGetRegistrarSuccess( - OTE_CLIENT_ID_WITHOUT_CONTACT, + OTE_REGISTRAR_ID_WITHOUT_CONTACT, GAE_ADMIN, "admin admin@gmail.com has [OWNER, ADMIN] access to registrar OteRegistrar."); verifyNoInteractions(lazyGroupsConnection); @@ -346,9 +343,7 @@ class AuthenticatedRegistrarAccessorTest { @Test void testGetRegistrarForUser_doesntExist_isAdmin() { expectGetRegistrarFailure( - "BadClientId", - GAE_ADMIN, - "Registrar BadClientId does not exist"); + "BadRegistrarId", GAE_ADMIN, "Registrar BadRegistrarId does not exist"); verifyNoInteractions(lazyGroupsConnection); } @@ -356,7 +351,7 @@ class AuthenticatedRegistrarAccessorTest { throws Exception { AuthenticatedRegistrarAccessor registrarAccessor = new AuthenticatedRegistrarAccessor( - authResult, ADMIN_CLIENT_ID, SUPPORT_GROUP, lazyGroupsConnection); + authResult, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); // make sure loading the registrar succeeds and returns a value assertThat(registrarAccessor.getRegistrar(registrarId)).isNotNull(); @@ -367,7 +362,7 @@ class AuthenticatedRegistrarAccessorTest { String registrarId, AuthResult authResult, String message) { AuthenticatedRegistrarAccessor registrarAccessor = new AuthenticatedRegistrarAccessor( - authResult, ADMIN_CLIENT_ID, SUPPORT_GROUP, lazyGroupsConnection); + authResult, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); // make sure getRegistrar fails RegistrarAccessDeniedException exception = @@ -378,27 +373,27 @@ class AuthenticatedRegistrarAccessorTest { assertThat(exception).hasMessageThat().contains(message); } - /** guessClientIdForUser returns the first clientId in getAllClientIdWithRoles. */ + /** guessRegistrarIdForUser returns the first registrarId in getAllRegistrarIdWithRoles. */ @Test - void testGuessClientIdForUser_hasAccess_returnsFirst() throws Exception { + void testGuessRegistrarIdForUser_hasAccess_returnsFirst() throws Exception { AuthenticatedRegistrarAccessor registrarAccessor = AuthenticatedRegistrarAccessor.createForTesting( ImmutableSetMultimap.of( - "clientId-1", OWNER, - "clientId-2", OWNER, - "clientId-2", ADMIN)); + "registrarId-1", OWNER, + "registrarId-2", OWNER, + "registrarId-2", ADMIN)); - assertThat(registrarAccessor.guessClientId()).isEqualTo("clientId-1"); + assertThat(registrarAccessor.guessRegistrarId()).isEqualTo("registrarId-1"); } /** If a user doesn't have access to any registrars, guess fails. */ @Test - void testGuessClientIdForUser_noAccess_fails() { + void testGuessRegistrarIdForUser_noAccess_fails() { AuthenticatedRegistrarAccessor registrarAccessor = AuthenticatedRegistrarAccessor.createForTesting(ImmutableSetMultimap.of()); RegistrarAccessDeniedException thrown = - assertThrows(RegistrarAccessDeniedException.class, registrarAccessor::guessClientId); + assertThrows(RegistrarAccessDeniedException.class, registrarAccessor::guessRegistrarId); assertThat(thrown).hasMessageThat().isEqualTo("TestUserId isn't associated with any registrar"); } @@ -409,4 +404,75 @@ class AuthenticatedRegistrarAccessorTest { .setDefault(HttpServletResponse.class, rsp) .testAllPublicStaticMethods(AuthenticatedRegistrarAccessor.class); } + + @Test + void testConsoleUser_admin() { + google.registry.model.console.User consoleUser = + new google.registry.model.console.User.Builder() + .setGaiaId("gaiaId") + .setEmailAddress("email@email.com") + .setUserRoles( + new UserRoles.Builder().setIsAdmin(true).setGlobalRole(GlobalRole.FTE).build()) + .build(); + AuthResult authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser)); + AuthenticatedRegistrarAccessor registrarAccessor = + new AuthenticatedRegistrarAccessor( + authResult, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); + + // Admin access to all, and owner access to the non-real registrar and the admin registrar + assertThat(registrarAccessor.getAllRegistrarIdsWithRoles()) + .containsExactly( + REGISTRAR_ID_WITH_CONTACT, ADMIN, + REAL_REGISTRAR_ID_WITHOUT_CONTACT, ADMIN, + OTE_REGISTRAR_ID_WITHOUT_CONTACT, ADMIN, + OTE_REGISTRAR_ID_WITHOUT_CONTACT, OWNER, + ADMIN_REGISTRAR_ID, ADMIN, + ADMIN_REGISTRAR_ID, OWNER); + } + + @Test + void testConsoleUser_globalRole() { + // Users with global roles shouldn't necessarily have access to specific registrars if they're + // not admins + google.registry.model.console.User consoleUser = + new google.registry.model.console.User.Builder() + .setGaiaId("gaiaId") + .setEmailAddress("email@email.com") + .setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.SUPPORT_AGENT).build()) + .build(); + AuthResult authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser)); + AuthenticatedRegistrarAccessor registrarAccessor = + new AuthenticatedRegistrarAccessor( + authResult, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); + + // Explicit access to registrars is required for non-admins + assertThat(registrarAccessor.getAllRegistrarIdsWithRoles()).isEmpty(); + } + + @Test + void testConsoleUser_registrarRoles() { + // Registrar employees should have OWNER access to their registrars + google.registry.model.console.User consoleUser = + new google.registry.model.console.User.Builder() + .setGaiaId("gaiaId") + .setEmailAddress("email@email.com") + .setUserRoles( + new UserRoles.Builder() + .setRegistrarRoles( + ImmutableMap.of( + REGISTRAR_ID_WITH_CONTACT, + RegistrarRole.ACCOUNT_MANAGER, + REAL_REGISTRAR_ID_WITHOUT_CONTACT, + RegistrarRole.ACCOUNT_MANAGER)) + .build()) + .build(); + AuthResult authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser)); + AuthenticatedRegistrarAccessor registrarAccessor = + new AuthenticatedRegistrarAccessor( + authResult, ADMIN_REGISTRAR_ID, SUPPORT_GROUP, lazyGroupsConnection); + assertThat(registrarAccessor.getAllRegistrarIdsWithRoles()) + .containsExactly( + REGISTRAR_ID_WITH_CONTACT, OWNER, + REAL_REGISTRAR_ID_WITHOUT_CONTACT, OWNER); + } } diff --git a/core/src/test/java/google/registry/request/auth/RequestAuthenticatorTest.java b/core/src/test/java/google/registry/request/auth/RequestAuthenticatorTest.java index 403cd5f44..b7cca3ac1 100644 --- a/core/src/test/java/google/registry/request/auth/RequestAuthenticatorTest.java +++ b/core/src/test/java/google/registry/request/auth/RequestAuthenticatorTest.java @@ -209,7 +209,7 @@ class RequestAuthenticatorTest { assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); assertThat(authResult.get().userAuthInfo()).isPresent(); - assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser); + assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser); assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isFalse(); assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isEmpty(); } @@ -224,7 +224,7 @@ class RequestAuthenticatorTest { assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); assertThat(authResult.get().userAuthInfo()).isPresent(); - assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser); + assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser); assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isEmpty(); } @@ -264,7 +264,7 @@ class RequestAuthenticatorTest { assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); assertThat(authResult.get().userAuthInfo()).isPresent(); - assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser); + assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser); assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isTrue(); assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isEmpty(); } @@ -280,7 +280,7 @@ class RequestAuthenticatorTest { assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); assertThat(authResult.get().userAuthInfo()).isPresent(); - assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser); + assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser); assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isFalse(); assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isPresent(); assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().authorizedScopes()) @@ -303,7 +303,7 @@ class RequestAuthenticatorTest { assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); assertThat(authResult.get().userAuthInfo()).isPresent(); - assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser); + assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser); assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isTrue(); assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isPresent(); assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().authorizedScopes()) @@ -372,7 +372,7 @@ class RequestAuthenticatorTest { assertThat(authResult).isPresent(); assertThat(authResult.get().authLevel()).isEqualTo(AuthLevel.USER); assertThat(authResult.get().userAuthInfo()).isPresent(); - assertThat(authResult.get().userAuthInfo().get().user()).isEqualTo(testUser); + assertThat(authResult.get().userAuthInfo().get().appEngineUser()).hasValue(testUser); assertThat(authResult.get().userAuthInfo().get().isUserAdmin()).isFalse(); assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo()).isPresent(); assertThat(authResult.get().userAuthInfo().get().oauthTokenInfo().get().authorizedScopes()) diff --git a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockGetActionTest.java b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockGetActionTest.java index 3ab73b961..929cd91a5 100644 --- a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockGetActionTest.java +++ b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockGetActionTest.java @@ -32,6 +32,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSetMultimap; import com.google.gson.Gson; +import google.registry.model.console.RegistrarRole; +import google.registry.model.console.UserRoles; import google.registry.model.domain.RegistryLock; import google.registry.model.registrar.RegistrarPoc; import google.registry.request.Action.Method; @@ -83,6 +85,60 @@ final class RegistryLockGetActionTest { Method.GET, response, accessor, authResult, Optional.of("TheRegistrar")); } + @Test + void testSuccess_newConsoleUser() { + RegistryLock regularLock = + new RegistryLock.Builder() + .setRepoId("repoId") + .setDomainName("example.test") + .setRegistrarId("TheRegistrar") + .setVerificationCode("123456789ABCDEFGHJKLMNPQRSTUVWXY") + .setRegistrarPocId("johndoe@theregistrar.com") + .setLockCompletionTime(fakeClock.nowUtc()) + .build(); + saveRegistryLock(regularLock); + google.registry.model.console.User consoleUser = + new google.registry.model.console.User.Builder() + .setEmailAddress("johndoe@theregistrar.com") + .setGaiaId("gaiaId") + .setUserRoles( + new UserRoles.Builder() + .setRegistrarRoles( + ImmutableMap.of( + "TheRegistrar", RegistrarRole.ACCOUNT_MANAGER_WITH_REGISTRY_LOCK)) + .build()) + .build(); + + action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser)); + action.run(); + assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK); + assertThat(GSON.fromJson(response.getPayload(), Map.class)) + .containsExactly( + "status", + "SUCCESS", + "message", + "Successful locks retrieval", + "results", + ImmutableList.of( + ImmutableMap.of( + "lockEnabledForContact", + true, + "email", + "johndoe@theregistrar.com", + "clientId", + "TheRegistrar", + "locks", + ImmutableList.of( + new ImmutableMap.Builder<>() + .put("domainName", "example.test") + .put("lockedTime", "2000-06-08T22:00:00.000Z") + .put("lockedBy", "johndoe@theregistrar.com") + .put("isLockPending", false) + .put("isUnlockPending", false) + .put("userCanUnlock", true) + .build())))); + } + @Test void testSuccess_retrievesLocks() { RegistryLock expiredLock = diff --git a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockPostActionTest.java b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockPostActionTest.java index f4e6284c1..ba91f2dec 100644 --- a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockPostActionTest.java +++ b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockPostActionTest.java @@ -33,6 +33,8 @@ import com.google.appengine.api.users.User; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import google.registry.model.console.RegistrarRole; +import google.registry.model.console.UserRoles; import google.registry.model.domain.Domain; import google.registry.model.domain.RegistryLock; import google.registry.request.JsonActionRunner; @@ -222,6 +224,47 @@ final class RegistryLockPostActionTest { assertSuccess(response, "lock", "johndoe@theregistrar.com"); } + @Test + void testSuccess_consoleUser() throws Exception { + google.registry.model.console.User consoleUser = + new google.registry.model.console.User.Builder() + .setEmailAddress("johndoe@theregistrar.com") + .setGaiaId("gaiaId") + .setUserRoles( + new UserRoles.Builder() + .setRegistrarRoles( + ImmutableMap.of( + "TheRegistrar", RegistrarRole.ACCOUNT_MANAGER_WITH_REGISTRY_LOCK)) + .build()) + .setRegistryLockPassword("hi") + .build(); + AuthResult consoleAuthResult = + AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser)); + action = createAction(consoleAuthResult); + Map response = action.handleJsonRequest(lockRequest()); + assertSuccess(response, "lock", "johndoe@theregistrar.com"); + } + + @Test + void testSuccess_consoleUser_admin() throws Exception { + google.registry.model.console.User consoleUser = + new google.registry.model.console.User.Builder() + .setEmailAddress("johndoe@theregistrar.com") + .setGaiaId("gaiaId") + .setUserRoles(new UserRoles.Builder().setIsAdmin(true).build()) + .build(); + AuthResult consoleAuthResult = + AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser)); + action = createAction(consoleAuthResult); + Map requestMapWithoutPassword = + ImmutableMap.of( + "isLock", true, + "registrarId", "TheRegistrar", + "domainName", "example.tld"); + Map response = action.handleJsonRequest(requestMapWithoutPassword); + assertSuccess(response, "lock", "johndoe@theregistrar.com"); + } + @Test void testFailure_noInput() { Map response = action.handleJsonRequest(null); @@ -397,6 +440,33 @@ final class RegistryLockPostActionTest { assertFailureWithMessage(response, "Domain example.tld is already unlocked"); } + @Test + void testFailure_consoleUser_wrongPassword_noAdmin() { + google.registry.model.console.User consoleUser = + new google.registry.model.console.User.Builder() + .setEmailAddress("johndoe@theregistrar.com") + .setGaiaId("gaiaId") + .setUserRoles( + new UserRoles.Builder() + .setRegistrarRoles( + ImmutableMap.of( + "TheRegistrar", RegistrarRole.ACCOUNT_MANAGER_WITH_REGISTRY_LOCK)) + .build()) + .setRegistryLockPassword("hi") + .build(); + AuthResult consoleAuthResult = + AuthResult.create(AuthLevel.USER, UserAuthInfo.create(consoleUser)); + action = createAction(consoleAuthResult); + Map response = + action.handleJsonRequest( + ImmutableMap.of( + "registrarId", "TheRegistrar", + "domainName", "example.tld", + "isLock", true, + "password", "badPassword")); + assertFailureWithMessage(response, "Incorrect registry lock password for user"); + } + private ImmutableMap lockRequest() { return fullRequest(true); }