Allow registrars to be completely DISABLED

Disabled registrar cannot perform any actions via EPP and cannot log in to the
registrar web console.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=239606389
This commit is contained in:
mcilwain 2019-03-21 09:07:17 -07:00 committed by jianglai
parent e4ac18ec31
commit d7306652eb
15 changed files with 138 additions and 46 deletions

View file

@ -130,7 +130,7 @@ public class LoginFlow implements Flow {
throw e;
}
}
if (registrar.get().getState().equals(Registrar.State.PENDING)) {
if (!registrar.get().isLive()) {
throw new RegistrarAccountNotActiveException();
}
if (login.getNewPassword() != null) { // We don't support in-band password changes.

View file

@ -159,7 +159,13 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
* This is a suspended account which is disallowed from provisioning new domains, but can
* otherwise still perform other operations to continue operations.
*/
SUSPENDED;
SUSPENDED,
/**
* This registrar is completely disabled and cannot perform any EPP actions whatsoever, nor log
* in to the registrar console.
*/
DISABLED;
}
/** Regex for E.164 phone number format specified by {@code contact.xsd}. */

View file

@ -16,18 +16,22 @@ package google.registry.request.auth;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Streams.stream;
import static google.registry.model.ofy.ObjectifyService.ofy;
import com.google.appengine.api.users.User;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.flogger.FluentLogger;
import com.googlecode.objectify.Key;
import dagger.Lazy;
import google.registry.config.RegistryConfig.Config;
import google.registry.groups.GroupsConnection;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.Registrar.State;
import google.registry.model.registrar.RegistrarContact;
import java.util.Optional;
import javax.annotation.concurrent.Immutable;
@ -297,6 +301,9 @@ public class AuthenticatedRegistrarAccessor {
lazyGroupsConnection, user.getEmail(), gSuiteSupportGroupEmailAddress);
}
/**
* Returns a map of registrar client IDs to roles for all registrars that the user has access to.
*/
private static ImmutableSetMultimap<String, Role> createRoleMap(
AuthResult authResult,
boolean isAdmin,
@ -305,36 +312,36 @@ public class AuthenticatedRegistrarAccessor {
if (!authResult.userAuthInfo().isPresent()) {
return ImmutableSetMultimap.of();
}
UserAuthInfo userAuthInfo = authResult.userAuthInfo().get();
User user = userAuthInfo.user();
ImmutableSetMultimap.Builder<String, Role> builder = new ImmutableSetMultimap.Builder<>();
logger.atInfo().log("Checking registrar contacts for user ID %s", user.getUserId());
ofy()
.load()
.type(RegistrarContact.class)
.filter("gaeUserId", user.getUserId())
.forEach(contact -> builder.put(contact.getParent().getName(), Role.OWNER));
if (isAdmin && !Strings.isNullOrEmpty(registryAdminClientId)) {
builder.put(registryAdminClientId, Role.OWNER);
}
// Find all registrars that have a registrar contact with this user's ID.
ImmutableList<Key<Registrar>> accessibleClientIds =
stream(ofy().load().type(RegistrarContact.class).filter("gaeUserId", user.getUserId()))
.map(RegistrarContact::getParent)
.collect(toImmutableList());
// Filter out disabled registrars (note that pending registrars still allow console login).
ofy().load().keys(accessibleClientIds).values().stream()
.filter(registrar -> registrar.getState() != State.DISABLED)
.forEach(registrar -> builder.put(registrar.getClientId(), Role.OWNER));
// Admins have ADMIN access to all registrars, and also OWNER access to the registry registrar
// and all non-REAL or non-live registrars.
if (isAdmin) {
// Admins have ADMIN access to all registrars, and OWNER access to all non-REAL registrars
ofy()
.load()
.type(Registrar.class)
.forEach(registrar -> {
if (registrar.getType() != Registrar.Type.REAL
|| registrar.getState() == Registrar.State.PENDING) {
builder.put(registrar.getClientId(), Role.OWNER);
}
builder.put(registrar.getClientId(), Role.ADMIN);
});
.forEach(
registrar -> {
if (registrar.getType() != Registrar.Type.REAL
|| !registrar.isLive()
|| registrar.getClientId().equals(registryAdminClientId)) {
builder.put(registrar.getClientId(), Role.OWNER);
}
builder.put(registrar.getClientId(), Role.ADMIN);
});
}
return builder.build();

View file

@ -12,6 +12,7 @@ java_library(
"//java/google/registry/groups",
"//java/google/registry/model",
"//java/google/registry/security",
"//third_party/objectify:objectify-v4_1",
"@com_google_appengine_api_1_0_sdk",
"@com_google_auto_value",
"@com_google_code_findbugs_jsr305",

View file

@ -80,6 +80,7 @@ final class ValidateLoginCredentialsCommand implements CommandWithRemoteApi {
Registrar.loadByClientId(clientId), "Registrar %s not found", clientId);
new TlsCredentials(true, clientCertificateHash, Optional.of(clientIpAddress))
.validate(registrar, password);
checkState(!registrar.getState().equals(Registrar.State.PENDING), "Account pending");
checkState(
registrar.isLive(), "Registrar %s has non-live state: %s", clientId, registrar.getState());
}
}