Allow admins to access registrar console without a RegistrarContact

This allows admins to access the registrar console without needing to be added
as a registrar contact. If they are a registrar contact, then that registrar
takes precedence.

Tested=In Alpha

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=164182623
This commit is contained in:
bbilbo 2017-08-03 14:29:05 -07:00 committed by Ben McIlwain
parent 151ae2558f
commit f3919e056d
9 changed files with 308 additions and 69 deletions

View file

@ -171,9 +171,8 @@ upload just that one using the `-M` flag to specify the service to update.
To verify successful deployment, visit To verify successful deployment, visit
https://acme-registry-alpha.appspot.com/registrar in your browser (adjusting https://acme-registry-alpha.appspot.com/registrar in your browser (adjusting
appropriately for the project ID that you actually used). If the project appropriately for the project ID that you actually used). If the project
deployed successfully, you'll see a "You need permission" page indicating that deployed successfully, you'll see the registrar console homepage. It's time to
you need to configure the system and grant access to your Google account. It's go to the next step, configuration.
time to go to the next step, configuration.
Configuration is handled by editing code, rebuilding the project, and deploying Configuration is handled by editing code, rebuilding the project, and deploying
again. See the [configuration guide](./configuration.md) for more details. Once again. See the [configuration guide](./configuration.md) for more details. Once

View file

@ -931,6 +931,16 @@ public final class RegistryConfig {
return config.registryPolicy.checkApiServletClientId; return config.registryPolicy.checkApiServletClientId;
} }
/**
* Returns the clientId of the registrar that admins are automatically logged in as if they
* aren't otherwise associated with one.
*/
@Provides
@Config("registryAdminClientId")
public static String provideRegistryAdminClientId(RegistryConfigSettings config) {
return config.registryPolicy.registryAdminClientId;
}
@Singleton @Singleton
@Provides @Provides
static RegistryConfigSettings provideRegistryConfigSettings() { static RegistryConfigSettings provideRegistryConfigSettings() {

View file

@ -78,6 +78,7 @@ public class RegistryConfigSettings {
public String tmchCrlUrl; public String tmchCrlUrl;
public String tmchMarksDbUrl; public String tmchMarksDbUrl;
public String checkApiServletClientId; public String checkApiServletClientId;
public String registryAdminClientId;
public String reservedTermsExportDisclaimer; public String reservedTermsExportDisclaimer;
public String whoisDisclaimer; public String whoisDisclaimer;
} }

View file

@ -71,6 +71,11 @@ registryPolicy:
# domain checks. # domain checks.
checkApiServletClientId: TheRegistrar checkApiServletClientId: TheRegistrar
# The registry admin's registrar. Admins are granted permission to log in
# using this registrar automatically if they are not associated with any
# registrar
registryAdminClientId: TheRegistrar
# Disclaimer at the top of the exported reserved terms list. # Disclaimer at the top of the exported reserved terms list.
reservedTermsExportDisclaimer: | reservedTermsExportDisclaimer: |
This list contains reserved terms for the TLD. Other terms may be reserved This list contains reserved terms for the TLD. Other terms may be reserved

View file

@ -29,6 +29,7 @@ registryPolicy:
tmchCrlUrl: http://crl.icann.org/tmch.crl tmchCrlUrl: http://crl.icann.org/tmch.crl
tmchMarksDbUrl: https://ry.marksdb.org tmchMarksDbUrl: https://ry.marksdb.org
checkApiServletClientId: placeholder checkApiServletClientId: placeholder
registryAdminClientId: placeholder
whoisDisclaimer: | whoisDisclaimer: |
multi-line multi-line
placeholder placeholder

View file

@ -21,7 +21,6 @@ import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY; import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE; import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserService;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -36,6 +35,7 @@ import google.registry.request.Action;
import google.registry.request.Response; import google.registry.request.Response;
import google.registry.request.auth.Auth; import google.registry.request.auth.Auth;
import google.registry.request.auth.AuthResult; import google.registry.request.auth.AuthResult;
import google.registry.request.auth.UserAuthInfo;
import google.registry.security.XsrfTokenManager; import google.registry.security.XsrfTokenManager;
import google.registry.ui.server.SoyTemplateUtils; import google.registry.ui.server.SoyTemplateUtils;
import google.registry.ui.soy.registrar.ConsoleSoyInfo; import google.registry.ui.soy.registrar.ConsoleSoyInfo;
@ -97,7 +97,7 @@ public final class ConsoleUiAction implements Runnable {
response.setHeader(LOCATION, location); response.setHeader(LOCATION, location);
return; return;
} }
User user = authResult.userAuthInfo().get().user(); UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
response.setContentType(MediaType.HTML_UTF_8); response.setContentType(MediaType.HTML_UTF_8);
response.setHeader(X_FRAME_OPTIONS, "SAMEORIGIN"); // Disallow iframing. response.setHeader(X_FRAME_OPTIONS, "SAMEORIGIN"); // Disallow iframing.
response.setHeader("X-Ui-Compatible", "IE=edge"); // Ask IE not to be silly. response.setHeader("X-Ui-Compatible", "IE=edge"); // Ask IE not to be silly.
@ -119,9 +119,9 @@ public final class ConsoleUiAction implements Runnable {
.render()); .render());
return; return;
} }
data.put("username", user.getNickname()); data.put("username", userAuthInfo.user().getNickname());
data.put("logoutUrl", userService.createLogoutURL(PATH)); data.put("logoutUrl", userService.createLogoutURL(PATH));
if (!sessionUtils.checkRegistrarConsoleLogin(req, user)) { if (!sessionUtils.checkRegistrarConsoleLogin(req, userAuthInfo)) {
response.setStatus(SC_FORBIDDEN); response.setStatus(SC_FORBIDDEN);
response.setPayload( response.setPayload(
TOFU_SUPPLIER.get() TOFU_SUPPLIER.get()
@ -135,7 +135,7 @@ public final class ConsoleUiAction implements Runnable {
Registrar registrar = Registrar registrar =
checkArgumentPresent( checkArgumentPresent(
Registrar.loadByClientIdCached(clientId), "Registrar %s does not exist", clientId); Registrar.loadByClientIdCached(clientId), "Registrar %s does not exist", clientId);
data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail())); data.put("xsrfToken", xsrfTokenManager.generateToken(userAuthInfo.user().getEmail()));
data.put("clientId", clientId); data.put("clientId", clientId);
data.put("showPaymentLink", registrar.getBillingMethod() == Registrar.BillingMethod.BRAINTREE); data.put("showPaymentLink", registrar.getBillingMethod() == Registrar.BillingMethod.BRAINTREE);

View file

@ -22,12 +22,15 @@ import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
import com.google.appengine.api.users.User; import com.google.appengine.api.users.User;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.registrar.Registrar; import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarContact; import google.registry.model.registrar.RegistrarContact;
import google.registry.request.HttpException.ForbiddenException; import google.registry.request.HttpException.ForbiddenException;
import google.registry.request.auth.AuthResult; import google.registry.request.auth.AuthResult;
import google.registry.request.auth.UserAuthInfo;
import google.registry.util.FormattingLogger; import google.registry.util.FormattingLogger;
import javax.annotation.CheckReturnValue; import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -40,10 +43,14 @@ import javax.servlet.http.HttpSession;
@Immutable @Immutable
public class SessionUtils { public class SessionUtils {
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass(); static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
public static final String CLIENT_ID_ATTRIBUTE = "clientId"; public static final String CLIENT_ID_ATTRIBUTE = "clientId";
@Inject
@Config("registryAdminClientId")
String registryAdminClientId;
@Inject public SessionUtils() {} @Inject public SessionUtils() {}
/** /**
@ -58,7 +65,7 @@ public class SessionUtils {
if (!authResult.userAuthInfo().isPresent()) { if (!authResult.userAuthInfo().isPresent()) {
throw new ForbiddenException("Not logged in"); throw new ForbiddenException("Not logged in");
} }
if (!checkRegistrarConsoleLogin(request, authResult.userAuthInfo().get().user())) { if (!checkRegistrarConsoleLogin(request, authResult.userAuthInfo().get())) {
throw new ForbiddenException("Not authorized to access Registrar Console"); throw new ForbiddenException("Not authorized to access Registrar Console");
} }
String clientId = getRegistrarClientId(request); String clientId = getRegistrarClientId(request);
@ -86,28 +93,62 @@ public class SessionUtils {
* error response and abort the request. * error response and abort the request.
*/ */
@CheckReturnValue @CheckReturnValue
public boolean checkRegistrarConsoleLogin(HttpServletRequest req, User user) { public boolean checkRegistrarConsoleLogin(HttpServletRequest req, UserAuthInfo userAuthInfo) {
checkState(user != null, "No logged in user found"); checkState(userAuthInfo != null, "No logged in user found");
User user = userAuthInfo.user();
HttpSession session = req.getSession(); HttpSession session = req.getSession();
String clientId = (String) session.getAttribute(CLIENT_ID_ATTRIBUTE); String clientId = (String) session.getAttribute(CLIENT_ID_ATTRIBUTE);
if (clientId == null) {
Optional<Registrar> registrar = guessRegistrar(user.getUserId()); // Use the clientId if it exists
if (!registrar.isPresent()) { if (clientId != null) {
logger.infofmt("User not associated with any Registrar: %s (%s)",
user.getUserId(), user.getEmail());
return false;
}
verify(hasAccessToRegistrar(registrar.get(), user.getUserId()));
session.setAttribute(CLIENT_ID_ATTRIBUTE, registrar.get().getClientId());
} else {
if (!hasAccessToRegistrar(clientId, user.getUserId())) { if (!hasAccessToRegistrar(clientId, user.getUserId())) {
logger.infofmt("Registrar Console access revoked: %s for %s (%s)", logger.infofmt("Registrar Console access revoked: %s", clientId);
clientId, user.getEmail(), user.getUserId());
session.invalidate(); session.invalidate();
return false; return false;
} }
logger.infofmt("Associating user %s with given registrar %s.", user.getUserId(), clientId);
return true;
} }
return true;
// The clientId was null, so let's try and find a registrar this user is associated with
Optional<Registrar> registrar = findRegistrarForUser(user.getUserId());
if (registrar.isPresent()) {
verify(hasAccessToRegistrar(registrar.get(), user.getUserId()));
logger.infofmt(
"Associating user %s with found registrar %s.",
user.getUserId(), registrar.get().getClientId());
session.setAttribute(CLIENT_ID_ATTRIBUTE, registrar.get().getClientId());
return true;
}
// We couldn't guess the registrar, but maybe the user is an admin and we can use the
// registryAdminClientId
if (userAuthInfo.isUserAdmin()) {
if (Strings.isNullOrEmpty(registryAdminClientId)) {
logger.infofmt(
"Cannot associate admin user %s with configured client Id."
+ " ClientId is null or empty.",
user.getUserId());
return false;
}
if (!Registrar.loadByClientIdCached(registryAdminClientId).isPresent()) {
logger.infofmt(
"Cannot associate admin user %s with configured client Id %s."
+ " Registrar does not exist.",
user.getUserId(), registryAdminClientId);
return false;
}
logger.infofmt(
"User %s is an admin with no associated registrar."
+ " Automatically associating the user with configured client Id %s.",
user.getUserId(), registryAdminClientId);
session.setAttribute(CLIENT_ID_ATTRIBUTE, registryAdminClientId);
return true;
}
// We couldn't find any relevant clientId
logger.infofmt("User not associated with any Registrar: %s", user.getUserId());
return false;
} }
/** /**
@ -123,7 +164,7 @@ public class SessionUtils {
} }
/** Returns first {@link Registrar} that {@code gaeUserId} is authorized to administer. */ /** Returns first {@link Registrar} that {@code gaeUserId} is authorized to administer. */
private static Optional<Registrar> guessRegistrar(String gaeUserId) { private static Optional<Registrar> findRegistrarForUser(String gaeUserId) {
RegistrarContact contact = ofy().load() RegistrarContact contact = ofy().load()
.type(RegistrarContact.class) .type(RegistrarContact.class)
.filter("gaeUserId", gaeUserId) .filter("gaeUserId", gaeUserId)
@ -141,7 +182,7 @@ public class SessionUtils {
} }
/** @see #hasAccessToRegistrar(Registrar, String) */ /** @see #hasAccessToRegistrar(Registrar, String) */
private static boolean hasAccessToRegistrar(String clientId, final String gaeUserId) { protected static boolean hasAccessToRegistrar(String clientId, final String gaeUserId) {
Optional<Registrar> registrar = Registrar.loadByClientIdCached(clientId); Optional<Registrar> registrar = Registrar.loadByClientIdCached(clientId);
if (!registrar.isPresent()) { if (!registrar.isPresent()) {
logger.warningfmt("Registrar '%s' disappeared from Datastore!", clientId); logger.warningfmt("Registrar '%s' disappeared from Datastore!", clientId);

View file

@ -70,8 +70,9 @@ public class ConsoleUiActionTest {
action.sessionUtils = sessionUtils; action.sessionUtils = sessionUtils;
action.userService = UserServiceFactory.getUserService(); action.userService = UserServiceFactory.getUserService();
action.xsrfTokenManager = new XsrfTokenManager(new FakeClock(), action.userService); action.xsrfTokenManager = new XsrfTokenManager(new FakeClock(), action.userService);
action.authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false)); UserAuthInfo userAuthInfo = UserAuthInfo.create(user, false);
when(sessionUtils.checkRegistrarConsoleLogin(request, user)).thenReturn(true); action.authResult = AuthResult.create(AuthLevel.USER, userAuthInfo);
when(sessionUtils.checkRegistrarConsoleLogin(request, userAuthInfo)).thenReturn(true);
when(sessionUtils.getRegistrarClientId(request)).thenReturn("TheRegistrar"); when(sessionUtils.getRegistrarClientId(request)).thenReturn("TheRegistrar");
} }
@ -109,7 +110,8 @@ public class ConsoleUiActionTest {
@Test @Test
public void testUserDoesntHaveAccessToAnyRegistrar_showsWhoAreYouPage() throws Exception { public void testUserDoesntHaveAccessToAnyRegistrar_showsWhoAreYouPage() throws Exception {
when(sessionUtils.checkRegistrarConsoleLogin(any(HttpServletRequest.class), any(User.class))) when(sessionUtils.checkRegistrarConsoleLogin(
any(HttpServletRequest.class), any(UserAuthInfo.class)))
.thenReturn(false); .thenReturn(false);
action.run(); action.run();
assertThat(response.getPayload()).contains("<h1>You need permission</h1>"); assertThat(response.getPayload()).contains("<h1>You need permission</h1>");

View file

@ -18,6 +18,8 @@ import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.AppEngineRule.THE_REGISTRAR_GAE_USER_ID; import static google.registry.testing.AppEngineRule.THE_REGISTRAR_GAE_USER_ID;
import static google.registry.testing.DatastoreHelper.deleteResource; import static google.registry.testing.DatastoreHelper.deleteResource;
import static google.registry.testing.DatastoreHelper.loadRegistrar; import static google.registry.testing.DatastoreHelper.loadRegistrar;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.LogsSubject.assertAboutLogs;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@ -26,13 +28,17 @@ import static org.mockito.Mockito.when;
import com.google.appengine.api.users.User; import com.google.appengine.api.users.User;
import com.google.common.testing.NullPointerTester; import com.google.common.testing.NullPointerTester;
import com.google.common.testing.TestLogHandler;
import google.registry.model.registrar.RegistrarContact; import google.registry.model.registrar.RegistrarContact;
import google.registry.request.auth.UserAuthInfo;
import google.registry.testing.AppEngineRule; import google.registry.testing.AppEngineRule;
import google.registry.testing.ExceptionRule; import google.registry.testing.ExceptionRule;
import google.registry.testing.InjectRule; import google.registry.testing.InjectRule;
import java.util.logging.Level;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@ -43,60 +49,50 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public class SessionUtilsTest { public class SessionUtilsTest {
@Rule @Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
@Rule @Rule public final ExceptionRule thrown = new ExceptionRule();
public final ExceptionRule thrown = new ExceptionRule();
@Rule @Rule public final InjectRule inject = new InjectRule();
public final InjectRule inject = new InjectRule();
private final HttpServletRequest req = mock(HttpServletRequest.class); private final HttpServletRequest req = mock(HttpServletRequest.class);
private final HttpServletResponse rsp = mock(HttpServletResponse.class); private final HttpServletResponse rsp = mock(HttpServletResponse.class);
private final HttpSession session = mock(HttpSession.class); private final HttpSession session = mock(HttpSession.class);
private final TestLogHandler testLogHandler = new TestLogHandler();
private SessionUtils sessionUtils; private SessionUtils sessionUtils;
private final User jart = new User("jart@google.com", "google.com", THE_REGISTRAR_GAE_USER_ID);
private final User bozo = new User("bozo@bing.com", "bing.com", "badGaeUserId"); private static final UserAuthInfo AUTHORIZED_USER = createAuthInfo(true, false);
private static final UserAuthInfo UNAUTHORIZED_USER = createAuthInfo(false, false);
private static final UserAuthInfo AUTHORIZED_ADMIN = createAuthInfo(true, true);
private static final UserAuthInfo UNAUTHORIZED_ADMIN = createAuthInfo(false, true);
private static final String DEFAULT_CLIENT_ID = "TheRegistrar";
private static final String ADMIN_CLIENT_ID = "NewRegistrar";
private static UserAuthInfo createAuthInfo(boolean isAuthorized, boolean isAdmin) {
return UserAuthInfo.create(
new User(
"user1@google.com",
"google.com",
isAuthorized ? THE_REGISTRAR_GAE_USER_ID : "badGaeUserId"),
isAdmin);
}
@Before @Before
public void before() throws Exception { public void before() throws Exception {
SessionUtils.logger.addHandler(testLogHandler);
sessionUtils = new SessionUtils(); sessionUtils = new SessionUtils();
sessionUtils.registryAdminClientId = ADMIN_CLIENT_ID;
persistResource(loadRegistrar(ADMIN_CLIENT_ID));
when(req.getSession()).thenReturn(session); when(req.getSession()).thenReturn(session);
} }
@Test @After
public void testCheckRegistrarConsoleLogin_authedButNoSession_createsSession() throws Exception { public void after() throws Exception {
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, jart)).isTrue(); SessionUtils.logger.removeHandler(testLogHandler);
verify(session).setAttribute(eq("clientId"), eq("TheRegistrar"));
}
@Test
public void testCheckRegistrarConsoleLogin_authedWithValidSession_doesNothing() throws Exception {
when(session.getAttribute("clientId")).thenReturn("TheRegistrar");
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, jart)).isTrue();
verify(session).getAttribute("clientId");
verifyNoMoreInteractions(session);
}
@Test
public void testCheckRegistrarConsoleLogin_sessionRevoked_invalidates() throws Exception {
RegistrarContact.updateContacts(
loadRegistrar("TheRegistrar"), new java.util.HashSet<RegistrarContact>());
when(session.getAttribute("clientId")).thenReturn("TheRegistrar");
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, jart)).isFalse();
verify(session).invalidate();
}
@Test
public void testCheckRegistrarConsoleLogin_orphanedContactIsDenied() throws Exception {
deleteResource(loadRegistrar("TheRegistrar"));
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, jart)).isFalse();
} }
/** User needs to be logged in before calling checkRegistrarConsoleLogin */
@Test @Test
public void testCheckRegistrarConsoleLogin_notLoggedIn_throwsIllegalStateException() public void testCheckRegistrarConsoleLogin_notLoggedIn_throwsIllegalStateException()
throws Exception { throws Exception {
@ -105,9 +101,193 @@ public class SessionUtilsTest {
boolean unused = sessionUtils.checkRegistrarConsoleLogin(req, null); boolean unused = sessionUtils.checkRegistrarConsoleLogin(req, null);
} }
/**
* If clientId exists in the session and the user does not have access to that registrar, then no
* access should be granted.
*/
@Test @Test
public void testCheckRegistrarConsoleLogin_notAllowed_returnsFalse() throws Exception { public void testCheckRegistrarConsoleLogin_hasSession_noAccess_isNotAdmin() throws Exception {
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, bozo)).isFalse(); when(session.getAttribute("clientId")).thenReturn(DEFAULT_CLIENT_ID);
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, UNAUTHORIZED_USER)).isFalse();
verify(session).invalidate();
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(Level.INFO, "Registrar Console access revoked");
}
/**
* If clientId exists in the session and the user does not have access to that registrar, then
* access should be revoked. The admin flag should be ignored.
*/
@Test
public void testCheckRegistrarConsoleLogin_hasSession_noAccess_isAdmin() throws Exception {
when(session.getAttribute("clientId")).thenReturn(DEFAULT_CLIENT_ID);
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, UNAUTHORIZED_ADMIN)).isFalse();
verify(session).invalidate();
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(Level.INFO, "Registrar Console access revoked");
}
/**
* If clientId exists in the session and the user does have access to that registrar, then access
* should be allowed.
*/
@Test
public void testCheckRegistrarConsoleLogin_hasSession_hasAccess_isNotAdmin() throws Exception {
when(session.getAttribute("clientId")).thenReturn(DEFAULT_CLIENT_ID);
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, AUTHORIZED_USER)).isTrue();
verify(session).getAttribute("clientId");
verifyNoMoreInteractions(session);
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(
Level.INFO,
String.format(
"Associating user %s with given registrar %s.",
AUTHORIZED_USER.user().getUserId(), DEFAULT_CLIENT_ID));
}
/**
* If clientId exists in the session and the user does have access to that registrar, then access
* should be allowed. The admin flag should be ignored.
*/
@Test
public void testCheckRegistrarConsoleLogin_hasSession_hasAccess_isAdmin() throws Exception {
when(session.getAttribute("clientId")).thenReturn(DEFAULT_CLIENT_ID);
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, AUTHORIZED_ADMIN)).isTrue();
verify(session).getAttribute("clientId");
verifyNoMoreInteractions(session);
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(
Level.INFO,
String.format(
"Associating user %s with given registrar %s.",
AUTHORIZED_ADMIN.user().getUserId(), DEFAULT_CLIENT_ID));
}
/**
* If clientId does not exist in the session and the user has access to a registrar, then access
* should be granted to that registrar.
*/
@Test
public void testCheckRegistrarConsoleLogin_noSession_hasAccess_isNotAdmin() throws Exception {
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, AUTHORIZED_USER)).isTrue();
verify(session).setAttribute(eq("clientId"), eq(DEFAULT_CLIENT_ID));
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(
Level.INFO,
String.format(
"Associating user %s with found registrar %s.",
AUTHORIZED_USER.user().getUserId(), DEFAULT_CLIENT_ID));
}
/**
* If clientId does not exist in the session and the user has access to a registrar, then access
* should be granted to that registrar. The admin flag should be ignored.
*/
@Test
public void testCheckRegistrarConsoleLogin_noSession_hasAccess_isAdmin() throws Exception {
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, AUTHORIZED_ADMIN)).isTrue();
verify(session).setAttribute(eq("clientId"), eq(DEFAULT_CLIENT_ID));
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(
Level.INFO,
String.format(
"Associating user %s with found registrar %s.",
AUTHORIZED_ADMIN.user().getUserId(), DEFAULT_CLIENT_ID));
}
/**
* If clientId does not exist in the session, the user is not associated with a registrar and the
* user is an admin, then access could be granted to the configured adminClientId. But if the
* configured adminClientId is empty or null, no access is granted.
*/
@Test
public void testCheckRegistrarConsoleLogin_noSession_noAccess_isAdmin_adminClientIdEmpty()
throws Exception {
sessionUtils.registryAdminClientId = "";
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, UNAUTHORIZED_ADMIN)).isFalse();
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(
Level.INFO,
String.format(
"Cannot associate admin user %s with configured client Id."
+ " ClientId is null or empty.",
UNAUTHORIZED_ADMIN.user().getUserId()));
}
/**
* If clientId does not exist in the session, the user is not associated with a registrar and the
* user is an admin, then access could be granted to the configured adminClientId. But if the
* configured adminClientId does not reference a registry, then no access is granted.
*/
@Test
public void testCheckRegistrarConsoleLogin_noSession_noAccess_isAdmin_adminClientIdInvalid()
throws Exception {
sessionUtils.registryAdminClientId = "NonexistentRegistry";
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, UNAUTHORIZED_ADMIN)).isFalse();
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(
Level.INFO,
String.format(
"Cannot associate admin user %s with configured client Id %s."
+ " Registrar does not exist.",
UNAUTHORIZED_ADMIN.user().getUserId(), "NonexistentRegistry"));
}
/**
* If clientId does not exist in the session, the user does not have access to a registrar and the
* user is an admin, then grant the user access to the validated configured adminClientId.
*/
@Test
public void testCheckRegistrarConsoleLogin_noSession_noAccess_isAdmin() throws Exception {
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, UNAUTHORIZED_ADMIN)).isTrue();
verify(session).setAttribute(eq("clientId"), eq(ADMIN_CLIENT_ID));
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(
Level.INFO,
String.format(
"User %s is an admin with no associated registrar."
+ " Automatically associating the user with configured client Id %s.",
UNAUTHORIZED_ADMIN.user().getUserId(), ADMIN_CLIENT_ID));
}
/**
* If clientId does not exist in the session and the user is not associated with a registrar, then
* access should not be granted.
*/
@Test
public void testCheckRegistrarConsoleLogin_noSession_noAccess_isNotAdmin() throws Exception {
assertThat(sessionUtils.checkRegistrarConsoleLogin(req, UNAUTHORIZED_USER)).isFalse();
assertAboutLogs()
.that(testLogHandler)
.hasLogAtLevelWithMessage(
Level.INFO,
String.format(
"User not associated with any Registrar: %s",
UNAUTHORIZED_USER.user().getUserId()));
}
@Test
public void testHasAccessToRegistrar_orphanedContact_returnsFalse() throws Exception {
deleteResource(loadRegistrar(DEFAULT_CLIENT_ID));
assertThat(SessionUtils.hasAccessToRegistrar(DEFAULT_CLIENT_ID, THE_REGISTRAR_GAE_USER_ID))
.isFalse();
}
@Test
public void testHasAccessToRegistrar_accessRevoked_returnsFalse() throws Exception {
RegistrarContact.updateContacts(
loadRegistrar(DEFAULT_CLIENT_ID), new java.util.HashSet<RegistrarContact>());
assertThat(SessionUtils.hasAccessToRegistrar(DEFAULT_CLIENT_ID, THE_REGISTRAR_GAE_USER_ID))
.isFalse();
} }
@Test @Test