mirror of
https://github.com/google/nomulus.git
synced 2025-05-14 00:17:20 +02:00
Allow admins read-only access to all registrars
We want to be able to view / test / debug how the registrar console looks for our clients. However, we don't want to accidentally change the data for registrars, especially in a "non-accountable" way (where we later don't know who did that change) So we do 2 things here: - Add a "mode" (read-only and read-write) to the getRegistrarForUser function. We set it according to what we want to do with the registrar. Currently, read-write is only requested for the "update" RegistrarSetting action. Admins will have read-only access to all registrars, but read-write access only to the "admin registrar" (or whatever registrar they are contacts for). - Support an undocumented "clientId=XXX" query param that replaces the "guessClientIdForUser" function in the original page load. We can then set it when we want to view a different account. We also change the navigation links on the HTML page to preserve the query. ------------------------- This might be used also for a better user experience for our clients, especially those with multiple "clientId"s (some registrar entities have multiple "registrar" objects) Currently, they have to have a separate user for each clientId, and only have one user allowed which has both read and write permissions. Using this change, we can give them the possibility to add users on their own, some with read-only access (to view billing information without being able to change anything), and use a single user for all their clientIds. ------------------------- ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=215480610
This commit is contained in:
parent
5038fa917c
commit
1d621bd14d
13 changed files with 267 additions and 63 deletions
|
@ -26,12 +26,14 @@ import google.registry.request.RequestComponentBuilder;
|
||||||
import google.registry.request.RequestModule;
|
import google.registry.request.RequestModule;
|
||||||
import google.registry.request.RequestScope;
|
import google.registry.request.RequestScope;
|
||||||
import google.registry.ui.server.registrar.ConsoleUiAction;
|
import google.registry.ui.server.registrar.ConsoleUiAction;
|
||||||
|
import google.registry.ui.server.registrar.RegistrarConsoleModule;
|
||||||
import google.registry.ui.server.registrar.RegistrarSettingsAction;
|
import google.registry.ui.server.registrar.RegistrarSettingsAction;
|
||||||
|
|
||||||
/** Dagger component with per-request lifetime for "default" App Engine module. */
|
/** Dagger component with per-request lifetime for "default" App Engine module. */
|
||||||
@RequestScope
|
@RequestScope
|
||||||
@Subcomponent(
|
@Subcomponent(
|
||||||
modules = {
|
modules = {
|
||||||
|
RegistrarConsoleModule.class,
|
||||||
DnsModule.class,
|
DnsModule.class,
|
||||||
EppTlsModule.class,
|
EppTlsModule.class,
|
||||||
RequestModule.class,
|
RequestModule.class,
|
||||||
|
|
|
@ -18,6 +18,7 @@ import static com.google.common.base.Charsets.UTF_8;
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
|
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
import static google.registry.ui.server.registrar.SessionUtils.AccessType.READ_ONLY;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||||
|
@ -181,7 +182,7 @@ public abstract class RdapActionBase implements Runnable {
|
||||||
String clientId = sessionUtils.guessClientIdForUser(authResult);
|
String clientId = sessionUtils.guessClientIdForUser(authResult);
|
||||||
// We load the Registrar to make sure the user has access to it. We don't actually need it,
|
// We load the Registrar to make sure the user has access to it. We don't actually need it,
|
||||||
// we're just checking if an exception is thrown.
|
// we're just checking if an exception is thrown.
|
||||||
sessionUtils.getRegistrarForUserCached(clientId, authResult);
|
sessionUtils.getRegistrarForUserCached(clientId, READ_ONLY, authResult);
|
||||||
return Optional.of(clientId);
|
return Optional.of(clientId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.atWarning().withCause(e).log(
|
logger.atWarning().withCause(e).log(
|
||||||
|
|
|
@ -160,7 +160,7 @@ registry.registrar.Console.prototype.changeNavStyle = function() {
|
||||||
slashNdx = slashNdx == -1 ? hashToken.length : slashNdx;
|
slashNdx = slashNdx == -1 ? hashToken.length : slashNdx;
|
||||||
var regNavlist = goog.dom.getRequiredElement('reg-navlist');
|
var regNavlist = goog.dom.getRequiredElement('reg-navlist');
|
||||||
var path = hashToken.substring(0, slashNdx);
|
var path = hashToken.substring(0, slashNdx);
|
||||||
var active = regNavlist.querySelector('a[href="/registrar#' + path + '"]');
|
var active = regNavlist.querySelector('a[href="#' + path + '"]');
|
||||||
if (goog.isNull(active)) {
|
if (goog.isNull(active)) {
|
||||||
registry.util.log('Unknown path or path form in changeNavStyle.');
|
registry.util.log('Unknown path or path form in changeNavStyle.');
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -16,6 +16,8 @@ package google.registry.ui.server.registrar;
|
||||||
|
|
||||||
import static com.google.common.net.HttpHeaders.LOCATION;
|
import static com.google.common.net.HttpHeaders.LOCATION;
|
||||||
import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS;
|
import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS;
|
||||||
|
import static google.registry.ui.server.registrar.RegistrarConsoleModule.PARAM_CLIENT_ID;
|
||||||
|
import static google.registry.ui.server.registrar.SessionUtils.AccessType.READ_ONLY;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
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;
|
||||||
|
@ -34,12 +36,14 @@ import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.HttpException.ForbiddenException;
|
import google.registry.request.HttpException.ForbiddenException;
|
||||||
|
import google.registry.request.Parameter;
|
||||||
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.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;
|
||||||
|
import java.util.Optional;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
@ -79,6 +83,7 @@ public final class ConsoleUiAction implements Runnable {
|
||||||
@Inject @Config("supportPhoneNumber") String supportPhoneNumber;
|
@Inject @Config("supportPhoneNumber") String supportPhoneNumber;
|
||||||
@Inject @Config("technicalDocsUrl") String technicalDocsUrl;
|
@Inject @Config("technicalDocsUrl") String technicalDocsUrl;
|
||||||
@Inject @Config("registrarConsoleEnabled") boolean enabled;
|
@Inject @Config("registrarConsoleEnabled") boolean enabled;
|
||||||
|
@Inject @Parameter(PARAM_CLIENT_ID) Optional<String> paramClientId;
|
||||||
@Inject ConsoleUiAction() {}
|
@Inject ConsoleUiAction() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -126,7 +131,8 @@ public final class ConsoleUiAction implements Runnable {
|
||||||
data.put("logoutUrl", userService.createLogoutURL(PATH));
|
data.put("logoutUrl", userService.createLogoutURL(PATH));
|
||||||
data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail()));
|
data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail()));
|
||||||
try {
|
try {
|
||||||
String clientId = sessionUtils.guessClientIdForUser(authResult);
|
String clientId =
|
||||||
|
paramClientId.orElseGet(() -> sessionUtils.guessClientIdForUser(authResult));
|
||||||
data.put("clientId", clientId);
|
data.put("clientId", clientId);
|
||||||
// We want to load the registrar even if we won't use it later (even if we remove the
|
// We want to load the registrar even if we won't use it later (even if we remove the
|
||||||
// requireFeeExtension) - to make sure the user indeed has access to the guessed registrar.
|
// requireFeeExtension) - to make sure the user indeed has access to the guessed registrar.
|
||||||
|
@ -135,7 +141,7 @@ public final class ConsoleUiAction implements Runnable {
|
||||||
// since we double check the access to the registrar on any read / update request. We have to
|
// since we double check the access to the registrar on any read / update request. We have to
|
||||||
// - since the access might get revoked between the initial page load and the request! (also
|
// - since the access might get revoked between the initial page load and the request! (also
|
||||||
// because the requests come from the browser, and can easily be faked)
|
// because the requests come from the browser, and can easily be faked)
|
||||||
Registrar registrar = sessionUtils.getRegistrarForUser(clientId, authResult);
|
Registrar registrar = sessionUtils.getRegistrarForUser(clientId, READ_ONLY, authResult);
|
||||||
data.put("requireFeeExtension", registrar.getPremiumPriceAckRequired());
|
data.put("requireFeeExtension", registrar.getPremiumPriceAckRequired());
|
||||||
} catch (ForbiddenException e) {
|
} catch (ForbiddenException e) {
|
||||||
logger.atWarning().withCause(e).log(
|
logger.atWarning().withCause(e).log(
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2018 The Nomulus Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package google.registry.ui.server.registrar;
|
||||||
|
|
||||||
|
|
||||||
|
import static google.registry.request.RequestParameters.extractOptionalParameter;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
import google.registry.request.Parameter;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/** Dagger module for the Registrar Console parameters. */
|
||||||
|
@Module
|
||||||
|
public final class RegistrarConsoleModule {
|
||||||
|
|
||||||
|
static final String PARAM_CLIENT_ID = "clientId";
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Parameter(PARAM_CLIENT_ID)
|
||||||
|
static Optional<String> provideClientId(HttpServletRequest req) {
|
||||||
|
return extractOptionalParameter(req, PARAM_CLIENT_ID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,8 @@ import static google.registry.export.sheet.SyncRegistrarsSheetAction.enqueueRegi
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.security.JsonResponseHelper.Status.ERROR;
|
import static google.registry.security.JsonResponseHelper.Status.ERROR;
|
||||||
import static google.registry.security.JsonResponseHelper.Status.SUCCESS;
|
import static google.registry.security.JsonResponseHelper.Status.SUCCESS;
|
||||||
|
import static google.registry.ui.server.registrar.SessionUtils.AccessType.READ_ONLY;
|
||||||
|
import static google.registry.ui.server.registrar.SessionUtils.AccessType.READ_WRITE;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.HashMultimap;
|
import com.google.common.collect.HashMultimap;
|
||||||
|
@ -132,7 +134,9 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||||
|
|
||||||
Map<String, Object> read(String clientId) {
|
Map<String, Object> read(String clientId) {
|
||||||
return JsonResponseHelper.create(
|
return JsonResponseHelper.create(
|
||||||
SUCCESS, "Success", sessionUtils.getRegistrarForUser(clientId, authResult).toJsonMap());
|
SUCCESS,
|
||||||
|
"Success",
|
||||||
|
sessionUtils.getRegistrarForUser(clientId, READ_ONLY, authResult).toJsonMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> update(final Map<String, ?> args, String clientId) {
|
Map<String, Object> update(final Map<String, ?> args, String clientId) {
|
||||||
|
@ -142,7 +146,8 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
||||||
// We load the registrar here rather than outside of the transaction - to make
|
// We load the registrar here rather than outside of the transaction - to make
|
||||||
// sure we have the latest version. This one is loaded inside the transaction, so it's
|
// sure we have the latest version. This one is loaded inside the transaction, so it's
|
||||||
// guaranteed to not change before we update it.
|
// guaranteed to not change before we update it.
|
||||||
Registrar registrar = sessionUtils.getRegistrarForUser(clientId, authResult);
|
Registrar registrar =
|
||||||
|
sessionUtils.getRegistrarForUser(clientId, READ_WRITE, authResult);
|
||||||
// Verify that the registrar hasn't been changed.
|
// Verify that the registrar hasn't been changed.
|
||||||
// To do that - we find the latest update time (or null if the registrar has been
|
// To do that - we find the latest update time (or null if the registrar has been
|
||||||
// deleted) and compare to the update time from the args. The update time in the args
|
// deleted) and compare to the update time from the args. The update time in the args
|
||||||
|
|
|
@ -30,7 +30,7 @@ import java.util.function.Function;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/** Authenticated Registrar access helper class. */
|
/** HTTP session management helper class. */
|
||||||
@Immutable
|
@Immutable
|
||||||
public class SessionUtils {
|
public class SessionUtils {
|
||||||
|
|
||||||
|
@ -43,6 +43,9 @@ public class SessionUtils {
|
||||||
@Inject
|
@Inject
|
||||||
public SessionUtils() {}
|
public SessionUtils() {}
|
||||||
|
|
||||||
|
/** Type of access we're requesting. */
|
||||||
|
public enum AccessType {READ_ONLY, READ_WRITE}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads Registrar on behalf of an authorised user.
|
* Loads Registrar on behalf of an authorised user.
|
||||||
*
|
*
|
||||||
|
@ -50,10 +53,13 @@ public class SessionUtils {
|
||||||
* access the requested registrar.
|
* access the requested registrar.
|
||||||
*
|
*
|
||||||
* @param clientId ID of the registrar we request
|
* @param clientId ID of the registrar we request
|
||||||
|
* @param accessType what kind of access do we want for this registrar - just read it or write as
|
||||||
|
* well? (different users might have different access levels)
|
||||||
* @param authResult AuthResult of the user on behalf of which we want to access the data
|
* @param authResult AuthResult of the user on behalf of which we want to access the data
|
||||||
*/
|
*/
|
||||||
public Registrar getRegistrarForUser(String clientId, AuthResult authResult) {
|
public Registrar getRegistrarForUser(
|
||||||
return getAndAuthorize(Registrar::loadByClientId, clientId, authResult);
|
String clientId, AccessType accessType, AuthResult authResult) {
|
||||||
|
return getAndAuthorize(Registrar::loadByClientId, clientId, accessType, authResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,15 +69,19 @@ public class SessionUtils {
|
||||||
* access the requested registrar.
|
* access the requested registrar.
|
||||||
*
|
*
|
||||||
* @param clientId ID of the registrar we request
|
* @param clientId ID of the registrar we request
|
||||||
|
* @param accessType what kind of access do we want for this registrar - just read it or write as
|
||||||
|
* well? (different users might have different access levels)
|
||||||
* @param authResult AuthResult of the user on behalf of which we want to access the data
|
* @param authResult AuthResult of the user on behalf of which we want to access the data
|
||||||
*/
|
*/
|
||||||
public Registrar getRegistrarForUserCached(String clientId, AuthResult authResult) {
|
public Registrar getRegistrarForUserCached(
|
||||||
return getAndAuthorize(Registrar::loadByClientIdCached, clientId, authResult);
|
String clientId, AccessType accessType, AuthResult authResult) {
|
||||||
|
return getAndAuthorize(Registrar::loadByClientIdCached, clientId, accessType, authResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
Registrar getAndAuthorize(
|
private Registrar getAndAuthorize(
|
||||||
Function<String, Optional<Registrar>> registrarLoader,
|
Function<String, Optional<Registrar>> registrarLoader,
|
||||||
String clientId,
|
String clientId,
|
||||||
|
AccessType accessType,
|
||||||
AuthResult authResult) {
|
AuthResult authResult) {
|
||||||
UserAuthInfo userAuthInfo =
|
UserAuthInfo userAuthInfo =
|
||||||
authResult.userAuthInfo().orElseThrow(() -> new ForbiddenException("Not logged in"));
|
authResult.userAuthInfo().orElseThrow(() -> new ForbiddenException("Not logged in"));
|
||||||
|
@ -97,8 +107,17 @@ public class SessionUtils {
|
||||||
return registrar;
|
return registrar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isAdmin && accessType == AccessType.READ_ONLY) {
|
||||||
|
// Admins have read-only access to all registrars
|
||||||
|
logger.atInfo().log(
|
||||||
|
"Allowing admin %s read-only access to registrar %s.", userIdForLogging, clientId);
|
||||||
|
return registrar;
|
||||||
|
}
|
||||||
|
|
||||||
throw new ForbiddenException(
|
throw new ForbiddenException(
|
||||||
String.format("User %s doesn't have access to registrar %s", userIdForLogging, clientId));
|
String.format(
|
||||||
|
"User %s doesn't have %s access to registrar %s",
|
||||||
|
userIdForLogging, accessType, clientId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -78,21 +78,21 @@
|
||||||
<div id="reg-nav" class="{css('kd-content-sidebar')}">
|
<div id="reg-nav" class="{css('kd-content-sidebar')}">
|
||||||
<ul id="reg-navlist">
|
<ul id="reg-navlist">
|
||||||
<li>
|
<li>
|
||||||
<a href="/registrar#">Home</a>
|
<a href="#">Home</a>
|
||||||
<li>
|
<li>
|
||||||
<a href="/registrar#resources">Resources & billing</a>
|
<a href="#resources">Resources & billing</a>
|
||||||
<li>
|
<li>
|
||||||
<ul>
|
<ul>
|
||||||
<span class="{css('reg-navlist-sub')}">Settings</span>
|
<span class="{css('reg-navlist-sub')}">Settings</span>
|
||||||
<li>
|
<li>
|
||||||
<a href="/registrar#whois-settings">WHOIS</a>
|
<a href="#whois-settings">WHOIS</a>
|
||||||
<li>
|
<li>
|
||||||
<a href="/registrar#security-settings">Security</a>
|
<a href="#security-settings">Security</a>
|
||||||
<li>
|
<li>
|
||||||
<a href="/registrar#contact-settings">Contact</a>
|
<a href="#contact-settings">Contact</a>
|
||||||
</ul>
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="/registrar#contact-us">Contact us</a>
|
<a href="#contact-us">Contact us</a>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{/template}
|
{/template}
|
||||||
|
@ -130,19 +130,29 @@
|
||||||
{@param logoutUrl: string} /** Generated URL for logging out of Google. */
|
{@param logoutUrl: string} /** Generated URL for logging out of Google. */
|
||||||
{@param logoFilename: string}
|
{@param logoFilename: string}
|
||||||
{@param productName: string}
|
{@param productName: string}
|
||||||
|
{@param? clientId: string}
|
||||||
{call registry.soy.console.header}
|
{call registry.soy.console.header}
|
||||||
{param app: 'registrar' /}
|
{param app: 'registrar' /}
|
||||||
{param subtitle: 'Please Login' /}
|
{param subtitle: 'Not Authorized' /}
|
||||||
{/call}
|
{/call}
|
||||||
<div class="{css('whoAreYou')}">
|
<div class="{css('whoAreYou')}">
|
||||||
<a class="{css('logo')}" href="/registrar">
|
<a class="{css('logo')}" href="/registrar">
|
||||||
<img src="/assets/images/{$logoFilename}" alt="{$productName}">
|
<img src="/assets/images/{$logoFilename}" alt="{$productName}">
|
||||||
</a>
|
</a>
|
||||||
<h1>You need permission</h1>
|
<h1>You need permission</h1>
|
||||||
<p>
|
{if isNonnull($clientId)} // A clientId was given - but we don't have access to it
|
||||||
The account you are logged in as is not associated with {$productName}.
|
<p>
|
||||||
Please contact your customer service representative or
|
The account you are logged in as is not associated with the registrar
|
||||||
switch to an account associated with {$productName}.
|
{sp}{$clientId}. Please contact your customer service representative or
|
||||||
|
switch to an account associated with {$clientId}. Alternatively, click
|
||||||
|
{sp}<a href="?">here</a> to find a registrar associated with your
|
||||||
|
account.
|
||||||
|
{else}
|
||||||
|
<p>
|
||||||
|
The account you are logged in as is not associated with {$productName}.
|
||||||
|
Please contact your customer service representative or
|
||||||
|
switch to an account associated with {$productName}.
|
||||||
|
{/if}
|
||||||
<p>
|
<p>
|
||||||
You are signed in as <strong>{$username}</strong>.
|
You are signed in as <strong>{$username}</strong>.
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -61,7 +61,7 @@ function setUp() {
|
||||||
});
|
});
|
||||||
registry.registrar.ConsoleTestUtil.setup(test);
|
registry.registrar.ConsoleTestUtil.setup(test);
|
||||||
var regNavlist = $('reg-navlist');
|
var regNavlist = $('reg-navlist');
|
||||||
var active = regNavlist.querySelector('a[href="/registrar#contact-us"]');
|
var active = regNavlist.querySelector('a[href="#contact-us"]');
|
||||||
assertTrue(active != null);
|
assertTrue(active != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package google.registry.ui.server.registrar;
|
||||||
import static com.google.common.net.HttpHeaders.LOCATION;
|
import static com.google.common.net.HttpHeaders.LOCATION;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
||||||
|
import static google.registry.ui.server.registrar.SessionUtils.AccessType.READ_ONLY;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
|
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -34,6 +35,7 @@ import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.testing.FakeResponse;
|
import google.registry.testing.FakeResponse;
|
||||||
import google.registry.testing.UserInfo;
|
import google.registry.testing.UserInfo;
|
||||||
|
import java.util.Optional;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
|
@ -72,10 +74,11 @@ 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.paramClientId = Optional.empty();
|
||||||
AuthResult authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
|
AuthResult authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false));
|
||||||
action.authResult = authResult;
|
action.authResult = authResult;
|
||||||
when(sessionUtils.guessClientIdForUser(authResult)).thenReturn("TheRegistrar");
|
when(sessionUtils.guessClientIdForUser(authResult)).thenReturn("TheRegistrar");
|
||||||
when(sessionUtils.getRegistrarForUser("TheRegistrar", authResult))
|
when(sessionUtils.getRegistrarForUser("TheRegistrar", READ_ONLY, authResult))
|
||||||
.thenReturn(loadRegistrar("TheRegistrar"));
|
.thenReturn(loadRegistrar("TheRegistrar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +120,7 @@ public class ConsoleUiActionTest {
|
||||||
.thenThrow(new ForbiddenException("forbidden"));
|
.thenThrow(new ForbiddenException("forbidden"));
|
||||||
action.run();
|
action.run();
|
||||||
assertThat(response.getPayload()).contains("<h1>You need permission</h1>");
|
assertThat(response.getPayload()).contains("<h1>You need permission</h1>");
|
||||||
|
assertThat(response.getPayload()).contains("not associated with Nomulus.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -136,4 +140,24 @@ public class ConsoleUiActionTest {
|
||||||
assertThat(response.getStatus()).isEqualTo(SC_MOVED_TEMPORARILY);
|
assertThat(response.getStatus()).isEqualTo(SC_MOVED_TEMPORARILY);
|
||||||
assertThat(response.getHeaders().get(LOCATION)).isEqualTo("/");
|
assertThat(response.getHeaders().get(LOCATION)).isEqualTo("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSettingClientId_notAllowed_showsNeedPermissionPage() {
|
||||||
|
action.paramClientId = Optional.of("OtherClientId");
|
||||||
|
when(sessionUtils.getRegistrarForUser("OtherClientId", READ_ONLY, action.authResult))
|
||||||
|
.thenThrow(new ForbiddenException("forbidden"));
|
||||||
|
action.run();
|
||||||
|
assertThat(response.getPayload()).contains("<h1>You need permission</h1>");
|
||||||
|
assertThat(response.getPayload()).contains("not associated with the registrar OtherClientId.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSettingClientId_allowed_showsRegistrarConsole() {
|
||||||
|
action.paramClientId = Optional.of("OtherClientId");
|
||||||
|
when(sessionUtils.getRegistrarForUser("OtherClientId", READ_ONLY, action.authResult))
|
||||||
|
.thenReturn(loadRegistrar("TheRegistrar"));
|
||||||
|
action.run();
|
||||||
|
assertThat(response.getPayload()).contains("Registrar Console");
|
||||||
|
assertThat(response.getPayload()).contains("reg-content-and-footer");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,19 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
|
||||||
|
|
||||||
/** This is the default read test for the registrar settings actions. */
|
/** This is the default read test for the registrar settings actions. */
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_readRegistrarInfo_authorized() {
|
public void testSuccess_readRegistrarInfo_authorizedReadWrite() {
|
||||||
|
Map<String, Object> response = action.handleJsonRequest(ImmutableMap.of("id", CLIENT_ID));
|
||||||
|
assertThat(response)
|
||||||
|
.containsExactly(
|
||||||
|
"status", "SUCCESS",
|
||||||
|
"message", "Success",
|
||||||
|
"results", asList(loadRegistrar(CLIENT_ID).toJsonMap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This is the default read test for the registrar settings actions. */
|
||||||
|
@Test
|
||||||
|
public void testSuccess_readRegistrarInfo_authorizedReadOnly() {
|
||||||
|
action.authResult = USER_READ_ONLY;
|
||||||
Map<String, Object> response = action.handleJsonRequest(ImmutableMap.of("id", CLIENT_ID));
|
Map<String, Object> response = action.handleJsonRequest(ImmutableMap.of("id", CLIENT_ID));
|
||||||
assertThat(response)
|
assertThat(response)
|
||||||
.containsExactly(
|
.containsExactly(
|
||||||
|
@ -144,7 +156,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFailute_updateRegistrarInfo_notAuthorized() {
|
public void testFailure_updateRegistrarInfo_notAuthorized() {
|
||||||
action.authResult = USER_UNAUTHORIZED;
|
action.authResult = USER_UNAUTHORIZED;
|
||||||
Map<String, Object> response = action.handleJsonRequest(ImmutableMap.of(
|
Map<String, Object> response = action.handleJsonRequest(ImmutableMap.of(
|
||||||
"op", "update",
|
"op", "update",
|
||||||
|
@ -157,6 +169,20 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
|
||||||
assertNoTasksEnqueued("sheet");
|
assertNoTasksEnqueued("sheet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_updateRegistrarInfo_readOnlyAccess() {
|
||||||
|
action.authResult = USER_READ_ONLY;
|
||||||
|
Map<String, Object> response = action.handleJsonRequest(ImmutableMap.of(
|
||||||
|
"op", "update",
|
||||||
|
"id", CLIENT_ID,
|
||||||
|
"args", ImmutableMap.of("lastUpdateTime", getLastUpdateTime())));
|
||||||
|
assertThat(response).containsExactly(
|
||||||
|
"status", "ERROR",
|
||||||
|
"results", ImmutableList.of(),
|
||||||
|
"message", "forbidden test error");
|
||||||
|
assertNoTasksEnqueued("sheet");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdate_badEmail_errorEmailField() {
|
public void testUpdate_badEmail_errorEmailField() {
|
||||||
Map<String, Object> response = action.handleJsonRequest(ImmutableMap.of(
|
Map<String, Object> response = action.handleJsonRequest(ImmutableMap.of(
|
||||||
|
|
|
@ -18,6 +18,8 @@ import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailAddres
|
||||||
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailDisplayName;
|
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailDisplayName;
|
||||||
import static google.registry.security.JsonHttpTestUtils.createJsonPayload;
|
import static google.registry.security.JsonHttpTestUtils.createJsonPayload;
|
||||||
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
||||||
|
import static google.registry.ui.server.registrar.SessionUtils.AccessType.READ_ONLY;
|
||||||
|
import static google.registry.ui.server.registrar.SessionUtils.AccessType.READ_WRITE;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.google.appengine.api.users.User;
|
import com.google.appengine.api.users.User;
|
||||||
|
@ -58,12 +60,14 @@ public class RegistrarSettingsActionTestCase {
|
||||||
|
|
||||||
static final String CLIENT_ID = "TheRegistrar";
|
static final String CLIENT_ID = "TheRegistrar";
|
||||||
|
|
||||||
static final AuthResult USER_AUTHORIZED =
|
static final AuthResult USER_READ_WRITE =
|
||||||
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(new User("user", "gmail.com"), false));
|
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(new User("rw", "gmail.com"), false));
|
||||||
|
|
||||||
|
static final AuthResult USER_READ_ONLY =
|
||||||
|
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(new User("ro", "gmail.com"), false));
|
||||||
|
|
||||||
static final AuthResult USER_UNAUTHORIZED =
|
static final AuthResult USER_UNAUTHORIZED =
|
||||||
AuthResult.create(
|
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(new User("evil", "gmail.com"), false));
|
||||||
AuthLevel.USER, UserAuthInfo.create(new User("unauthorized", "gmail.com"), false));
|
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public final AppEngineRule appEngine =
|
public final AppEngineRule appEngine =
|
||||||
|
@ -90,7 +94,9 @@ public class RegistrarSettingsActionTestCase {
|
||||||
action.sessionUtils = sessionUtils;
|
action.sessionUtils = sessionUtils;
|
||||||
action.appEngineServiceUtils = appEngineServiceUtils;
|
action.appEngineServiceUtils = appEngineServiceUtils;
|
||||||
when(appEngineServiceUtils.getCurrentVersionHostname("backend")).thenReturn("backend.hostname");
|
when(appEngineServiceUtils.getCurrentVersionHostname("backend")).thenReturn("backend.hostname");
|
||||||
action.authResult = USER_AUTHORIZED;
|
// We set the default user to one with read-write access, as that's the most common test case.
|
||||||
|
// When we want to specifically check read-only or unauthorized, we can switch the user here.
|
||||||
|
action.authResult = USER_READ_WRITE;
|
||||||
action.jsonActionRunner = new JsonActionRunner(
|
action.jsonActionRunner = new JsonActionRunner(
|
||||||
ImmutableMap.of(), new JsonResponse(new ResponseImpl(rsp)));
|
ImmutableMap.of(), new JsonResponse(new ResponseImpl(rsp)));
|
||||||
action.registrarChangesNotificationEmailAddresses = ImmutableList.of(
|
action.registrarChangesNotificationEmailAddresses = ImmutableList.of(
|
||||||
|
@ -109,9 +115,19 @@ public class RegistrarSettingsActionTestCase {
|
||||||
// the result is out of date after mutations.
|
// the result is out of date after mutations.
|
||||||
// (for example, if someone wants to change the registrar to prepare for a test, the function
|
// (for example, if someone wants to change the registrar to prepare for a test, the function
|
||||||
// would still return the old value)
|
// would still return the old value)
|
||||||
when(sessionUtils.getRegistrarForUser(CLIENT_ID, USER_AUTHORIZED))
|
when(sessionUtils.getRegistrarForUser(CLIENT_ID, READ_ONLY, USER_READ_WRITE))
|
||||||
.thenAnswer(x -> loadRegistrar(CLIENT_ID));
|
.thenAnswer(x -> loadRegistrar(CLIENT_ID));
|
||||||
when(sessionUtils.getRegistrarForUser(CLIENT_ID, USER_UNAUTHORIZED))
|
when(sessionUtils.getRegistrarForUser(CLIENT_ID, READ_WRITE, USER_READ_WRITE))
|
||||||
|
.thenAnswer(x -> loadRegistrar(CLIENT_ID));
|
||||||
|
|
||||||
|
when(sessionUtils.getRegistrarForUser(CLIENT_ID, READ_ONLY, USER_READ_ONLY))
|
||||||
|
.thenAnswer(x -> loadRegistrar(CLIENT_ID));
|
||||||
|
when(sessionUtils.getRegistrarForUser(CLIENT_ID, READ_WRITE, USER_READ_ONLY))
|
||||||
|
.thenThrow(new ForbiddenException("forbidden test error"));
|
||||||
|
|
||||||
|
when(sessionUtils.getRegistrarForUser(CLIENT_ID, READ_ONLY, USER_UNAUTHORIZED))
|
||||||
|
.thenThrow(new ForbiddenException("forbidden test error"));
|
||||||
|
when(sessionUtils.getRegistrarForUser(CLIENT_ID, READ_WRITE, USER_UNAUTHORIZED))
|
||||||
.thenThrow(new ForbiddenException("forbidden test error"));
|
.thenThrow(new ForbiddenException("forbidden test error"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
||||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||||
import static google.registry.testing.LogsSubject.assertAboutLogs;
|
import static google.registry.testing.LogsSubject.assertAboutLogs;
|
||||||
|
import static google.registry.ui.server.registrar.SessionUtils.AccessType.READ_ONLY;
|
||||||
|
import static google.registry.ui.server.registrar.SessionUtils.AccessType.READ_WRITE;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import com.google.appengine.api.users.User;
|
import com.google.appengine.api.users.User;
|
||||||
|
@ -32,6 +34,7 @@ import google.registry.request.auth.AuthResult;
|
||||||
import google.registry.request.auth.UserAuthInfo;
|
import google.registry.request.auth.UserAuthInfo;
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.testing.InjectRule;
|
import google.registry.testing.InjectRule;
|
||||||
|
import google.registry.ui.server.registrar.SessionUtils.AccessType;
|
||||||
import java.util.logging.Level;
|
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;
|
||||||
|
@ -96,66 +99,121 @@ public class SessionUtilsTest {
|
||||||
|
|
||||||
/** Fail loading registrar if user doesn't have access to it. */
|
/** Fail loading registrar if user doesn't have access to it. */
|
||||||
@Test
|
@Test
|
||||||
public void testGetRegistrarForUser_noAccess_isNotAdmin() {
|
public void testGetRegistrarForUser_readOnly_noAccess_isNotAdmin() {
|
||||||
expectGetRegistrarFailure(
|
expectGetRegistrarFailure(
|
||||||
DEFAULT_CLIENT_ID,
|
DEFAULT_CLIENT_ID,
|
||||||
|
READ_ONLY,
|
||||||
UNAUTHORIZED_USER,
|
UNAUTHORIZED_USER,
|
||||||
"User {user} doesn't have access to registrar {clientId}");
|
"User {user} doesn't have READ_ONLY access to registrar {clientId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fail loading registrar if user doesn't have access to it. */
|
||||||
|
@Test
|
||||||
|
public void testGetRegistrarForUser_readWrite_noAccess_isNotAdmin() {
|
||||||
|
expectGetRegistrarFailure(
|
||||||
|
DEFAULT_CLIENT_ID,
|
||||||
|
READ_WRITE,
|
||||||
|
UNAUTHORIZED_USER,
|
||||||
|
"User {user} doesn't have READ_WRITE access to registrar {clientId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fail loading registrar if there's no user associated with the request. */
|
/** Fail loading registrar if there's no user associated with the request. */
|
||||||
@Test
|
@Test
|
||||||
public void testGetRegistrarForUser_noUser() {
|
public void testGetRegistrarForUser_readOnly_noUser() {
|
||||||
expectGetRegistrarFailure(DEFAULT_CLIENT_ID, NO_USER, "Not logged in");
|
expectGetRegistrarFailure(DEFAULT_CLIENT_ID, READ_ONLY, NO_USER, "Not logged in");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Succeed loading registrar if user has access to it. */
|
/** Fail loading registrar if there's no user associated with the request. */
|
||||||
@Test
|
@Test
|
||||||
public void testGetRegistrarForUser_hasAccess_isNotAdmin() {
|
public void testGetRegistrarForUser_readWrite_noUser() {
|
||||||
expectGetRegistrarSuccess(AUTHORIZED_USER, "User {user} has access to registrar {clientId}");
|
expectGetRegistrarFailure(DEFAULT_CLIENT_ID, READ_WRITE, NO_USER, "Not logged in");
|
||||||
|
|
||||||
|
assertAboutLogs().that(testLogHandler).hasNoLogsAtLevel(Level.INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Succeed loading registrar if admin. */
|
/** Succeed loading registrar in read-only mode if user has access to it. */
|
||||||
@Test
|
@Test
|
||||||
public void testGetRegistrarForUser_hasAccess_isAdmin() {
|
public void testGetRegistrarForUser_readOnly_hasAccess_isNotAdmin() {
|
||||||
expectGetRegistrarSuccess(AUTHORIZED_ADMIN, "User {user} has access to registrar {clientId}");
|
expectGetRegistrarSuccess(
|
||||||
|
AUTHORIZED_USER, READ_ONLY, "User {user} has access to registrar {clientId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fail loading registrar if admin isn't on the approved contacts list. */
|
/** Succeed loading registrar in read-write mode if user has access to it. */
|
||||||
@Test
|
@Test
|
||||||
public void testGetRegistrarForUser_noAccess_isAdmin() {
|
public void testGetRegistrarForUser_readWrite_hasAccess_isNotAdmin() {
|
||||||
|
expectGetRegistrarSuccess(
|
||||||
|
AUTHORIZED_USER, READ_WRITE, "User {user} has access to registrar {clientId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Succeed loading registrar in read-only mode if admin with access. */
|
||||||
|
@Test
|
||||||
|
public void testGetRegistrarForUser_readOnly_hasAccess_isAdmin() {
|
||||||
|
expectGetRegistrarSuccess(
|
||||||
|
AUTHORIZED_ADMIN, READ_ONLY, "User {user} has access to registrar {clientId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Succeed loading registrar in read-write mode if admin with access. */
|
||||||
|
@Test
|
||||||
|
public void testGetRegistrarForUser_readWrite_hasAccess_isAdmin() {
|
||||||
|
expectGetRegistrarSuccess(
|
||||||
|
AUTHORIZED_ADMIN, READ_WRITE, "User {user} has access to registrar {clientId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Succeed loading registrar for read-only when admin isn't on the approved contacts list. */
|
||||||
|
@Test
|
||||||
|
public void testGetRegistrarForUser_readOnly_noAccess_isAdmin() {
|
||||||
|
expectGetRegistrarSuccess(
|
||||||
|
UNAUTHORIZED_ADMIN,
|
||||||
|
READ_ONLY,
|
||||||
|
"Allowing admin {user} read-only access to registrar {clientId}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fail loading registrar for read-write when admin isn't on the approved contacts list. */
|
||||||
|
@Test
|
||||||
|
public void testGetRegistrarForUser_readWrite_noAccess_isAdmin() {
|
||||||
expectGetRegistrarFailure(
|
expectGetRegistrarFailure(
|
||||||
DEFAULT_CLIENT_ID,
|
DEFAULT_CLIENT_ID,
|
||||||
|
READ_WRITE,
|
||||||
UNAUTHORIZED_ADMIN,
|
UNAUTHORIZED_ADMIN,
|
||||||
"User {user} doesn't have access to registrar {clientId}");
|
"User {user} doesn't have READ_WRITE access to registrar {clientId}");
|
||||||
}
|
|
||||||
|
|
||||||
/** Succeed loading registrarAdmin even if unauthorized admin. */
|
|
||||||
@Test
|
|
||||||
public void testGetRegistrarForUser_registrarAdminClientId() {
|
|
||||||
sessionUtils.registryAdminClientId = DEFAULT_CLIENT_ID;
|
|
||||||
expectGetRegistrarSuccess(
|
|
||||||
UNAUTHORIZED_ADMIN, "Allowing admin {user} access to registrar {clientId}.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fail loading registrar even if admin, if registrar doesn't exist. */
|
/** Fail loading registrar even if admin, if registrar doesn't exist. */
|
||||||
@Test
|
@Test
|
||||||
public void testGetRegistrarForUser_doesntExist_isAdmin() {
|
public void testGetRegistrarForUser_readOnly_doesntExist_isAdmin() {
|
||||||
expectGetRegistrarFailure("BadClientId", UNAUTHORIZED_ADMIN, "Registrar {clientId} not found");
|
expectGetRegistrarFailure(
|
||||||
|
"BadClientId",
|
||||||
|
READ_ONLY,
|
||||||
|
AUTHORIZED_ADMIN,
|
||||||
|
"Registrar {clientId} not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expectGetRegistrarSuccess(AuthResult authResult, String message) {
|
/** Fail loading registrar even if admin, if registrar doesn't exist. */
|
||||||
assertThat(sessionUtils.getRegistrarForUser(DEFAULT_CLIENT_ID, authResult)).isNotNull();
|
@Test
|
||||||
|
public void testGetRegistrarForUser_readWrite_doesntExist_isAdmin() {
|
||||||
|
expectGetRegistrarFailure(
|
||||||
|
"BadClientId",
|
||||||
|
READ_WRITE,
|
||||||
|
AUTHORIZED_ADMIN,
|
||||||
|
"Registrar {clientId} not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectGetRegistrarSuccess(
|
||||||
|
AuthResult authResult, AccessType accessType, String message) {
|
||||||
|
assertThat(sessionUtils.getRegistrarForUser(DEFAULT_CLIENT_ID, accessType, authResult))
|
||||||
|
.isNotNull();
|
||||||
assertAboutLogs()
|
assertAboutLogs()
|
||||||
.that(testLogHandler)
|
.that(testLogHandler)
|
||||||
.hasLogAtLevelWithMessage(
|
.hasLogAtLevelWithMessage(
|
||||||
Level.INFO, formatMessage(message, authResult, DEFAULT_CLIENT_ID));
|
Level.INFO, formatMessage(message, authResult, DEFAULT_CLIENT_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expectGetRegistrarFailure(String clientId, AuthResult authResult, String message) {
|
private void expectGetRegistrarFailure(
|
||||||
|
String clientId, AccessType accessType, AuthResult authResult, String message) {
|
||||||
ForbiddenException exception =
|
ForbiddenException exception =
|
||||||
assertThrows(
|
assertThrows(
|
||||||
ForbiddenException.class, () -> sessionUtils.getRegistrarForUser(clientId, authResult));
|
ForbiddenException.class,
|
||||||
|
() -> sessionUtils.getRegistrarForUser(clientId, accessType, authResult));
|
||||||
|
|
||||||
assertThat(exception).hasMessageThat().contains(formatMessage(message, authResult, clientId));
|
assertThat(exception).hasMessageThat().contains(formatMessage(message, authResult, clientId));
|
||||||
assertAboutLogs().that(testLogHandler).hasNoLogsAtLevel(Level.INFO);
|
assertAboutLogs().that(testLogHandler).hasNoLogsAtLevel(Level.INFO);
|
||||||
|
@ -221,7 +279,7 @@ public class SessionUtilsTest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If an admin is not associated with a registrar and the configured adminClientId points to a
|
* If an admin is not associated with a registrar and the configured adminClientId points to a
|
||||||
* non-existent registrar, we still guess it (we will later failing loading the registrar).
|
* non-existent registrar, we still guess it (we will later fail loading the registrar).
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGuessClientIdForUser_noAccess_isAdmin_adminClientIdInvalid() {
|
public void testGuessClientIdForUser_noAccess_isAdmin_adminClientIdInvalid() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue