Inject RdapAuthorization

We currently create it from injected arguments, and pass it to every function.

Instead, we just create a provider for it and inject it where needed.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=247072517
This commit is contained in:
guyben 2019-05-07 12:48:54 -07:00 committed by jianglai
parent ce7456ea66
commit 3b8a8892bb
10 changed files with 70 additions and 102 deletions

View file

@ -25,7 +25,6 @@ import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import com.google.gson.Gson;
@ -50,9 +49,6 @@ import google.registry.request.Parameter;
import google.registry.request.RequestMethod;
import google.registry.request.RequestPath;
import google.registry.request.Response;
import google.registry.request.auth.AuthResult;
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
import google.registry.request.auth.UserAuthInfo;
import google.registry.util.Clock;
import java.net.URI;
import java.net.URISyntaxException;
@ -93,8 +89,7 @@ public abstract class RdapActionBase implements Runnable {
@Inject Clock clock;
@Inject @RequestMethod Action.Method requestMethod;
@Inject @RequestPath String requestPath;
@Inject AuthResult authResult;
@Inject AuthenticatedRegistrarAccessor registrarAccessor;
@Inject RdapAuthorization rdapAuthorization;
@Inject RdapJsonFormatter rdapJsonFormatter;
@Inject @Parameter("registrar") Optional<String> registrarParam;
@Inject @Parameter("includeDeleted") Optional<Boolean> includeDeletedParam;
@ -145,7 +140,7 @@ public abstract class RdapActionBase implements Runnable {
public void run() {
metricInformationBuilder.setIncludeDeleted(includeDeletedParam.orElse(false));
metricInformationBuilder.setRegistrarSpecified(registrarParam.isPresent());
metricInformationBuilder.setRole(getAuthorization().role());
metricInformationBuilder.setRole(rdapAuthorization.role());
metricInformationBuilder.setRequestMethod(requestMethod);
metricInformationBuilder.setEndpointType(endpointType);
try {
@ -211,22 +206,6 @@ public abstract class RdapActionBase implements Runnable {
response.setPayload(gson.toJson(topLevelObject.toJson()));
}
RdapAuthorization getAuthorization() {
if (!authResult.userAuthInfo().isPresent()) {
return RdapAuthorization.PUBLIC_AUTHORIZATION;
}
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
if (userAuthInfo.isUserAdmin()) {
return RdapAuthorization.ADMINISTRATOR_AUTHORIZATION;
}
ImmutableSet<String> clientIds = registrarAccessor.getAllClientIdWithRoles().keySet();
if (clientIds.isEmpty()) {
logger.atWarning().log("Couldn't find registrar for User %s.", authResult.userIdForLogging());
return RdapAuthorization.PUBLIC_AUTHORIZATION;
}
return RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, clientIds);
}
/** Returns the registrar on which results should be filtered, or absent(). */
Optional<String> getDesiredRegistrar() {
return registrarParam;
@ -247,14 +226,10 @@ public abstract class RdapActionBase implements Runnable {
if (!includeDeletedParam.orElse(false)) {
return false;
}
if (!authResult.userAuthInfo().isPresent()) {
return false;
}
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
if (userAuthInfo.isUserAdmin()) {
return true;
}
return !registrarAccessor.getAllClientIdWithRoles().isEmpty();
// Return true if we *might* be allowed to view any deleted info, meaning we're either an admin
// or have access to at least one registrar's data
return rdapAuthorization.role() == RdapAuthorization.Role.ADMINISTRATOR
|| !rdapAuthorization.clientIds().isEmpty();
}
DeletedItemHandling getDeletedItemHandling() {
@ -270,7 +245,7 @@ public abstract class RdapActionBase implements Runnable {
boolean isAuthorized(EppResource eppResource, DateTime now) {
return now.isBefore(eppResource.getDeletionTime())
|| (shouldIncludeDeleted()
&& getAuthorization()
&& rdapAuthorization
.isAuthorizedForClientId(eppResource.getPersistedCurrentSponsorClientId()));
}
@ -311,7 +286,7 @@ public abstract class RdapActionBase implements Runnable {
boolean shouldBeVisible(Registrar registrar) {
return (registrar.isLiveAndPubliclyVisible()
|| (shouldIncludeDeleted()
&& getAuthorization().isAuthorizedForClientId(registrar.getClientId())))
&& rdapAuthorization.isAuthorizedForClientId(registrar.getClientId())))
&& (!registrarParam.isPresent() || registrarParam.get().equals(registrar.getClientId()));
}

View file

@ -69,7 +69,6 @@ public class RdapDomainAction extends RdapActionBase {
domainBase.get(),
rdapWhoisServer,
now,
OutputDataType.FULL,
getAuthorization());
OutputDataType.FULL);
}
}

View file

@ -502,13 +502,11 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
DomainSearchResponse.Builder builder =
DomainSearchResponse.builder()
.setIncompletenessWarningType(incompletenessWarningType);
RdapAuthorization authorization = getAuthorization();
Optional<String> newCursor = Optional.empty();
for (DomainBase domain : Iterables.limit(domains, rdapResultSetMaxSize)) {
newCursor = Optional.of(domain.getFullyQualifiedDomainName());
builder.domainSearchResultsBuilder().add(
rdapJsonFormatter.makeRdapJsonForDomain(
domain, rdapWhoisServer, now, outputDataType, authorization));
rdapJsonFormatter.makeRdapJsonForDomain(domain, rdapWhoisServer, now, outputDataType));
}
if (rdapResultSetMaxSize < domains.size()) {
builder.setNextPageUri(createNavigationUri(newCursor.get()));

View file

@ -79,8 +79,7 @@ public class RdapEntityAction extends RdapActionBase {
Optional.empty(),
rdapWhoisServer,
now,
OutputDataType.FULL,
getAuthorization());
OutputDataType.FULL);
}
}
Long ianaIdentifier = Longs.tryParse(pathSearchString);

View file

@ -267,8 +267,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
if (subtype == Subtype.REGISTRARS) {
resultSet = RdapResultSet.create(ImmutableList.of());
} else {
RdapAuthorization authorization = getAuthorization();
if ((authorization.role() == RdapAuthorization.Role.PUBLIC)
if ((rdapAuthorization.role() == RdapAuthorization.Role.PUBLIC)
|| (cursorType == CursorType.REGISTRAR)) {
resultSet = RdapResultSet.create(ImmutableList.of());
} else {
@ -280,8 +279,8 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
cursorQueryString, // if we get this far, and there's a cursor, it must be a contact
DeletedItemHandling.EXCLUDE,
rdapResultSetMaxSize + 1);
if (authorization.role() != RdapAuthorization.Role.ADMINISTRATOR) {
query = query.filter("currentSponsorClientId in", authorization.clientIds());
if (rdapAuthorization.role() != RdapAuthorization.Role.ADMINISTRATOR) {
query = query.filter("currentSponsorClientId in", rdapAuthorization.clientIds());
}
resultSet = getMatchingResources(query, false, now, rdapResultSetMaxSize + 1);
}
@ -463,7 +462,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
// There can be more results than our max size, partially because we have two pools to draw from
// (contacts and registrars), and partially because we try to fetch one more than the max size,
// so we can tell whether to display the truncation notification.
RdapAuthorization authorization = getAuthorization();
//
// Each time we add a contact or registrar to the output data set, remember what the appropriate
// cursor would be if it were the last item returned. When we stop adding items, the last cursor
// value we remembered will be the right one to pass back.
@ -479,8 +478,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
Optional.empty(),
rdapWhoisServer,
now,
outputDataType,
authorization));
outputDataType));
newCursor =
Optional.of(
CONTACT_CURSOR_PREFIX

View file

@ -91,6 +91,7 @@ public class RdapJsonFormatter {
@Inject @Config("rdapTos") ImmutableList<String> rdapTos;
@Inject @Config("rdapTosStaticUrl") @Nullable String rdapTosStaticUrl;
@Inject @FullServletPath String fullServletPath;
@Inject RdapAuthorization rdapAuthorization;
@Inject RdapJsonFormatter() {}
/**
@ -216,15 +217,12 @@ public class RdapJsonFormatter {
* port43 field; if null, port43 is not added to the object
* @param now the as-date
* @param outputDataType whether to generate full or summary data
* @param authorization the authorization level of the request; if not authorized for the
* registrar owning the domain, no contact information is included
*/
RdapDomain makeRdapJsonForDomain(
DomainBase domainBase,
@Nullable String whoisServer,
DateTime now,
OutputDataType outputDataType,
RdapAuthorization authorization) {
OutputDataType outputDataType) {
RdapDomain.Builder builder = RdapDomain.builder();
// RDAP Response Profile 15feb19 section 2.2:
// The domain handle MUST be the ROID
@ -238,7 +236,7 @@ public class RdapJsonFormatter {
builder.linksBuilder().add(
makeSelfLink("domain", domainBase.getFullyQualifiedDomainName()));
boolean displayContacts =
authorization.isAuthorizedForClientId(domainBase.getCurrentSponsorClientId());
rdapAuthorization.isAuthorizedForClientId(domainBase.getCurrentSponsorClientId());
// If we are outputting all data (not just summary data), also add information about hosts,
// contacts and events (history entries). If we are outputting summary data, instead add a
// remark indicating that fact.
@ -271,8 +269,7 @@ public class RdapJsonFormatter {
Optional.of(designatedContact.getType()),
null,
now,
outputDataType,
authorization))
outputDataType))
.forEach(builder.entitiesBuilder()::add);
}
builder
@ -394,18 +391,15 @@ public class RdapJsonFormatter {
* port43 field; if null, port43 is not added to the object
* @param now the as-date
* @param outputDataType whether to generate full or summary data
* @param authorization the authorization level of the request; personal contact data is only
* shown if the contact is owned by a registrar for which the request is authorized
*/
RdapEntity makeRdapJsonForContact(
ContactResource contactResource,
Optional<DesignatedContact.Type> contactType,
@Nullable String whoisServer,
DateTime now,
OutputDataType outputDataType,
RdapAuthorization authorization) {
OutputDataType outputDataType) {
boolean isAuthorized =
authorization.isAuthorizedForClientId(contactResource.getCurrentSponsorClientId());
rdapAuthorization.isAuthorizedForClientId(contactResource.getCurrentSponsorClientId());
RdapEntity.Builder entityBuilder =
RdapEntity.builder()

View file

@ -14,10 +14,15 @@
package google.registry.rdap;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import dagger.Module;
import dagger.Provides;
import google.registry.request.Parameter;
import google.registry.request.RequestParameters;
import google.registry.request.auth.AuthResult;
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
import google.registry.request.auth.UserAuthInfo;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
@ -25,6 +30,8 @@ import javax.servlet.http.HttpServletRequest;
@Module
public final class RdapModule {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@Provides
@Parameter("name")
static Optional<String> provideName(HttpServletRequest req) {
@ -90,4 +97,22 @@ public final class RdapModule {
static Optional<String> provideCursor(HttpServletRequest req) {
return RequestParameters.extractOptionalParameter(req, "cursor");
}
@Provides
static RdapAuthorization provideRdapAuthorization(
AuthResult authResult, AuthenticatedRegistrarAccessor registrarAccessor) {
if (!authResult.userAuthInfo().isPresent()) {
return RdapAuthorization.PUBLIC_AUTHORIZATION;
}
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
if (userAuthInfo.isUserAdmin()) {
return RdapAuthorization.ADMINISTRATOR_AUTHORIZATION;
}
ImmutableSet<String> clientIds = registrarAccessor.getAllClientIdWithRoles().keySet();
if (clientIds.isEmpty()) {
logger.atWarning().log("Couldn't find registrar for User %s.", authResult.userIdForLogging());
return RdapAuthorization.PUBLIC_AUTHORIZATION;
}
return RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, clientIds);
}
}

View file

@ -20,20 +20,16 @@ import static google.registry.rdap.RdapAuthorization.Role.PUBLIC;
import static google.registry.rdap.RdapAuthorization.Role.REGISTRAR;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.HEAD;
import static google.registry.request.auth.AuthenticatedRegistrarAccessor.Role.OWNER;
import static google.registry.testing.TestDataHelper.loadFile;
import static org.mockito.Mockito.mock;
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 google.registry.model.ofy.Ofy;
import google.registry.request.Action;
import google.registry.request.Actions;
import google.registry.request.auth.AuthLevel;
import google.registry.request.auth.AuthResult;
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
import google.registry.request.auth.UserAuthInfo;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeClock;
@ -72,9 +68,6 @@ public class RdapActionBaseTestCase<A extends RdapActionBase> {
AuthLevel.USER,
UserAuthInfo.create(new User("rdap.admin@google.com", "gmail.com", "12345"), true));
protected final AuthenticatedRegistrarAccessor registrarAccessor =
mock(AuthenticatedRegistrarAccessor.class);
protected FakeResponse response = new FakeResponse();
protected final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01TZ"));
protected final RdapMetrics rdapMetrics = mock(RdapMetrics.class);
@ -94,9 +87,7 @@ public class RdapActionBaseTestCase<A extends RdapActionBase> {
public void baseSetUp() {
inject.setStaticField(Ofy.class, "clock", clock);
action = TypeUtils.instantiate(rdapActionClass);
action.registrarAccessor = registrarAccessor;
action.clock = clock;
action.authResult = AUTH_RESULT;
action.includeDeletedParam = Optional.empty();
action.registrarParam = Optional.empty();
action.formatOutputParam = Optional.empty();
@ -109,24 +100,20 @@ public class RdapActionBaseTestCase<A extends RdapActionBase> {
}
protected void login(String clientId) {
when(registrarAccessor.getAllClientIdWithRoles())
.thenReturn(ImmutableSetMultimap.of(clientId, OWNER));
action.authResult = AUTH_RESULT;
action.rdapAuthorization = RdapAuthorization.create(REGISTRAR, clientId);
action.rdapJsonFormatter.rdapAuthorization = action.rdapAuthorization;
metricRole = REGISTRAR;
}
protected void logout() {
when(registrarAccessor.getAllClientIdWithRoles()).thenReturn(ImmutableSetMultimap.of());
action.authResult = AUTH_RESULT;
action.rdapAuthorization = RdapAuthorization.PUBLIC_AUTHORIZATION;
action.rdapJsonFormatter.rdapAuthorization = action.rdapAuthorization;
metricRole = PUBLIC;
}
protected void loginAsAdmin() {
// when admin, we don't actually check what they have access to - so it doesn't matter what we
// return.
// null isn't actually a legal value, we just want to make sure it's never actually used.
when(registrarAccessor.getAllClientIdWithRoles()).thenReturn(null);
action.authResult = AUTH_RESULT_ADMIN;
action.rdapAuthorization = RdapAuthorization.ADMINISTRATOR_AUTHORIZATION;
action.rdapJsonFormatter.rdapAuthorization = action.rdapAuthorization;
metricRole = ADMINISTRATOR;
}

View file

@ -94,6 +94,8 @@ public class RdapJsonFormatterTest {
inject.setStaticField(Ofy.class, "clock", clock);
rdapJsonFormatter = RdapTestHelper.getTestRdapJsonFormatter();
rdapJsonFormatter.rdapAuthorization =
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar");
// Create the registrar in 1999, then update it in 2000.
clock.setTo(DateTime.parse("1999-01-01T00:00:00Z"));
@ -413,8 +415,7 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.REGISTRANT),
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_registrant.json"));
}
@ -428,14 +429,14 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.REGISTRANT),
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.SUMMARY,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.SUMMARY)
.toJson())
.isEqualTo(loadJson("rdapjson_registrant_summary.json"));
}
@Test
public void testRegistrant_loggedOut() {
rdapJsonFormatter.rdapAuthorization = RdapAuthorization.PUBLIC_AUTHORIZATION;
assertThat(
rdapJsonFormatter
.makeRdapJsonForContact(
@ -443,8 +444,7 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.REGISTRANT),
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.PUBLIC_AUTHORIZATION)
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_registrant_logged_out.json"));
}
@ -465,8 +465,7 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.REGISTRANT),
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_registrant.json"));
}
@ -480,8 +479,7 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.ADMIN),
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_admincontact.json"));
}
@ -495,8 +493,7 @@ public class RdapJsonFormatterTest {
Optional.of(DesignatedContact.Type.TECH),
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_techcontact.json"));
}
@ -510,8 +507,7 @@ public class RdapJsonFormatterTest {
Optional.empty(),
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_rolelesscontact.json"));
}
@ -525,8 +521,7 @@ public class RdapJsonFormatterTest {
Optional.empty(),
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_unlinkedcontact.json"));
}
@ -539,8 +534,7 @@ public class RdapJsonFormatterTest {
domainBaseFull,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_domain_full.json"));
}
@ -553,22 +547,21 @@ public class RdapJsonFormatterTest {
domainBaseFull,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.SUMMARY,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.SUMMARY)
.toJson())
.isEqualTo(loadJson("rdapjson_domain_summary.json"));
}
@Test
public void testDomain_logged_out() {
rdapJsonFormatter.rdapAuthorization = RdapAuthorization.PUBLIC_AUTHORIZATION;
assertThat(
rdapJsonFormatter
.makeRdapJsonForDomain(
domainBaseFull,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.PUBLIC_AUTHORIZATION)
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_domain_logged_out.json"));
}
@ -581,8 +574,7 @@ public class RdapJsonFormatterTest {
domainBaseNoNameserversNoTransfers,
WHOIS_SERVER,
clock.nowUtc(),
OutputDataType.FULL,
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar"))
OutputDataType.FULL)
.toJson())
.isEqualTo(loadJson("rdapjson_domain_no_nameservers.json"));
}

View file

@ -173,6 +173,7 @@ public class RdapTestHelper {
static RdapJsonFormatter getTestRdapJsonFormatter() {
RdapJsonFormatter rdapJsonFormatter = new RdapJsonFormatter();
rdapJsonFormatter.rdapAuthorization = RdapAuthorization.PUBLIC_AUTHORIZATION;
rdapJsonFormatter.fullServletPath = "https://example.tld/rdap/";
rdapJsonFormatter.rdapTos =
ImmutableList.of(