mirror of
https://github.com/google/nomulus
synced 2026-01-05 13:07:04 +00:00
Create Users when setting up OT&E and Production registrars (#2488)
This commit is contained in:
@@ -96,6 +96,14 @@
|
|||||||
<max-retry-duration>3600s</max-retry-duration>
|
<max-retry-duration>3600s</max-retry-duration>
|
||||||
</queue>
|
</queue>
|
||||||
|
|
||||||
|
<!-- Queue for tasks that update membership in the console user group. -->
|
||||||
|
<queue>
|
||||||
|
<name>console-user-group-update</name>
|
||||||
|
<max-dispatches-per-second>1</max-dispatches-per-second>
|
||||||
|
<max-concurrent-dispatches>1</max-concurrent-dispatches>
|
||||||
|
<max-retry-duration>3600s</max-retry-duration>
|
||||||
|
</queue>
|
||||||
|
|
||||||
<!-- Queue for infrequent cron tasks (i.e. hourly or less often) that should retry three times on failure. -->
|
<!-- Queue for infrequent cron tasks (i.e. hourly or less often) that should retry three times on failure. -->
|
||||||
<queue>
|
<queue>
|
||||||
<name>retryable-cron-tasks</name>
|
<name>retryable-cron-tasks</name>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package google.registry.model;
|
|||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||||
|
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||||
import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
|
import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
|
||||||
import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
|
import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
|
||||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||||
@@ -28,19 +29,28 @@ import com.google.common.collect.ImmutableSet;
|
|||||||
import com.google.common.collect.ImmutableSortedMap;
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.collect.Streams;
|
import com.google.common.collect.Streams;
|
||||||
|
import google.registry.batch.CloudTasksUtils;
|
||||||
|
import google.registry.model.console.RegistrarRole;
|
||||||
|
import google.registry.model.console.User;
|
||||||
|
import google.registry.model.console.UserDao;
|
||||||
|
import google.registry.model.console.UserRoles;
|
||||||
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.model.registrar.RegistrarAddress;
|
import google.registry.model.registrar.RegistrarAddress;
|
||||||
import google.registry.model.registrar.RegistrarPoc;
|
|
||||||
import google.registry.model.tld.Tld;
|
import google.registry.model.tld.Tld;
|
||||||
import google.registry.model.tld.Tld.TldState;
|
import google.registry.model.tld.Tld.TldState;
|
||||||
import google.registry.model.tld.Tld.TldType;
|
import google.registry.model.tld.Tld.TldType;
|
||||||
import google.registry.model.tld.label.PremiumList;
|
import google.registry.model.tld.label.PremiumList;
|
||||||
import google.registry.model.tld.label.PremiumListDao;
|
import google.registry.model.tld.label.PremiumListDao;
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
|
import google.registry.tools.IamClient;
|
||||||
import google.registry.util.CidrAddressBlock;
|
import google.registry.util.CidrAddressBlock;
|
||||||
import google.registry.util.RegistryEnvironment;
|
import google.registry.util.RegistryEnvironment;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -75,8 +85,8 @@ public final class OteAccountBuilder {
|
|||||||
* Validation regex for registrar base client IDs (3-14 lowercase alphanumeric characters).
|
* Validation regex for registrar base client IDs (3-14 lowercase alphanumeric characters).
|
||||||
*
|
*
|
||||||
* <p>The base client ID is appended with numbers to create four different test registrar accounts
|
* <p>The base client ID is appended with numbers to create four different test registrar accounts
|
||||||
* (e.g. reg-1, reg-3, reg-4, reg-5). Registrar client IDs are of type clIDType in eppcom.xsd
|
* (e.g., reg-1, reg-3, reg-4, reg-5). Registrar client IDs are of type clIDType in eppcom.xsd
|
||||||
* which is limited to 16 characters, hence the limit of 14 here to account for the dash and
|
* that is limited to 16 characters, hence the limit of 14 here to account for the dash and
|
||||||
* numbers.
|
* numbers.
|
||||||
*
|
*
|
||||||
* <p>The base client ID is also used to generate the OT&E TLDs, hence the restriction to
|
* <p>The base client ID is also used to generate the OT&E TLDs, hence the restriction to
|
||||||
@@ -113,7 +123,7 @@ public final class OteAccountBuilder {
|
|||||||
* The default billing account map applied to all OT&E registrars.
|
* The default billing account map applied to all OT&E registrars.
|
||||||
*
|
*
|
||||||
* <p>This contains dummy values for USD and JPY so that OT&E registrars can be granted access
|
* <p>This contains dummy values for USD and JPY so that OT&E registrars can be granted access
|
||||||
* to all existing TLDs in sandbox. Note that OT&E is only on sandbox and thus these dummy
|
* to all existing TLDs in sandbox. Note that OT&E is only on sandbox, and thus these dummy
|
||||||
* values will never be used in production (the only environment where real invoicing takes
|
* values will never be used in production (the only environment where real invoicing takes
|
||||||
* place).
|
* place).
|
||||||
*/
|
*/
|
||||||
@@ -124,7 +134,7 @@ public final class OteAccountBuilder {
|
|||||||
private final Tld sunriseTld;
|
private final Tld sunriseTld;
|
||||||
private final Tld gaTld;
|
private final Tld gaTld;
|
||||||
private final Tld eapTld;
|
private final Tld eapTld;
|
||||||
private final ImmutableList.Builder<RegistrarPoc> contactsBuilder = new ImmutableList.Builder<>();
|
private final List<User> users = new ArrayList<>();
|
||||||
|
|
||||||
private ImmutableList<Registrar> registrars;
|
private ImmutableList<Registrar> registrars;
|
||||||
private boolean replaceExisting = false;
|
private boolean replaceExisting = false;
|
||||||
@@ -172,16 +182,28 @@ public final class OteAccountBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a RegistrarContact with Web Console access.
|
* Adds a {@link User} with Web Console access.
|
||||||
*
|
*
|
||||||
* <p>NOTE: can be called more than once, adding multiple contacts. Each contact will have access
|
* <p>NOTE: can be called more than once, adding multiple users. Each user will have access to all
|
||||||
* to all OT&E Registrars.
|
* OT&E Registrars.
|
||||||
*
|
*
|
||||||
* @param email the contact/login email that will have web-console access to all the Registrars.
|
* @param email the login email that will have web-console access to all the Registrars. Must be
|
||||||
* Must be from "our G Suite domain".
|
* from "our Google Workspace domain".
|
||||||
*/
|
*/
|
||||||
public OteAccountBuilder addContact(String email) {
|
public OteAccountBuilder addUser(String email) {
|
||||||
registrars.forEach(registrar -> contactsBuilder.add(createRegistrarContact(email, registrar)));
|
users.add(
|
||||||
|
new User.Builder()
|
||||||
|
.setEmailAddress(email)
|
||||||
|
.setUserRoles(
|
||||||
|
new UserRoles.Builder()
|
||||||
|
.setRegistrarRoles(
|
||||||
|
registrars.stream()
|
||||||
|
.collect(
|
||||||
|
toImmutableMap(
|
||||||
|
Registrar::getRegistrarId,
|
||||||
|
registrar -> RegistrarRole.ACCOUNT_MANAGER)))
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +239,7 @@ public final class OteAccountBuilder {
|
|||||||
return transformRegistrars(builder -> builder.setClientCertificate(asciiCert, now));
|
return transformRegistrars(builder -> builder.setClientCertificate(asciiCert, now));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the IP allow list to all the OT&E Registrars. */
|
/** Sets the IP allowlist to all the OT&E Registrars. */
|
||||||
public OteAccountBuilder setIpAllowList(Collection<String> ipAllowList) {
|
public OteAccountBuilder setIpAllowList(Collection<String> ipAllowList) {
|
||||||
ImmutableList<CidrAddressBlock> ipAddressAllowList =
|
ImmutableList<CidrAddressBlock> ipAddressAllowList =
|
||||||
ipAllowList.stream().map(CidrAddressBlock::create).collect(toImmutableList());
|
ipAllowList.stream().map(CidrAddressBlock::create).collect(toImmutableList());
|
||||||
@@ -237,18 +259,37 @@ public final class OteAccountBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return map from the OT&E registrarIds we will create to the new TLDs they will have access
|
* Return the map from the OT&E registrarIds we will create to the new TLDs they will have
|
||||||
* to.
|
* access to.
|
||||||
*/
|
*/
|
||||||
public ImmutableMap<String, String> getRegistrarIdToTldMap() {
|
public ImmutableMap<String, String> getRegistrarIdToTldMap() {
|
||||||
return registrarIdToTld;
|
return registrarIdToTld;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Grants the users permission to pass IAP. */
|
||||||
|
public void grantIapPermission(
|
||||||
|
Optional<String> groupEmailAddress, CloudTasksUtils cloudTasksUtils, IamClient iamClient) {
|
||||||
|
for (User user : users) {
|
||||||
|
User.grantIapPermission(
|
||||||
|
user.getEmailAddress(), groupEmailAddress, cloudTasksUtils, iamClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Saves all the OT&E entities we created. */
|
/** Saves all the OT&E entities we created. */
|
||||||
private void saveAllEntities() {
|
private void saveAllEntities() {
|
||||||
// use ImmutableObject instead of Registry so that the Key generation doesn't break
|
|
||||||
ImmutableList<Tld> registries = ImmutableList.of(sunriseTld, gaTld, eapTld);
|
ImmutableList<Tld> registries = ImmutableList.of(sunriseTld, gaTld, eapTld);
|
||||||
ImmutableList<RegistrarPoc> contacts = contactsBuilder.build();
|
Map<String, User> existingUsers = new HashMap<>();
|
||||||
|
|
||||||
|
users.forEach(
|
||||||
|
user ->
|
||||||
|
UserDao.loadUser(user.getEmailAddress())
|
||||||
|
.ifPresent(
|
||||||
|
existingUser ->
|
||||||
|
existingUsers.put(existingUser.getEmailAddress(), existingUser)));
|
||||||
|
|
||||||
|
if (!replaceExisting) {
|
||||||
|
checkState(existingUsers.isEmpty(), "Found existing users: %s", existingUsers);
|
||||||
|
}
|
||||||
|
|
||||||
tm().transact(
|
tm().transact(
|
||||||
() -> {
|
() -> {
|
||||||
@@ -256,8 +297,7 @@ public final class OteAccountBuilder {
|
|||||||
ImmutableList<VKey<? extends ImmutableObject>> keys =
|
ImmutableList<VKey<? extends ImmutableObject>> keys =
|
||||||
Streams.concat(
|
Streams.concat(
|
||||||
registries.stream().map(tld -> Tld.createVKey(tld.getTldStr())),
|
registries.stream().map(tld -> Tld.createVKey(tld.getTldStr())),
|
||||||
registrars.stream().map(Registrar::createVKey),
|
registrars.stream().map(Registrar::createVKey))
|
||||||
contacts.stream().map(RegistrarPoc::createVKey))
|
|
||||||
.collect(toImmutableList());
|
.collect(toImmutableList());
|
||||||
ImmutableMap<VKey<? extends ImmutableObject>, ImmutableObject> existingObjects =
|
ImmutableMap<VKey<? extends ImmutableObject>, ImmutableObject> existingObjects =
|
||||||
tm().loadByKeysIfPresent(keys);
|
tm().loadByKeysIfPresent(keys);
|
||||||
@@ -275,8 +315,18 @@ public final class OteAccountBuilder {
|
|||||||
registrars = registrars.stream().map(this::addAllowedTld).collect(toImmutableList());
|
registrars = registrars.stream().map(this::addAllowedTld).collect(toImmutableList());
|
||||||
// and we can save the registrars and contacts!
|
// and we can save the registrars and contacts!
|
||||||
tm().putAll(registrars);
|
tm().putAll(registrars);
|
||||||
tm().putAll(contacts);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (User user : users) {
|
||||||
|
String email = user.getEmailAddress();
|
||||||
|
if (existingUsers.containsKey(email)) {
|
||||||
|
// Note that other roles for the existing user are reset. We do this instead of simply
|
||||||
|
// saving the new user is that UserDao does not allow us to save the new user with the same
|
||||||
|
// email as the existing user.
|
||||||
|
user = existingUsers.get(email).asBuilder().setUserRoles(user.getUserRoles()).build();
|
||||||
|
}
|
||||||
|
UserDao.saveUser(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Registrar addAllowedTld(Registrar registrar) {
|
private Registrar addAllowedTld(Registrar registrar) {
|
||||||
@@ -336,15 +386,6 @@ public final class OteAccountBuilder {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RegistrarPoc createRegistrarContact(String email, Registrar registrar) {
|
|
||||||
return new RegistrarPoc.Builder()
|
|
||||||
.setRegistrar(registrar)
|
|
||||||
.setName(email)
|
|
||||||
.setEmailAddress(email)
|
|
||||||
.setLoginEmailAddress(email)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the registrar IDs of the OT&E, with the TLDs each has access to. */
|
/** Returns the registrar IDs of the OT&E, with the TLDs each has access to. */
|
||||||
public static ImmutableMap<String, String> createRegistrarIdToTldMap(String baseRegistrarId) {
|
public static ImmutableMap<String, String> createRegistrarIdToTldMap(String baseRegistrarId) {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
|
|||||||
@@ -14,7 +14,19 @@
|
|||||||
|
|
||||||
package google.registry.model.console;
|
package google.registry.model.console;
|
||||||
|
|
||||||
|
import static google.registry.tools.server.UpdateUserGroupAction.GROUP_UPDATE_QUEUE;
|
||||||
|
|
||||||
|
import com.google.cloud.tasks.v2.Task;
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
import com.google.common.flogger.FluentLogger;
|
||||||
|
import google.registry.batch.CloudTasksUtils;
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
|
import google.registry.request.Action.Service;
|
||||||
|
import google.registry.tools.IamClient;
|
||||||
|
import google.registry.tools.server.UpdateUserGroupAction;
|
||||||
|
import google.registry.tools.server.UpdateUserGroupAction.Mode;
|
||||||
|
import google.registry.util.RegistryEnvironment;
|
||||||
|
import java.util.Optional;
|
||||||
import javax.persistence.Access;
|
import javax.persistence.Access;
|
||||||
import javax.persistence.AccessType;
|
import javax.persistence.AccessType;
|
||||||
import javax.persistence.Embeddable;
|
import javax.persistence.Embeddable;
|
||||||
@@ -31,6 +43,76 @@ import javax.persistence.Table;
|
|||||||
@Table(indexes = {@Index(columnList = "emailAddress", name = "user_email_address_idx")})
|
@Table(indexes = {@Index(columnList = "emailAddress", name = "user_email_address_idx")})
|
||||||
public class User extends UserBase {
|
public class User extends UserBase {
|
||||||
|
|
||||||
|
public static final String IAP_SECURED_WEB_APP_USER_ROLE = "roles/iap.httpsResourceAccessor";
|
||||||
|
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grants the user permission to pass IAP.
|
||||||
|
*
|
||||||
|
* <p>Depending on if a console user group is set up, the permission is granted either
|
||||||
|
* individually or via group membership.
|
||||||
|
*/
|
||||||
|
public static void grantIapPermission(
|
||||||
|
String emailAddress,
|
||||||
|
Optional<String> groupEmailAddress,
|
||||||
|
CloudTasksUtils cloudTasksUtils,
|
||||||
|
IamClient iamClient) {
|
||||||
|
if (RegistryEnvironment.isInTestServer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (groupEmailAddress.isEmpty()) {
|
||||||
|
logger.atInfo().log("Granting IAP role to user %s", emailAddress);
|
||||||
|
iamClient.addBinding(emailAddress, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
|
} else {
|
||||||
|
logger.atInfo().log("Adding %s to group %s", emailAddress, groupEmailAddress.get());
|
||||||
|
modifyGroupMembershipAsync(
|
||||||
|
emailAddress, groupEmailAddress.get(), cloudTasksUtils, UpdateUserGroupAction.Mode.ADD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revoke the user's permission to pass IAP.
|
||||||
|
*
|
||||||
|
* <p>Depending on if a console user group is set up, the permission is revoked either
|
||||||
|
* individually or via group membership.
|
||||||
|
*/
|
||||||
|
public static void revokeIapPermission(
|
||||||
|
String emailAddress,
|
||||||
|
Optional<String> groupEmailAddress,
|
||||||
|
CloudTasksUtils cloudTasksUtils,
|
||||||
|
IamClient iamClient) {
|
||||||
|
if (RegistryEnvironment.isInTestServer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (groupEmailAddress.isEmpty()) {
|
||||||
|
logger.atInfo().log("Removing IAP role from user %s", emailAddress);
|
||||||
|
iamClient.removeBinding(emailAddress, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
|
} else {
|
||||||
|
logger.atInfo().log("Removing %s from group %s", emailAddress, groupEmailAddress.get());
|
||||||
|
modifyGroupMembershipAsync(
|
||||||
|
emailAddress, groupEmailAddress.get(), cloudTasksUtils, Mode.REMOVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void modifyGroupMembershipAsync(
|
||||||
|
String userEmailAddress,
|
||||||
|
String groupEmailAddress,
|
||||||
|
CloudTasksUtils cloudTasksUtils,
|
||||||
|
Mode mode) {
|
||||||
|
Task task =
|
||||||
|
cloudTasksUtils.createPostTask(
|
||||||
|
UpdateUserGroupAction.PATH,
|
||||||
|
Service.TOOLS,
|
||||||
|
ImmutableMultimap.of(
|
||||||
|
"userEmailAddress",
|
||||||
|
userEmailAddress,
|
||||||
|
"groupEmailAddress",
|
||||||
|
groupEmailAddress,
|
||||||
|
"groupUpdateMode",
|
||||||
|
mode.name()));
|
||||||
|
cloudTasksUtils.enqueue(GROUP_UPDATE_QUEUE, task);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|||||||
@@ -15,30 +15,25 @@
|
|||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static google.registry.model.console.User.grantIapPermission;
|
||||||
|
|
||||||
import com.beust.jcommander.Parameters;
|
import com.beust.jcommander.Parameters;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import google.registry.batch.CloudTasksUtils;
|
||||||
import com.google.common.flogger.FluentLogger;
|
|
||||||
import com.google.common.net.MediaType;
|
|
||||||
import google.registry.config.RegistryConfig.Config;
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.model.console.User;
|
import google.registry.model.console.User;
|
||||||
import google.registry.model.console.UserDao;
|
import google.registry.model.console.UserDao;
|
||||||
import google.registry.tools.server.UpdateUserGroupAction;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/** Command to create a new User. */
|
/** Command to create a new User. */
|
||||||
@Parameters(separators = " =", commandDescription = "Update a user account")
|
@Parameters(separators = " =", commandDescription = "Update a user account")
|
||||||
public class CreateUserCommand extends CreateOrUpdateUserCommand implements CommandWithConnection {
|
public class CreateUserCommand extends CreateOrUpdateUserCommand {
|
||||||
|
|
||||||
static final String IAP_SECURED_WEB_APP_USER_ROLE = "roles/iap.httpsResourceAccessor";
|
|
||||||
static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
|
||||||
|
|
||||||
private ServiceConnection connection;
|
|
||||||
|
|
||||||
@Inject IamClient iamClient;
|
@Inject IamClient iamClient;
|
||||||
|
|
||||||
|
@Inject CloudTasksUtils cloudTasksUtils;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Config("gSuiteConsoleUserGroupEmailAddress")
|
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||||
Optional<String> maybeGroupEmailAddress;
|
Optional<String> maybeGroupEmailAddress;
|
||||||
@@ -53,29 +48,7 @@ public class CreateUserCommand extends CreateOrUpdateUserCommand implements Comm
|
|||||||
@Override
|
@Override
|
||||||
protected String execute() throws Exception {
|
protected String execute() throws Exception {
|
||||||
String ret = super.execute();
|
String ret = super.execute();
|
||||||
String groupEmailAddress = maybeGroupEmailAddress.orElse(null);
|
grantIapPermission(email, maybeGroupEmailAddress, cloudTasksUtils, iamClient);
|
||||||
if (groupEmailAddress != null) {
|
|
||||||
logger.atInfo().log("Adding %s to group %s", email, groupEmailAddress);
|
|
||||||
connection.sendPostRequest(
|
|
||||||
UpdateUserGroupAction.PATH,
|
|
||||||
ImmutableMap.of(
|
|
||||||
"userEmailAddress",
|
|
||||||
email,
|
|
||||||
"groupEmailAddress",
|
|
||||||
groupEmailAddress,
|
|
||||||
"groupUpdateMode",
|
|
||||||
"ADD"),
|
|
||||||
MediaType.PLAIN_TEXT_UTF_8,
|
|
||||||
new byte[0]);
|
|
||||||
} else {
|
|
||||||
logger.atInfo().log("Granting IAP role to user %s", email);
|
|
||||||
iamClient.addBinding(email, IAP_SECURED_WEB_APP_USER_ROLE);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setConnection(ServiceConnection connection) {
|
|
||||||
this.connection = connection;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,32 +15,27 @@
|
|||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||||
import static google.registry.tools.CreateUserCommand.IAP_SECURED_WEB_APP_USER_ROLE;
|
|
||||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||||
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
|
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
|
||||||
|
|
||||||
import com.beust.jcommander.Parameter;
|
import com.beust.jcommander.Parameter;
|
||||||
import com.beust.jcommander.Parameters;
|
import com.beust.jcommander.Parameters;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import google.registry.batch.CloudTasksUtils;
|
||||||
import com.google.common.flogger.FluentLogger;
|
|
||||||
import com.google.common.net.MediaType;
|
|
||||||
import google.registry.config.RegistryConfig.Config;
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.model.console.User;
|
import google.registry.model.console.User;
|
||||||
import google.registry.model.console.UserDao;
|
import google.registry.model.console.UserDao;
|
||||||
import google.registry.tools.server.UpdateUserGroupAction;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/** Deletes a {@link User}. */
|
/** Deletes a {@link User}. */
|
||||||
@Parameters(separators = " =", commandDescription = "Delete a user account")
|
@Parameters(separators = " =", commandDescription = "Delete a user account")
|
||||||
public class DeleteUserCommand extends ConfirmingCommand implements CommandWithConnection {
|
public class DeleteUserCommand extends ConfirmingCommand {
|
||||||
|
|
||||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
|
||||||
|
|
||||||
private ServiceConnection connection;
|
|
||||||
@Inject IamClient iamClient;
|
@Inject IamClient iamClient;
|
||||||
|
|
||||||
|
@Inject CloudTasksUtils cloudTasksUtils;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Config("gSuiteConsoleUserGroupEmailAddress")
|
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||||
Optional<String> maybeGroupEmailAddress;
|
Optional<String> maybeGroupEmailAddress;
|
||||||
@@ -49,11 +44,6 @@ public class DeleteUserCommand extends ConfirmingCommand implements CommandWithC
|
|||||||
@Parameter(names = "--email", description = "Email address of the user", required = true)
|
@Parameter(names = "--email", description = "Email address of the user", required = true)
|
||||||
String email;
|
String email;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setConnection(ServiceConnection connection) {
|
|
||||||
this.connection = connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String prompt() {
|
protected String prompt() {
|
||||||
checkArgumentNotNull(email, "Email must be provided");
|
checkArgumentNotNull(email, "Email must be provided");
|
||||||
@@ -69,24 +59,7 @@ public class DeleteUserCommand extends ConfirmingCommand implements CommandWithC
|
|||||||
checkArgumentPresent(optionalUser, "Email no longer corresponds to a valid user");
|
checkArgumentPresent(optionalUser, "Email no longer corresponds to a valid user");
|
||||||
tm().delete(optionalUser.get());
|
tm().delete(optionalUser.get());
|
||||||
});
|
});
|
||||||
String groupEmailAddress = maybeGroupEmailAddress.orElse(null);
|
User.revokeIapPermission(email, maybeGroupEmailAddress, cloudTasksUtils, iamClient);
|
||||||
if (groupEmailAddress != null) {
|
|
||||||
logger.atInfo().log("Removing %s from group %s", email, groupEmailAddress);
|
|
||||||
connection.sendPostRequest(
|
|
||||||
UpdateUserGroupAction.PATH,
|
|
||||||
ImmutableMap.of(
|
|
||||||
"userEmailAddress",
|
|
||||||
email,
|
|
||||||
"groupEmailAddress",
|
|
||||||
groupEmailAddress,
|
|
||||||
"groupUpdateMode",
|
|
||||||
"REMOVE"),
|
|
||||||
MediaType.PLAIN_TEXT_UTF_8,
|
|
||||||
new byte[0]);
|
|
||||||
} else {
|
|
||||||
logger.atInfo().log("Removing IAP role from user %s", email);
|
|
||||||
iamClient.removeBinding(email, IAP_SECURED_WEB_APP_USER_ROLE);
|
|
||||||
}
|
|
||||||
return String.format("Deleted user with email %s", email);
|
return String.format("Deleted user with email %s", email);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import com.google.api.services.cloudresourcemanager.model.GetIamPolicyRequest;
|
|||||||
import com.google.api.services.cloudresourcemanager.model.Policy;
|
import com.google.api.services.cloudresourcemanager.model.Policy;
|
||||||
import com.google.api.services.cloudresourcemanager.model.SetIamPolicyRequest;
|
import com.google.api.services.cloudresourcemanager.model.SetIamPolicyRequest;
|
||||||
import com.google.common.base.Ascii;
|
import com.google.common.base.Ascii;
|
||||||
import google.registry.config.CredentialModule.LocalCredential;
|
import google.registry.config.CredentialModule.ApplicationDefaultCredential;
|
||||||
import google.registry.config.RegistryConfig.Config;
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.util.GoogleCredentialsBundle;
|
import google.registry.util.GoogleCredentialsBundle;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -38,7 +38,7 @@ public class IamClient {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public IamClient(
|
public IamClient(
|
||||||
@LocalCredential GoogleCredentialsBundle credentialsBundle,
|
@ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||||
@Config("projectId") String projectId) {
|
@Config("projectId") String projectId) {
|
||||||
this(
|
this(
|
||||||
new CloudResourceManager.Builder(
|
new CloudResourceManager.Builder(
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ package google.registry.tools;
|
|||||||
import com.google.api.services.dataflow.Dataflow;
|
import com.google.api.services.dataflow.Dataflow;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import google.registry.config.CredentialModule.LocalCredential;
|
import google.registry.config.CredentialModule.ApplicationDefaultCredential;
|
||||||
import google.registry.config.RegistryConfig.Config;
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.util.GoogleCredentialsBundle;
|
import google.registry.util.GoogleCredentialsBundle;
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ public class RegistryToolDataflowModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
static Dataflow provideDataflow(
|
static Dataflow provideDataflow(
|
||||||
@LocalCredential GoogleCredentialsBundle credentialsBundle,
|
@ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
|
||||||
@Config("projectId") String projectId) {
|
@Config("projectId") String projectId) {
|
||||||
return new Dataflow.Builder(
|
return new Dataflow.Builder(
|
||||||
credentialsBundle.getHttpTransport(),
|
credentialsBundle.getHttpTransport(),
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import com.beust.jcommander.Parameter;
|
|||||||
import com.beust.jcommander.Parameters;
|
import com.beust.jcommander.Parameters;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.io.MoreFiles;
|
import com.google.common.io.MoreFiles;
|
||||||
|
import google.registry.batch.CloudTasksUtils;
|
||||||
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.model.OteAccountBuilder;
|
import google.registry.model.OteAccountBuilder;
|
||||||
import google.registry.tools.params.PathParameter;
|
import google.registry.tools.params.PathParameter;
|
||||||
import google.registry.util.Clock;
|
import google.registry.util.Clock;
|
||||||
@@ -30,6 +32,7 @@ import google.registry.util.StringGenerator;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
@@ -47,7 +50,7 @@ final class SetupOteCommand extends ConfirmingCommand {
|
|||||||
|
|
||||||
@Parameter(
|
@Parameter(
|
||||||
names = {"-a", "--ip_allow_list"},
|
names = {"-a", "--ip_allow_list"},
|
||||||
description = "Comma-separated list of IP addreses or CIDR ranges.",
|
description = "Comma-separated list of IP addresses or CIDR ranges.",
|
||||||
required = true)
|
required = true)
|
||||||
private List<String> ipAllowList = new ArrayList<>();
|
private List<String> ipAllowList = new ArrayList<>();
|
||||||
|
|
||||||
@@ -55,7 +58,7 @@ final class SetupOteCommand extends ConfirmingCommand {
|
|||||||
names = {"--email"},
|
names = {"--email"},
|
||||||
description =
|
description =
|
||||||
"The registrar's account to use for console access. "
|
"The registrar's account to use for console access. "
|
||||||
+ "Must be on the registry's G Suite domain.",
|
+ "Must be on the registry's Google Workspace domain.",
|
||||||
required = true)
|
required = true)
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@@ -76,6 +79,14 @@ final class SetupOteCommand extends ConfirmingCommand {
|
|||||||
|
|
||||||
@Inject Clock clock;
|
@Inject Clock clock;
|
||||||
|
|
||||||
|
@Inject CloudTasksUtils cloudTasksUtils;
|
||||||
|
|
||||||
|
@Inject IamClient iamClient;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||||
|
Optional<String> maybeGroupEmailAddress;
|
||||||
|
|
||||||
OteAccountBuilder oteAccountBuilder;
|
OteAccountBuilder oteAccountBuilder;
|
||||||
String password;
|
String password;
|
||||||
|
|
||||||
@@ -87,7 +98,7 @@ final class SetupOteCommand extends ConfirmingCommand {
|
|||||||
password = passwordGenerator.createString(PASSWORD_LENGTH);
|
password = passwordGenerator.createString(PASSWORD_LENGTH);
|
||||||
oteAccountBuilder =
|
oteAccountBuilder =
|
||||||
OteAccountBuilder.forRegistrarId(registrar)
|
OteAccountBuilder.forRegistrarId(registrar)
|
||||||
.addContact(email)
|
.addUser(email)
|
||||||
.setPassword(password)
|
.setPassword(password)
|
||||||
.setIpAllowList(ipAllowList)
|
.setIpAllowList(ipAllowList)
|
||||||
.setReplaceExisting(overwrite);
|
.setReplaceExisting(overwrite);
|
||||||
@@ -114,8 +125,11 @@ final class SetupOteCommand extends ConfirmingCommand {
|
|||||||
&& RegistryEnvironment.get() != RegistryEnvironment.UNITTEST) {
|
&& RegistryEnvironment.get() != RegistryEnvironment.UNITTEST) {
|
||||||
builder.append(
|
builder.append(
|
||||||
String.format(
|
String.format(
|
||||||
"\n\nWARNING: Running against %s environment. Are "
|
"""
|
||||||
+ "you sure you didn\'t mean to run this against sandbox (e.g. \"-e SANDBOX\")?",
|
|
||||||
|
|
||||||
|
WARNING: Running against %s environment. Are \
|
||||||
|
you sure you didn't mean to run this against sandbox (e.g. "-e SANDBOX")?""",
|
||||||
RegistryEnvironment.get()));
|
RegistryEnvironment.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,15 +139,15 @@ final class SetupOteCommand extends ConfirmingCommand {
|
|||||||
@Override
|
@Override
|
||||||
public String execute() {
|
public String execute() {
|
||||||
ImmutableMap<String, String> clientIdToTld = oteAccountBuilder.buildAndPersist();
|
ImmutableMap<String, String> clientIdToTld = oteAccountBuilder.buildAndPersist();
|
||||||
|
oteAccountBuilder.grantIapPermission(maybeGroupEmailAddress, cloudTasksUtils, iamClient);
|
||||||
|
|
||||||
StringBuilder output = new StringBuilder();
|
StringBuilder output = new StringBuilder();
|
||||||
|
|
||||||
output.append("Copy these usernames/passwords back into the onboarding bug:\n\n");
|
output.append("Copy these usernames/passwords back into the onboarding bug:\n\n");
|
||||||
clientIdToTld.forEach(
|
clientIdToTld.forEach(
|
||||||
(clientId, tld) -> {
|
(clientId, tld) ->
|
||||||
output.append(
|
output.append(
|
||||||
String.format("Login: %s\nPassword: %s\nTLD: %s\n\n", clientId, password, tld));
|
String.format("Login: %s\nPassword: %s\nTLD: %s\n\n", clientId, password, tld)));
|
||||||
});
|
|
||||||
|
|
||||||
return output.toString();
|
return output.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import javax.inject.Inject;
|
|||||||
public class UpdateUserGroupAction implements Runnable {
|
public class UpdateUserGroupAction implements Runnable {
|
||||||
|
|
||||||
public static final String PATH = "/_dr/admin/updateUserGroup";
|
public static final String PATH = "/_dr/admin/updateUserGroup";
|
||||||
|
public static final String GROUP_UPDATE_QUEUE = "console-user-group-update";
|
||||||
|
|
||||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ public class UpdateUserGroupAction implements Runnable {
|
|||||||
@Inject
|
@Inject
|
||||||
UpdateUserGroupAction() {}
|
UpdateUserGroupAction() {}
|
||||||
|
|
||||||
enum Mode {
|
public enum Mode {
|
||||||
ADD,
|
ADD,
|
||||||
REMOVE
|
REMOVE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import com.google.common.base.Supplier;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.flogger.FluentLogger;
|
import com.google.common.flogger.FluentLogger;
|
||||||
import com.google.template.soy.tofu.SoyTofu;
|
import com.google.template.soy.tofu.SoyTofu;
|
||||||
|
import google.registry.batch.CloudTasksUtils;
|
||||||
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.model.OteAccountBuilder;
|
import google.registry.model.OteAccountBuilder;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.Action.Method;
|
import google.registry.request.Action.Method;
|
||||||
@@ -31,6 +33,7 @@ import google.registry.request.HttpException.BadRequestException;
|
|||||||
import google.registry.request.Parameter;
|
import google.registry.request.Parameter;
|
||||||
import google.registry.request.auth.Auth;
|
import google.registry.request.auth.Auth;
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||||
|
import google.registry.tools.IamClient;
|
||||||
import google.registry.ui.server.SendEmailUtils;
|
import google.registry.ui.server.SendEmailUtils;
|
||||||
import google.registry.ui.server.SoyTemplateUtils;
|
import google.registry.ui.server.SoyTemplateUtils;
|
||||||
import google.registry.ui.soy.registrar.OteSetupConsoleSoyInfo;
|
import google.registry.ui.soy.registrar.OteSetupConsoleSoyInfo;
|
||||||
@@ -87,6 +90,14 @@ public final class ConsoleOteSetupAction extends HtmlAction {
|
|||||||
@Parameter("password")
|
@Parameter("password")
|
||||||
Optional<String> optionalPassword;
|
Optional<String> optionalPassword;
|
||||||
|
|
||||||
|
@Inject CloudTasksUtils cloudTasksUtils;
|
||||||
|
|
||||||
|
@Inject IamClient iamClient;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||||
|
Optional<String> maybeGroupEmailAddress;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ConsoleOteSetupAction() {}
|
ConsoleOteSetupAction() {}
|
||||||
|
|
||||||
@@ -107,16 +118,11 @@ public final class ConsoleOteSetupAction extends HtmlAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case POST -> {
|
case POST -> runPost(data);
|
||||||
runPost(data);
|
case GET -> runGet(data);
|
||||||
}
|
default ->
|
||||||
case GET -> {
|
throw new BadRequestException(
|
||||||
runGet(data);
|
String.format("Action cannot be called with method %s", method));
|
||||||
}
|
|
||||||
default -> {
|
|
||||||
throw new BadRequestException(
|
|
||||||
String.format("Action cannot be called with method %s", method));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,11 +139,13 @@ public final class ConsoleOteSetupAction extends HtmlAction {
|
|||||||
data.put("contactEmail", email.get());
|
data.put("contactEmail", email.get());
|
||||||
|
|
||||||
String password = optionalPassword.orElse(passwordGenerator.createString(PASSWORD_LENGTH));
|
String password = optionalPassword.orElse(passwordGenerator.createString(PASSWORD_LENGTH));
|
||||||
ImmutableMap<String, String> clientIdToTld =
|
OteAccountBuilder oteAccountBuilder =
|
||||||
OteAccountBuilder.forRegistrarId(clientId.get())
|
OteAccountBuilder.forRegistrarId(clientId.get())
|
||||||
.addContact(email.get())
|
.addUser(email.get())
|
||||||
.setPassword(password)
|
.setPassword(password);
|
||||||
.buildAndPersist();
|
ImmutableMap<String, String> clientIdToTld = oteAccountBuilder.buildAndPersist();
|
||||||
|
|
||||||
|
oteAccountBuilder.grantIapPermission(maybeGroupEmailAddress, cloudTasksUtils, iamClient);
|
||||||
|
|
||||||
sendExternalUpdates(clientIdToTld);
|
sendExternalUpdates(clientIdToTld);
|
||||||
|
|
||||||
|
|||||||
@@ -26,10 +26,15 @@ import com.google.common.base.Splitter;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.flogger.FluentLogger;
|
import com.google.common.flogger.FluentLogger;
|
||||||
import com.google.template.soy.tofu.SoyTofu;
|
import com.google.template.soy.tofu.SoyTofu;
|
||||||
|
import google.registry.batch.CloudTasksUtils;
|
||||||
|
import google.registry.config.RegistryConfig.Config;
|
||||||
|
import google.registry.model.console.RegistrarRole;
|
||||||
|
import google.registry.model.console.User;
|
||||||
|
import google.registry.model.console.UserDao;
|
||||||
|
import google.registry.model.console.UserRoles;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.model.registrar.RegistrarAddress;
|
import google.registry.model.registrar.RegistrarAddress;
|
||||||
import google.registry.model.registrar.RegistrarBase.State;
|
import google.registry.model.registrar.RegistrarBase.State;
|
||||||
import google.registry.model.registrar.RegistrarPoc;
|
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.Action.Method;
|
import google.registry.request.Action.Method;
|
||||||
import google.registry.request.Action.Service;
|
import google.registry.request.Action.Service;
|
||||||
@@ -37,6 +42,7 @@ import google.registry.request.HttpException.BadRequestException;
|
|||||||
import google.registry.request.Parameter;
|
import google.registry.request.Parameter;
|
||||||
import google.registry.request.auth.Auth;
|
import google.registry.request.auth.Auth;
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||||
|
import google.registry.tools.IamClient;
|
||||||
import google.registry.ui.server.SendEmailUtils;
|
import google.registry.ui.server.SendEmailUtils;
|
||||||
import google.registry.ui.server.SoyTemplateUtils;
|
import google.registry.ui.server.SoyTemplateUtils;
|
||||||
import google.registry.ui.soy.registrar.AnalyticsSoyInfo;
|
import google.registry.ui.soy.registrar.AnalyticsSoyInfo;
|
||||||
@@ -95,6 +101,14 @@ public final class ConsoleRegistrarCreatorAction extends HtmlAction {
|
|||||||
@Parameter("consoleName")
|
@Parameter("consoleName")
|
||||||
Optional<String> name;
|
Optional<String> name;
|
||||||
|
|
||||||
|
@Inject CloudTasksUtils cloudTasksUtils;
|
||||||
|
|
||||||
|
@Inject IamClient iamClient;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Config("gSuiteConsoleUserGroupEmailAddress")
|
||||||
|
Optional<String> maybeGroupEmailAddress;
|
||||||
|
|
||||||
@Inject @Parameter("billingAccount") Optional<String> billingAccount;
|
@Inject @Parameter("billingAccount") Optional<String> billingAccount;
|
||||||
@Inject @Parameter("ianaId") Optional<Integer> ianaId;
|
@Inject @Parameter("ianaId") Optional<Integer> ianaId;
|
||||||
@Inject @Parameter("referralEmail") Optional<String> referralEmail;
|
@Inject @Parameter("referralEmail") Optional<String> referralEmail;
|
||||||
@@ -129,16 +143,11 @@ public final class ConsoleRegistrarCreatorAction extends HtmlAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case POST -> {
|
case POST -> runPost(data);
|
||||||
runPost(data);
|
case GET -> runGet(data);
|
||||||
}
|
default ->
|
||||||
case GET -> {
|
throw new BadRequestException(
|
||||||
runGet(data);
|
String.format("Action cannot be called with method %s", method));
|
||||||
}
|
|
||||||
default -> {
|
|
||||||
throw new BadRequestException(
|
|
||||||
String.format("Action cannot be called with method %s", method));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +178,8 @@ public final class ConsoleRegistrarCreatorAction extends HtmlAction {
|
|||||||
list))
|
list))
|
||||||
.collect(
|
.collect(
|
||||||
toImmutableMap(
|
toImmutableMap(
|
||||||
list -> CurrencyUnit.of(Ascii.toUpperCase(list.get(0))), list -> list.get(1)));
|
list -> CurrencyUnit.of(Ascii.toUpperCase(list.getFirst())),
|
||||||
|
list -> list.get(1)));
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException("Error parsing billing accounts - " + e.getMessage(), e);
|
throw new RuntimeException("Error parsing billing accounts - " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
@@ -233,12 +243,15 @@ public final class ConsoleRegistrarCreatorAction extends HtmlAction {
|
|||||||
.setZip(optionalZip.orElse(null))
|
.setZip(optionalZip.orElse(null))
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
RegistrarPoc contact =
|
User user =
|
||||||
new RegistrarPoc.Builder()
|
new User.Builder()
|
||||||
.setRegistrar(registrar)
|
|
||||||
.setName(consoleUserEmail.get())
|
|
||||||
.setEmailAddress(consoleUserEmail.get())
|
.setEmailAddress(consoleUserEmail.get())
|
||||||
.setLoginEmailAddress(consoleUserEmail.get())
|
.setUserRoles(
|
||||||
|
new UserRoles.Builder()
|
||||||
|
.setRegistrarRoles(
|
||||||
|
ImmutableMap.of(
|
||||||
|
registrar.getRegistrarId(), RegistrarRole.ACCOUNT_MANAGER))
|
||||||
|
.build())
|
||||||
.build();
|
.build();
|
||||||
tm().transact(
|
tm().transact(
|
||||||
() -> {
|
() -> {
|
||||||
@@ -246,8 +259,11 @@ public final class ConsoleRegistrarCreatorAction extends HtmlAction {
|
|||||||
Registrar.loadByRegistrarId(registrar.getRegistrarId()).isEmpty(),
|
Registrar.loadByRegistrarId(registrar.getRegistrarId()).isEmpty(),
|
||||||
"Registrar with client ID %s already exists",
|
"Registrar with client ID %s already exists",
|
||||||
registrar.getRegistrarId());
|
registrar.getRegistrarId());
|
||||||
tm().putAll(registrar, contact);
|
tm().put(registrar);
|
||||||
});
|
});
|
||||||
|
UserDao.saveUser(user);
|
||||||
|
User.grantIapPermission(
|
||||||
|
user.getEmailAddress(), maybeGroupEmailAddress, cloudTasksUtils, iamClient);
|
||||||
data.put("password", password);
|
data.put("password", password);
|
||||||
data.put("passcode", phonePasscode);
|
data.put("passcode", phonePasscode);
|
||||||
|
|
||||||
|
|||||||
@@ -88,22 +88,6 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
|||||||
static final String ARGS_PARAM = "args";
|
static final String ARGS_PARAM = "args";
|
||||||
static final String ID_PARAM = "id";
|
static final String ID_PARAM = "id";
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows task enqueueing to be disabled when executing registrar console test cases.
|
|
||||||
*
|
|
||||||
* <p>The existing workflow in UI test cases triggers task enqueueing, which was not an issue with
|
|
||||||
* Task Queue since it's a native App Engine feature simulated by the App Engine SDK's
|
|
||||||
* environment. However, with Cloud Tasks, the server enqueues and fails to deliver to the actual
|
|
||||||
* Cloud Tasks endpoint due to lack of permission.
|
|
||||||
*
|
|
||||||
* <p>One way to allow enqueuing in backend test and avoid enqueuing in UI test is to disable
|
|
||||||
* enqueuing when the test server starts and enable enqueueing once the test server stops. This
|
|
||||||
* can be done by utilizing a ThreadLocal<Boolean> variable isInTestDriver, which is set to false
|
|
||||||
* by default. Enqueuing is allowed only if the value of isInTestDriver is false. It's set to true
|
|
||||||
* in start() and set to false in stop() inside TestDriver.java, a class used in testing.
|
|
||||||
*/
|
|
||||||
private static final ThreadLocal<Boolean> isInTestDriver = ThreadLocal.withInitial(() -> false);
|
|
||||||
|
|
||||||
@Inject JsonActionRunner jsonActionRunner;
|
@Inject JsonActionRunner jsonActionRunner;
|
||||||
@Inject RegistrarConsoleMetrics registrarConsoleMetrics;
|
@Inject RegistrarConsoleMetrics registrarConsoleMetrics;
|
||||||
@Inject SendEmailUtils sendEmailUtils;
|
@Inject SendEmailUtils sendEmailUtils;
|
||||||
@@ -118,14 +102,6 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
|||||||
return contact.getPhoneNumber() != null;
|
return contact.getPhoneNumber() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setIsInTestDriverToFalse() {
|
|
||||||
isInTestDriver.set(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setIsInTestDriverToTrue() {
|
|
||||||
isInTestDriver.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
jsonActionRunner.run(this);
|
jsonActionRunner.run(this);
|
||||||
@@ -623,7 +599,7 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
|
|||||||
if (CollectionUtils.difference(changedKeys, "lastUpdateTime").isEmpty()) {
|
if (CollectionUtils.difference(changedKeys, "lastUpdateTime").isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isInTestDriver.get()) {
|
if (!RegistryEnvironment.isInTestServer()) {
|
||||||
// Enqueues a sync registrar sheet task if enqueuing is not triggered by console tests and
|
// Enqueues a sync registrar sheet task if enqueuing is not triggered by console tests and
|
||||||
// there's an update besides the lastUpdateTime
|
// there's an update besides the lastUpdateTime
|
||||||
cloudTasksUtils.enqueue(
|
cloudTasksUtils.enqueue(
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package google.registry.model;
|
package google.registry.model;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.console.User.IAP_SECURED_WEB_APP_USER_ROLE;
|
||||||
import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
|
import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
|
||||||
import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
|
import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
|
||||||
import static google.registry.persistence.transaction.JpaTransactionManagerExtension.makeRegistrar1;
|
import static google.registry.persistence.transaction.JpaTransactionManagerExtension.makeRegistrar1;
|
||||||
@@ -26,16 +27,28 @@ import static google.registry.testing.DatabaseHelper.persistSimpleResource;
|
|||||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
import static org.joda.money.CurrencyUnit.USD;
|
import static org.joda.money.CurrencyUnit.USD;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
|
|
||||||
|
import com.google.cloud.tasks.v2.HttpMethod;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import google.registry.batch.CloudTasksUtils;
|
||||||
|
import google.registry.model.console.RegistrarRole;
|
||||||
|
import google.registry.model.console.User;
|
||||||
|
import google.registry.model.console.UserDao;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.model.registrar.RegistrarPoc;
|
|
||||||
import google.registry.model.tld.Tld;
|
import google.registry.model.tld.Tld;
|
||||||
import google.registry.model.tld.Tld.TldState;
|
import google.registry.model.tld.Tld.TldState;
|
||||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||||
|
import google.registry.testing.CloudTasksHelper;
|
||||||
|
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||||
|
import google.registry.tools.IamClient;
|
||||||
import google.registry.util.CidrAddressBlock;
|
import google.registry.util.CidrAddressBlock;
|
||||||
import google.registry.util.SystemClock;
|
import google.registry.util.SystemClock;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
@@ -50,6 +63,9 @@ public final class OteAccountBuilderTest {
|
|||||||
final JpaIntegrationTestExtension jpa =
|
final JpaIntegrationTestExtension jpa =
|
||||||
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
||||||
|
|
||||||
|
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||||
|
private final IamClient iamClient = mock(IamClient.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetRegistrarToTldMap() {
|
void testGetRegistrarToTldMap() {
|
||||||
assertThat(OteAccountBuilder.forRegistrarId("myclientid").getRegistrarIdToTldMap())
|
assertThat(OteAccountBuilder.forRegistrarId("myclientid").getRegistrarIdToTldMap())
|
||||||
@@ -89,23 +105,63 @@ public final class OteAccountBuilderTest {
|
|||||||
assertThat(registrar.getAllowedTlds()).containsExactly(tld);
|
assertThat(registrar.getAllowedTlds()).containsExactly(tld);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertContactExists(String registrarId, String email) {
|
public static void verifyUser(String registrarId, String email) {
|
||||||
Registrar registrar = Registrar.loadByRegistrarId(registrarId).get();
|
Optional<User> maybeUser = UserDao.loadUser(email);
|
||||||
assertThat(registrar.getContacts().stream().map(RegistrarPoc::getEmailAddress)).contains(email);
|
assertThat(maybeUser).isPresent();
|
||||||
RegistrarPoc contact =
|
assertThat(maybeUser.get().getUserRoles().getRegistrarRoles().get(registrarId))
|
||||||
registrar.getContacts().stream()
|
.isEqualTo(RegistrarRole.ACCOUNT_MANAGER);
|
||||||
.filter(c -> email.equals(c.getEmailAddress()))
|
}
|
||||||
.findAny()
|
|
||||||
.get();
|
public static void verifyIapPermission(
|
||||||
assertThat(contact.getEmailAddress()).isEqualTo(email);
|
@Nullable String emailAddress,
|
||||||
assertThat(contact.getLoginEmailAddress()).isEqualTo(email);
|
Optional<String> maybeGroupEmailAddress,
|
||||||
|
CloudTasksHelper cloudTasksHelper,
|
||||||
|
IamClient iamClient) {
|
||||||
|
if (emailAddress == null) {
|
||||||
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
|
verifyNoInteractions(iamClient);
|
||||||
|
} else {
|
||||||
|
String groupEmailAddress = maybeGroupEmailAddress.orElse(null);
|
||||||
|
if (groupEmailAddress == null) {
|
||||||
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
|
verify(iamClient).addBinding(emailAddress, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
|
} else {
|
||||||
|
cloudTasksHelper.assertTasksEnqueued(
|
||||||
|
"console-user-group-update",
|
||||||
|
new TaskMatcher()
|
||||||
|
.service("TOOLS")
|
||||||
|
.method(HttpMethod.POST)
|
||||||
|
.path("/_dr/admin/updateUserGroup")
|
||||||
|
.param("userEmailAddress", emailAddress)
|
||||||
|
.param("groupEmailAddress", groupEmailAddress)
|
||||||
|
.param("groupUpdateMode", "ADD"));
|
||||||
|
verifyNoInteractions(iamClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateUserGroup() {
|
||||||
|
CloudTasksUtils cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
|
OteAccountBuilder.forRegistrarId("myclientid")
|
||||||
|
.addUser("email@example.com")
|
||||||
|
.grantIapPermission(Optional.of("console@example.com"), cloudTasksUtils, iamClient);
|
||||||
|
verifyIapPermission(
|
||||||
|
"email@example.com", Optional.of("console@example.com"), cloudTasksHelper, iamClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGrantIndividualPermission() {
|
||||||
|
CloudTasksUtils cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
|
OteAccountBuilder.forRegistrarId("myclientid")
|
||||||
|
.addUser("email@example.com")
|
||||||
|
.grantIapPermission(Optional.empty(), cloudTasksUtils, iamClient);
|
||||||
|
verifyIapPermission("email@example.com", Optional.empty(), cloudTasksHelper, iamClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCreateOteEntities_success() {
|
void testCreateOteEntities_success() {
|
||||||
OteAccountBuilder.forRegistrarId("myclientid")
|
OteAccountBuilder.forRegistrarId("myclientid").addUser("email@example.com").buildAndPersist();
|
||||||
.addContact("email@example.com")
|
|
||||||
.buildAndPersist();
|
|
||||||
|
|
||||||
assertTldExists("myclientid-sunrise", START_DATE_SUNRISE, Money.zero(USD));
|
assertTldExists("myclientid-sunrise", START_DATE_SUNRISE, Money.zero(USD));
|
||||||
assertTldExists("myclientid-ga", GENERAL_AVAILABILITY, Money.zero(USD));
|
assertTldExists("myclientid-ga", GENERAL_AVAILABILITY, Money.zero(USD));
|
||||||
@@ -114,18 +170,18 @@ public final class OteAccountBuilderTest {
|
|||||||
assertRegistrarExists("myclientid-3", "myclientid-ga");
|
assertRegistrarExists("myclientid-3", "myclientid-ga");
|
||||||
assertRegistrarExists("myclientid-4", "myclientid-ga");
|
assertRegistrarExists("myclientid-4", "myclientid-ga");
|
||||||
assertRegistrarExists("myclientid-5", "myclientid-eap");
|
assertRegistrarExists("myclientid-5", "myclientid-eap");
|
||||||
assertContactExists("myclientid-1", "email@example.com");
|
verifyUser("myclientid-1", "email@example.com");
|
||||||
assertContactExists("myclientid-3", "email@example.com");
|
verifyUser("myclientid-3", "email@example.com");
|
||||||
assertContactExists("myclientid-4", "email@example.com");
|
verifyUser("myclientid-4", "email@example.com");
|
||||||
assertContactExists("myclientid-5", "email@example.com");
|
verifyUser("myclientid-5", "email@example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCreateOteEntities_multipleContacts_success() {
|
void testCreateOteEntities_multipleContacts_success() {
|
||||||
OteAccountBuilder.forRegistrarId("myclientid")
|
OteAccountBuilder.forRegistrarId("myclientid")
|
||||||
.addContact("email@example.com")
|
.addUser("email@example.com")
|
||||||
.addContact("other@example.com")
|
.addUser("other@example.com")
|
||||||
.addContact("someone@example.com")
|
.addUser("someone@example.com")
|
||||||
.buildAndPersist();
|
.buildAndPersist();
|
||||||
|
|
||||||
assertTldExists("myclientid-sunrise", START_DATE_SUNRISE, Money.zero(USD));
|
assertTldExists("myclientid-sunrise", START_DATE_SUNRISE, Money.zero(USD));
|
||||||
@@ -135,18 +191,18 @@ public final class OteAccountBuilderTest {
|
|||||||
assertRegistrarExists("myclientid-3", "myclientid-ga");
|
assertRegistrarExists("myclientid-3", "myclientid-ga");
|
||||||
assertRegistrarExists("myclientid-4", "myclientid-ga");
|
assertRegistrarExists("myclientid-4", "myclientid-ga");
|
||||||
assertRegistrarExists("myclientid-5", "myclientid-eap");
|
assertRegistrarExists("myclientid-5", "myclientid-eap");
|
||||||
assertContactExists("myclientid-1", "email@example.com");
|
verifyUser("myclientid-1", "email@example.com");
|
||||||
assertContactExists("myclientid-3", "email@example.com");
|
verifyUser("myclientid-3", "email@example.com");
|
||||||
assertContactExists("myclientid-4", "email@example.com");
|
verifyUser("myclientid-4", "email@example.com");
|
||||||
assertContactExists("myclientid-5", "email@example.com");
|
verifyUser("myclientid-5", "email@example.com");
|
||||||
assertContactExists("myclientid-1", "other@example.com");
|
verifyUser("myclientid-1", "other@example.com");
|
||||||
assertContactExists("myclientid-3", "other@example.com");
|
verifyUser("myclientid-3", "other@example.com");
|
||||||
assertContactExists("myclientid-4", "other@example.com");
|
verifyUser("myclientid-4", "other@example.com");
|
||||||
assertContactExists("myclientid-5", "other@example.com");
|
verifyUser("myclientid-5", "other@example.com");
|
||||||
assertContactExists("myclientid-1", "someone@example.com");
|
verifyUser("myclientid-1", "someone@example.com");
|
||||||
assertContactExists("myclientid-3", "someone@example.com");
|
verifyUser("myclientid-3", "someone@example.com");
|
||||||
assertContactExists("myclientid-4", "someone@example.com");
|
verifyUser("myclientid-4", "someone@example.com");
|
||||||
assertContactExists("myclientid-5", "someone@example.com");
|
verifyUser("myclientid-5", "someone@example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -223,7 +279,7 @@ public final class OteAccountBuilderTest {
|
|||||||
OteAccountBuilder oteSetupHelper = OteAccountBuilder.forRegistrarId("myclientid");
|
OteAccountBuilder oteSetupHelper = OteAccountBuilder.forRegistrarId("myclientid");
|
||||||
|
|
||||||
IllegalStateException thrown =
|
IllegalStateException thrown =
|
||||||
assertThrows(IllegalStateException.class, () -> oteSetupHelper.buildAndPersist());
|
assertThrows(IllegalStateException.class, oteSetupHelper::buildAndPersist);
|
||||||
assertThat(thrown)
|
assertThat(thrown)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.contains("Found existing object(s) conflicting with OT&E objects");
|
.contains("Found existing object(s) conflicting with OT&E objects");
|
||||||
@@ -236,7 +292,7 @@ public final class OteAccountBuilderTest {
|
|||||||
OteAccountBuilder oteSetupHelper = OteAccountBuilder.forRegistrarId("myclientid");
|
OteAccountBuilder oteSetupHelper = OteAccountBuilder.forRegistrarId("myclientid");
|
||||||
|
|
||||||
IllegalStateException thrown =
|
IllegalStateException thrown =
|
||||||
assertThrows(IllegalStateException.class, () -> oteSetupHelper.buildAndPersist());
|
assertThrows(IllegalStateException.class, oteSetupHelper::buildAndPersist);
|
||||||
assertThat(thrown)
|
assertThat(thrown)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.contains("Found existing object(s) conflicting with OT&E objects");
|
.contains("Found existing object(s) conflicting with OT&E objects");
|
||||||
@@ -261,7 +317,7 @@ public final class OteAccountBuilderTest {
|
|||||||
void testCreateOteEntities_doubleCreation_actuallyReplaces() {
|
void testCreateOteEntities_doubleCreation_actuallyReplaces() {
|
||||||
OteAccountBuilder.forRegistrarId("myclientid")
|
OteAccountBuilder.forRegistrarId("myclientid")
|
||||||
.setPassword("oldPassword")
|
.setPassword("oldPassword")
|
||||||
.addContact("email@example.com")
|
.addUser("email@example.com")
|
||||||
.buildAndPersist();
|
.buildAndPersist();
|
||||||
|
|
||||||
assertThat(Registrar.loadByRegistrarId("myclientid-3").get().verifyPassword("oldPassword"))
|
assertThat(Registrar.loadByRegistrarId("myclientid-3").get().verifyPassword("oldPassword"))
|
||||||
@@ -269,7 +325,7 @@ public final class OteAccountBuilderTest {
|
|||||||
|
|
||||||
OteAccountBuilder.forRegistrarId("myclientid")
|
OteAccountBuilder.forRegistrarId("myclientid")
|
||||||
.setPassword("newPassword")
|
.setPassword("newPassword")
|
||||||
.addContact("email@example.com")
|
.addUser("email@example.com")
|
||||||
.setReplaceExisting(true)
|
.setReplaceExisting(true)
|
||||||
.buildAndPersist();
|
.buildAndPersist();
|
||||||
|
|
||||||
@@ -281,19 +337,17 @@ public final class OteAccountBuilderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCreateOteEntities_doubleCreation_keepsOldContacts() {
|
void testCreateOteEntities_doubleCreation_keepsOldContacts() {
|
||||||
OteAccountBuilder.forRegistrarId("myclientid")
|
OteAccountBuilder.forRegistrarId("myclientid").addUser("email@example.com").buildAndPersist();
|
||||||
.addContact("email@example.com")
|
|
||||||
.buildAndPersist();
|
|
||||||
|
|
||||||
assertContactExists("myclientid-3", "email@example.com");
|
verifyUser("myclientid-3", "email@example.com");
|
||||||
|
|
||||||
OteAccountBuilder.forRegistrarId("myclientid")
|
OteAccountBuilder.forRegistrarId("myclientid")
|
||||||
.addContact("other@example.com")
|
.addUser("other@example.com")
|
||||||
.setReplaceExisting(true)
|
.setReplaceExisting(true)
|
||||||
.buildAndPersist();
|
.buildAndPersist();
|
||||||
|
|
||||||
assertContactExists("myclientid-3", "other@example.com");
|
verifyUser("myclientid-3", "other@example.com");
|
||||||
assertContactExists("myclientid-3", "email@example.com");
|
verifyUser("myclientid-3", "email@example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -79,9 +79,7 @@ public final class OteStatsTestHelper {
|
|||||||
public static void setupIncompleteOte(String baseClientId) throws IOException {
|
public static void setupIncompleteOte(String baseClientId) throws IOException {
|
||||||
createTld("tld");
|
createTld("tld");
|
||||||
persistPremiumList("default_sandbox_list", USD, "sandbox,USD 1000");
|
persistPremiumList("default_sandbox_list", USD, "sandbox,USD 1000");
|
||||||
OteAccountBuilder.forRegistrarId(baseClientId)
|
OteAccountBuilder.forRegistrarId(baseClientId).buildAndPersist();
|
||||||
.addContact("email@example.com")
|
|
||||||
.buildAndPersist();
|
|
||||||
String oteAccount1 = String.format("%s-1", baseClientId);
|
String oteAccount1 = String.format("%s-1", baseClientId);
|
||||||
DateTime now = DateTime.now(DateTimeZone.UTC);
|
DateTime now = DateTime.now(DateTimeZone.UTC);
|
||||||
persistResource(
|
persistResource(
|
||||||
|
|||||||
@@ -16,11 +16,21 @@ package google.registry.model.console;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||||
|
import static google.registry.model.console.User.IAP_SECURED_WEB_APP_USER_ROLE;
|
||||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
|
import com.google.cloud.tasks.v2.HttpMethod;
|
||||||
|
import google.registry.batch.CloudTasksUtils;
|
||||||
import google.registry.model.EntityTestCase;
|
import google.registry.model.EntityTestCase;
|
||||||
|
import google.registry.testing.CloudTasksHelper;
|
||||||
|
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||||
import google.registry.testing.DatabaseHelper;
|
import google.registry.testing.DatabaseHelper;
|
||||||
|
import google.registry.tools.IamClient;
|
||||||
|
import java.util.Optional;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/** Tests for {@link User}. */
|
/** Tests for {@link User}. */
|
||||||
@@ -104,4 +114,56 @@ public class UserTest extends EntityTestCase {
|
|||||||
assertThat(user.hasRegistryLockPassword()).isFalse();
|
assertThat(user.hasRegistryLockPassword()).isFalse();
|
||||||
assertThat(user.verifyRegistryLockPassword("foobar")).isFalse();
|
assertThat(user.verifyRegistryLockPassword("foobar")).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGrantIapPermission() {
|
||||||
|
CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||||
|
IamClient iamClient = mock(IamClient.class);
|
||||||
|
CloudTasksUtils cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
|
|
||||||
|
// Individual permission.
|
||||||
|
User.grantIapPermission("email@example.com", Optional.empty(), cloudTasksUtils, iamClient);
|
||||||
|
cloudTasksHelper.assertNoTasksEnqueued();
|
||||||
|
verify(iamClient).addBinding("email@example.com", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
|
|
||||||
|
// Group membership.
|
||||||
|
User.grantIapPermission(
|
||||||
|
"email@example.com", Optional.of("console@example.com"), cloudTasksUtils, iamClient);
|
||||||
|
cloudTasksHelper.assertTasksEnqueued(
|
||||||
|
"console-user-group-update",
|
||||||
|
new TaskMatcher()
|
||||||
|
.service("TOOLS")
|
||||||
|
.method(HttpMethod.POST)
|
||||||
|
.path("/_dr/admin/updateUserGroup")
|
||||||
|
.param("userEmailAddress", "email@example.com")
|
||||||
|
.param("groupEmailAddress", "console@example.com")
|
||||||
|
.param("groupUpdateMode", "ADD"));
|
||||||
|
verifyNoMoreInteractions(iamClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRevokeIapPermission() {
|
||||||
|
CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||||
|
IamClient iamClient = mock(IamClient.class);
|
||||||
|
CloudTasksUtils cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
|
|
||||||
|
// Individual permission.
|
||||||
|
User.revokeIapPermission("email@example.com", Optional.empty(), cloudTasksUtils, iamClient);
|
||||||
|
cloudTasksHelper.assertNoTasksEnqueued();
|
||||||
|
verify(iamClient).removeBinding("email@example.com", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
|
|
||||||
|
// Group membership.
|
||||||
|
User.revokeIapPermission(
|
||||||
|
"email@example.com", Optional.of("console@example.com"), cloudTasksUtils, iamClient);
|
||||||
|
cloudTasksHelper.assertTasksEnqueued(
|
||||||
|
"console-user-group-update",
|
||||||
|
new TaskMatcher()
|
||||||
|
.service("TOOLS")
|
||||||
|
.method(HttpMethod.POST)
|
||||||
|
.path("/_dr/admin/updateUserGroup")
|
||||||
|
.param("userEmailAddress", "email@example.com")
|
||||||
|
.param("groupEmailAddress", "console@example.com")
|
||||||
|
.param("groupUpdateMode", "REMOVE"));
|
||||||
|
verifyNoMoreInteractions(iamClient);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public final class RegistryTestServerMain {
|
|||||||
|
|
||||||
final RegistryTestServer server = new RegistryTestServer(address);
|
final RegistryTestServer server = new RegistryTestServer(address);
|
||||||
|
|
||||||
System.out.printf("%sLoading SQL fixtures and User service...%s\n", BLUE, RESET);
|
System.out.printf("%sLoading SQL fixtures setting User for authentication...%s\n", BLUE, RESET);
|
||||||
UserRoles userRoles =
|
UserRoles userRoles =
|
||||||
new UserRoles.Builder().setIsAdmin(loginIsAdmin).setGlobalRole(GlobalRole.FTE).build();
|
new UserRoles.Builder().setIsAdmin(loginIsAdmin).setGlobalRole(GlobalRole.FTE).build();
|
||||||
User user =
|
User user =
|
||||||
@@ -151,7 +151,7 @@ public final class RegistryTestServerMain {
|
|||||||
for (Fixture fixture : fixtures) {
|
for (Fixture fixture : fixtures) {
|
||||||
fixture.load();
|
fixture.load();
|
||||||
}
|
}
|
||||||
System.out.printf("%sStarting Jetty6 HTTP Server...%s\n", BLUE, RESET);
|
System.out.printf("%sStarting Jetty HTTP Server...%s\n", BLUE, RESET);
|
||||||
server.start();
|
server.start();
|
||||||
System.out.printf("%sListening on: %s%s\n", PURPLE, server.getUrl("/"), RESET);
|
System.out.printf("%sListening on: %s%s\n", PURPLE, server.getUrl("/"), RESET);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
import com.google.common.util.concurrent.SimpleTimeLimiter;
|
import com.google.common.util.concurrent.SimpleTimeLimiter;
|
||||||
import google.registry.ui.server.registrar.RegistrarSettingsAction;
|
import google.registry.util.RegistryEnvironment;
|
||||||
import google.registry.util.UrlChecker;
|
import google.registry.util.UrlChecker;
|
||||||
import jakarta.servlet.http.HttpServlet;
|
import jakarta.servlet.http.HttpServlet;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
@@ -91,7 +91,7 @@ public final class TestServer {
|
|||||||
/** Starts the HTTP server in a new thread and returns once it's online. */
|
/** Starts the HTTP server in a new thread and returns once it's online. */
|
||||||
public void start() {
|
public void start() {
|
||||||
try {
|
try {
|
||||||
RegistrarSettingsAction.setIsInTestDriverToTrue();
|
RegistryEnvironment.setIsInTestDriver(true);
|
||||||
server.start();
|
server.start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throwIfUnchecked(e);
|
throwIfUnchecked(e);
|
||||||
@@ -129,7 +129,7 @@ public final class TestServer {
|
|||||||
.callWithTimeout(
|
.callWithTimeout(
|
||||||
() -> {
|
() -> {
|
||||||
server.stop();
|
server.stop();
|
||||||
RegistrarSettingsAction.setIsInTestDriverToFalse();
|
RegistryEnvironment.setIsInTestDriver(false);
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
SHUTDOWN_TIMEOUT_MS,
|
SHUTDOWN_TIMEOUT_MS,
|
||||||
|
|||||||
@@ -80,12 +80,12 @@ import org.joda.time.DateTime;
|
|||||||
* to the same test task container that the original instance pushes to, so that we can make
|
* to the same test task container that the original instance pushes to, so that we can make
|
||||||
* assertions on them by accessing the original instance. We cannot make the test task container
|
* assertions on them by accessing the original instance. We cannot make the test task container
|
||||||
* itself static because we do not want tasks enqueued in previous tests to interfere with latter
|
* itself static because we do not want tasks enqueued in previous tests to interfere with latter
|
||||||
* tests, when they run on the same JVM (and therefore share the same static class members). To
|
* tests when they run on the same JVM (and therefore share the same static class members). To solve
|
||||||
* solve this we put the test container in a static map whose keys are the instance IDs. An
|
* this, we put the test container in a static map whose keys are the instance IDs. An explicitly
|
||||||
* explicitly created new {@link CloudTasksHelper} (as would be created for a new test method) would
|
* created new {@link CloudTasksHelper} (as would be created for a new test method) would have a new
|
||||||
* have a new ID allocated to it, and therefore stores its tasks in a distinct container. A
|
* ID allocated to it, and therefore stores its tasks in a distinct container. A deserialized {@link
|
||||||
* deserialized {@link CloudTasksHelper}, on the other hand, will have the same instance ID and
|
* CloudTasksHelper}, on the other hand, will have the same instance ID and share the same test
|
||||||
* share the same test class container with its progenitor.
|
* class container with its progenitor.
|
||||||
*/
|
*/
|
||||||
public class CloudTasksHelper implements Serializable {
|
public class CloudTasksHelper implements Serializable {
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ public class CloudTasksHelper implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public void assertTasksEnqueuedWithProperty(
|
public void assertTasksEnqueuedWithProperty(
|
||||||
String queueName, Function<Task, String> propertyGetter, String... expectedTaskProperties) {
|
String queueName, Function<Task, String> propertyGetter, String... expectedTaskProperties) {
|
||||||
// Ordering is irrelevant but duplicates should be considered independently.
|
// Ordering is irrelevant, but duplicates should be considered independently.
|
||||||
assertThat(getTestTasksFor(queueName).stream().map(propertyGetter))
|
assertThat(getTestTasksFor(queueName).stream().map(propertyGetter))
|
||||||
.containsExactly((Object[]) expectedTaskProperties);
|
.containsExactly((Object[]) expectedTaskProperties);
|
||||||
}
|
}
|
||||||
@@ -285,7 +285,7 @@ public class CloudTasksHelper implements Serializable {
|
|||||||
});
|
});
|
||||||
headers = headerBuilder.build();
|
headers = headerBuilder.build();
|
||||||
ImmutableMultimap.Builder<String, String> paramBuilder = new ImmutableMultimap.Builder<>();
|
ImmutableMultimap.Builder<String, String> paramBuilder = new ImmutableMultimap.Builder<>();
|
||||||
// Note that UriParameters.parse() does not throw an IAE on a bad query string (e.g. one
|
// Note that UriParameters.parse() does not throw an IAE on a bad query string (e.g., one
|
||||||
// where parameters are not properly URL-encoded); it always does a best-effort parse.
|
// where parameters are not properly URL-encoded); it always does a best-effort parse.
|
||||||
if (method == HttpMethod.GET && uri.getQuery() != null) {
|
if (method == HttpMethod.GET && uri.getQuery() != null) {
|
||||||
paramBuilder.putAll(UriParameters.parse(uri.getQuery()));
|
paramBuilder.putAll(UriParameters.parse(uri.getQuery()));
|
||||||
@@ -382,7 +382,7 @@ public class CloudTasksHelper implements Serializable {
|
|||||||
* the same contract as {@link #equals}, since it will ignore null fields.
|
* the same contract as {@link #equals}, since it will ignore null fields.
|
||||||
*
|
*
|
||||||
* <p>Match fails if any headers or params expected on the TaskMatcher are not found on the
|
* <p>Match fails if any headers or params expected on the TaskMatcher are not found on the
|
||||||
* Task. Note that the inverse is not true (i.e. there may be extra headers on the Task).
|
* Task. Note that the inverse is not true (i.e., there may be extra headers on the Task).
|
||||||
*
|
*
|
||||||
* <p>Schedule time by default is Timestamp.getDefaultInstance() or null.
|
* <p>Schedule time by default is Timestamp.getDefaultInstance() or null.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -15,20 +15,22 @@
|
|||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.tools.CreateUserCommand.IAP_SECURED_WEB_APP_USER_ROLE;
|
import static google.registry.model.console.User.IAP_SECURED_WEB_APP_USER_ROLE;
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoInteractions;
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
|
import com.google.cloud.tasks.v2.HttpMethod;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.net.MediaType;
|
|
||||||
import google.registry.model.console.GlobalRole;
|
import google.registry.model.console.GlobalRole;
|
||||||
import google.registry.model.console.RegistrarRole;
|
import google.registry.model.console.RegistrarRole;
|
||||||
import google.registry.model.console.User;
|
import google.registry.model.console.User;
|
||||||
import google.registry.model.console.UserDao;
|
import google.registry.model.console.UserDao;
|
||||||
|
import google.registry.testing.CloudTasksHelper;
|
||||||
|
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||||
import google.registry.testing.DatabaseHelper;
|
import google.registry.testing.DatabaseHelper;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@@ -38,13 +40,13 @@ import org.junit.jupiter.api.Test;
|
|||||||
public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
||||||
|
|
||||||
private final IamClient iamClient = mock(IamClient.class);
|
private final IamClient iamClient = mock(IamClient.class);
|
||||||
private final ServiceConnection connection = mock(ServiceConnection.class);
|
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void beforeEach() {
|
void beforeEach() {
|
||||||
command.iamClient = iamClient;
|
command.iamClient = iamClient;
|
||||||
command.maybeGroupEmailAddress = Optional.empty();
|
command.maybeGroupEmailAddress = Optional.empty();
|
||||||
command.setConnection(connection);
|
command.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -57,7 +59,7 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
|||||||
assertThat(onlyUser.getUserRoles().getRegistrarRoles()).isEmpty();
|
assertThat(onlyUser.getUserRoles().getRegistrarRoles()).isEmpty();
|
||||||
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
verifyNoMoreInteractions(iamClient);
|
verifyNoMoreInteractions(iamClient);
|
||||||
verifyNoInteractions(connection);
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -69,20 +71,16 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
|||||||
assertThat(onlyUser.getUserRoles().isAdmin()).isFalse();
|
assertThat(onlyUser.getUserRoles().isAdmin()).isFalse();
|
||||||
assertThat(onlyUser.getUserRoles().getGlobalRole()).isEqualTo(GlobalRole.NONE);
|
assertThat(onlyUser.getUserRoles().getGlobalRole()).isEqualTo(GlobalRole.NONE);
|
||||||
assertThat(onlyUser.getUserRoles().getRegistrarRoles()).isEmpty();
|
assertThat(onlyUser.getUserRoles().getRegistrarRoles()).isEmpty();
|
||||||
verify(connection)
|
cloudTasksHelper.assertTasksEnqueued(
|
||||||
.sendPostRequest(
|
"console-user-group-update",
|
||||||
"/_dr/admin/updateUserGroup",
|
new TaskMatcher()
|
||||||
ImmutableMap.of(
|
.method(HttpMethod.POST)
|
||||||
"userEmailAddress",
|
.service("TOOLS")
|
||||||
"user@example.test",
|
.path("/_dr/admin/updateUserGroup")
|
||||||
"groupEmailAddress",
|
.param("userEmailAddress", "user@example.test")
|
||||||
"group@example.test",
|
.param("groupEmailAddress", "group@example.test")
|
||||||
"groupUpdateMode",
|
.param("groupUpdateMode", "ADD"));
|
||||||
"ADD"),
|
|
||||||
MediaType.PLAIN_TEXT_UTF_8,
|
|
||||||
new byte[0]);
|
|
||||||
verifyNoInteractions(iamClient);
|
verifyNoInteractions(iamClient);
|
||||||
verifyNoMoreInteractions(connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -102,7 +100,7 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
|||||||
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().isAdmin()).isTrue();
|
assertThat(UserDao.loadUser("user@example.test").get().getUserRoles().isAdmin()).isTrue();
|
||||||
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
verifyNoMoreInteractions(iamClient);
|
verifyNoMoreInteractions(iamClient);
|
||||||
verifyNoInteractions(connection);
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -112,7 +110,7 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
|||||||
.isEqualTo(GlobalRole.FTE);
|
.isEqualTo(GlobalRole.FTE);
|
||||||
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
verifyNoMoreInteractions(iamClient);
|
verifyNoMoreInteractions(iamClient);
|
||||||
verifyNoInteractions(connection);
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -131,7 +129,7 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
|||||||
RegistrarRole.PRIMARY_CONTACT));
|
RegistrarRole.PRIMARY_CONTACT));
|
||||||
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
verify(iamClient).addBinding("user@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
verifyNoMoreInteractions(iamClient);
|
verifyNoMoreInteractions(iamClient);
|
||||||
verifyNoInteractions(connection);
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -146,7 +144,7 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
|
|||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo("A user with email user@example.test already exists");
|
.isEqualTo("A user with email user@example.test already exists");
|
||||||
verifyNoMoreInteractions(iamClient);
|
verifyNoMoreInteractions(iamClient);
|
||||||
verifyNoInteractions(connection);
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -15,16 +15,17 @@
|
|||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.tools.CreateUserCommand.IAP_SECURED_WEB_APP_USER_ROLE;
|
import static google.registry.model.console.User.IAP_SECURED_WEB_APP_USER_ROLE;
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoInteractions;
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.cloud.tasks.v2.HttpMethod;
|
||||||
import com.google.common.net.MediaType;
|
|
||||||
import google.registry.model.console.UserDao;
|
import google.registry.model.console.UserDao;
|
||||||
|
import google.registry.testing.CloudTasksHelper;
|
||||||
|
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||||
import google.registry.testing.DatabaseHelper;
|
import google.registry.testing.DatabaseHelper;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@@ -34,13 +35,13 @@ import org.junit.jupiter.api.Test;
|
|||||||
public class DeleteUserCommandTest extends CommandTestCase<DeleteUserCommand> {
|
public class DeleteUserCommandTest extends CommandTestCase<DeleteUserCommand> {
|
||||||
|
|
||||||
private final IamClient iamClient = mock(IamClient.class);
|
private final IamClient iamClient = mock(IamClient.class);
|
||||||
private final ServiceConnection connection = mock(ServiceConnection.class);
|
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void beforeEach() {
|
void beforeEach() {
|
||||||
command.iamClient = iamClient;
|
command.iamClient = iamClient;
|
||||||
command.setConnection(connection);
|
|
||||||
command.maybeGroupEmailAddress = Optional.empty();
|
command.maybeGroupEmailAddress = Optional.empty();
|
||||||
|
command.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -51,7 +52,7 @@ public class DeleteUserCommandTest extends CommandTestCase<DeleteUserCommand> {
|
|||||||
assertThat(UserDao.loadUser("email@example.test")).isEmpty();
|
assertThat(UserDao.loadUser("email@example.test")).isEmpty();
|
||||||
verify(iamClient).removeBinding("email@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
verify(iamClient).removeBinding("email@example.test", IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
verifyNoMoreInteractions(iamClient);
|
verifyNoMoreInteractions(iamClient);
|
||||||
verifyNoInteractions(connection);
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -61,20 +62,16 @@ public class DeleteUserCommandTest extends CommandTestCase<DeleteUserCommand> {
|
|||||||
assertThat(UserDao.loadUser("email@example.test")).isPresent();
|
assertThat(UserDao.loadUser("email@example.test")).isPresent();
|
||||||
runCommandForced("--email", "email@example.test");
|
runCommandForced("--email", "email@example.test");
|
||||||
assertThat(UserDao.loadUser("email@example.test")).isEmpty();
|
assertThat(UserDao.loadUser("email@example.test")).isEmpty();
|
||||||
verify(connection)
|
cloudTasksHelper.assertTasksEnqueued(
|
||||||
.sendPostRequest(
|
"console-user-group-update",
|
||||||
"/_dr/admin/updateUserGroup",
|
new TaskMatcher()
|
||||||
ImmutableMap.of(
|
.method(HttpMethod.POST)
|
||||||
"userEmailAddress",
|
.service("TOOLS")
|
||||||
"email@example.test",
|
.path("/_dr/admin/updateUserGroup")
|
||||||
"groupEmailAddress",
|
.param("userEmailAddress", "email@example.test")
|
||||||
"group@example.test",
|
.param("groupEmailAddress", "group@example.test")
|
||||||
"groupUpdateMode",
|
.param("groupUpdateMode", "REMOVE"));
|
||||||
"REMOVE"),
|
|
||||||
MediaType.PLAIN_TEXT_UTF_8,
|
|
||||||
new byte[0]);
|
|
||||||
verifyNoInteractions(iamClient);
|
verifyNoInteractions(iamClient);
|
||||||
verifyNoMoreInteractions(connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -86,6 +83,6 @@ public class DeleteUserCommandTest extends CommandTestCase<DeleteUserCommand> {
|
|||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo("Email does not correspond to a valid user");
|
.isEqualTo("Email does not correspond to a valid user");
|
||||||
verifyNoInteractions(iamClient);
|
verifyNoInteractions(iamClient);
|
||||||
verifyNoInteractions(connection);
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.OteAccountBuilderTest.verifyUser;
|
||||||
|
import static google.registry.model.console.User.IAP_SECURED_WEB_APP_USER_ROLE;
|
||||||
import static google.registry.model.registrar.RegistrarBase.State.ACTIVE;
|
import static google.registry.model.registrar.RegistrarBase.State.ACTIVE;
|
||||||
import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
|
import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
|
||||||
import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
|
import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
|
||||||
@@ -26,19 +28,30 @@ import static google.registry.testing.DatabaseHelper.persistResource;
|
|||||||
import static org.joda.money.CurrencyUnit.USD;
|
import static org.joda.money.CurrencyUnit.USD;
|
||||||
import static org.joda.time.DateTimeZone.UTC;
|
import static org.joda.time.DateTimeZone.UTC;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
|
|
||||||
import com.beust.jcommander.ParameterException;
|
import com.beust.jcommander.ParameterException;
|
||||||
|
import com.google.cloud.tasks.v2.HttpMethod;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSortedMap;
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
|
import google.registry.model.console.GlobalRole;
|
||||||
|
import google.registry.model.console.User;
|
||||||
|
import google.registry.model.console.UserDao;
|
||||||
|
import google.registry.model.console.UserRoles;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.model.registrar.RegistrarPoc;
|
|
||||||
import google.registry.model.tld.Tld;
|
import google.registry.model.tld.Tld;
|
||||||
import google.registry.model.tld.Tld.TldState;
|
import google.registry.model.tld.Tld.TldState;
|
||||||
|
import google.registry.testing.CloudTasksHelper;
|
||||||
|
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||||
import google.registry.testing.DeterministicStringGenerator;
|
import google.registry.testing.DeterministicStringGenerator;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.util.CidrAddressBlock;
|
import google.registry.util.CidrAddressBlock;
|
||||||
import java.security.cert.CertificateParsingException;
|
import java.security.cert.CertificateParsingException;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
@@ -50,22 +63,24 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
|
|
||||||
private static final String PASSWORD = "abcdefghijklmnop";
|
private static final String PASSWORD = "abcdefghijklmnop";
|
||||||
|
|
||||||
private DeterministicStringGenerator passwordGenerator =
|
private final IamClient iamClient = mock(IamClient.class);
|
||||||
|
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||||
|
private final DeterministicStringGenerator passwordGenerator =
|
||||||
new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz");
|
new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz");
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void beforeEach() {
|
void beforeEach() {
|
||||||
command.passwordGenerator = passwordGenerator;
|
command.passwordGenerator = passwordGenerator;
|
||||||
command.clock = new FakeClock(DateTime.parse("2018-07-07TZ"));
|
command.clock = new FakeClock(DateTime.parse("2018-07-07TZ"));
|
||||||
|
command.maybeGroupEmailAddress = Optional.of("group@example.com");
|
||||||
|
command.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
|
command.iamClient = iamClient;
|
||||||
persistPremiumList("default_sandbox_list", USD, "sandbox,USD 1000");
|
persistPremiumList("default_sandbox_list", USD, "sandbox,USD 1000");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Verify TLD creation. */
|
/** Verify TLD creation. */
|
||||||
private void verifyTldCreation(
|
private void verifyTldCreation(
|
||||||
String tldName,
|
String tldName, String roidSuffix, TldState tldState, boolean isEarlyAccess) {
|
||||||
String roidSuffix,
|
|
||||||
TldState tldState,
|
|
||||||
boolean isEarlyAccess) {
|
|
||||||
Tld registry = Tld.get(tldName);
|
Tld registry = Tld.get(tldName);
|
||||||
assertThat(registry).isNotNull();
|
assertThat(registry).isNotNull();
|
||||||
assertThat(registry.getRoidSuffix()).isEqualTo(roidSuffix);
|
assertThat(registry.getRoidSuffix()).isEqualTo(roidSuffix);
|
||||||
@@ -107,13 +122,28 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
assertThat(registrar.getClientCertificateHash()).hasValue(SAMPLE_CERT_HASH);
|
assertThat(registrar.getClientCertificateHash()).hasValue(SAMPLE_CERT_HASH);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyRegistrarContactCreation(String registrarName, String email) {
|
private void verifyIapPermission(@Nullable String emailAddress) {
|
||||||
ImmutableSet<RegistrarPoc> registrarPocs = loadRegistrar(registrarName).getContacts();
|
if (emailAddress == null) {
|
||||||
assertThat(registrarPocs).hasSize(1);
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
RegistrarPoc registrarPoc = registrarPocs.stream().findAny().get();
|
verifyNoInteractions(iamClient);
|
||||||
assertThat(registrarPoc.getEmailAddress()).isEqualTo(email);
|
} else {
|
||||||
assertThat(registrarPoc.getName()).isEqualTo(email);
|
String groupEmailAddress = command.maybeGroupEmailAddress.orElse(null);
|
||||||
assertThat(registrarPoc.getLoginEmailAddress()).isEqualTo(email);
|
if (groupEmailAddress == null) {
|
||||||
|
cloudTasksHelper.assertNoTasksEnqueued("console-user-group-update");
|
||||||
|
verify(iamClient).addBinding(emailAddress, IAP_SECURED_WEB_APP_USER_ROLE);
|
||||||
|
} else {
|
||||||
|
cloudTasksHelper.assertTasksEnqueued(
|
||||||
|
"console-user-group-update",
|
||||||
|
new TaskMatcher()
|
||||||
|
.service("TOOLS")
|
||||||
|
.method(HttpMethod.POST)
|
||||||
|
.path("/_dr/admin/updateUserGroup")
|
||||||
|
.param("userEmailAddress", emailAddress)
|
||||||
|
.param("groupEmailAddress", groupEmailAddress)
|
||||||
|
.param("groupUpdateMode", "ADD"));
|
||||||
|
verifyNoInteractions(iamClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -136,10 +166,12 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
verifyRegistrarCreation("blobio-4", "blobio-ga", PASSWORD, ipAddress);
|
verifyRegistrarCreation("blobio-4", "blobio-ga", PASSWORD, ipAddress);
|
||||||
verifyRegistrarCreation("blobio-5", "blobio-eap", PASSWORD, ipAddress);
|
verifyRegistrarCreation("blobio-5", "blobio-eap", PASSWORD, ipAddress);
|
||||||
|
|
||||||
verifyRegistrarContactCreation("blobio-1", "contact@email.com");
|
verifyUser("blobio-1", "contact@email.com");
|
||||||
verifyRegistrarContactCreation("blobio-3", "contact@email.com");
|
verifyUser("blobio-3", "contact@email.com");
|
||||||
verifyRegistrarContactCreation("blobio-4", "contact@email.com");
|
verifyUser("blobio-4", "contact@email.com");
|
||||||
verifyRegistrarContactCreation("blobio-5", "contact@email.com");
|
verifyUser("blobio-5", "contact@email.com");
|
||||||
|
|
||||||
|
verifyIapPermission("contact@email.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -162,10 +194,12 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
verifyRegistrarCreation("abc-4", "abc-ga", PASSWORD, ipAddress);
|
verifyRegistrarCreation("abc-4", "abc-ga", PASSWORD, ipAddress);
|
||||||
verifyRegistrarCreation("abc-5", "abc-eap", PASSWORD, ipAddress);
|
verifyRegistrarCreation("abc-5", "abc-eap", PASSWORD, ipAddress);
|
||||||
|
|
||||||
verifyRegistrarContactCreation("abc-1", "abc@email.com");
|
verifyUser("abc-1", "abc@email.com");
|
||||||
verifyRegistrarContactCreation("abc-3", "abc@email.com");
|
verifyUser("abc-3", "abc@email.com");
|
||||||
verifyRegistrarContactCreation("abc-4", "abc@email.com");
|
verifyUser("abc-4", "abc@email.com");
|
||||||
verifyRegistrarContactCreation("abc-5", "abc@email.com");
|
verifyUser("abc-5", "abc@email.com");
|
||||||
|
|
||||||
|
verifyIapPermission("abc@email.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -180,19 +214,20 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
verifyTldCreation("blobio-ga", "BLOBIOG2", GENERAL_AVAILABILITY, false);
|
verifyTldCreation("blobio-ga", "BLOBIOG2", GENERAL_AVAILABILITY, false);
|
||||||
verifyTldCreation("blobio-eap", "BLOBIOE3", GENERAL_AVAILABILITY, true);
|
verifyTldCreation("blobio-eap", "BLOBIOE3", GENERAL_AVAILABILITY, true);
|
||||||
|
|
||||||
ImmutableList<CidrAddressBlock> ipAddresses = ImmutableList.of(
|
ImmutableList<CidrAddressBlock> ipAddresses =
|
||||||
CidrAddressBlock.create("1.1.1.1"),
|
ImmutableList.of(CidrAddressBlock.create("1.1.1.1"), CidrAddressBlock.create("2.2.2.2"));
|
||||||
CidrAddressBlock.create("2.2.2.2"));
|
|
||||||
|
|
||||||
verifyRegistrarCreation("blobio-1", "blobio-sunrise", PASSWORD, ipAddresses);
|
verifyRegistrarCreation("blobio-1", "blobio-sunrise", PASSWORD, ipAddresses);
|
||||||
verifyRegistrarCreation("blobio-3", "blobio-ga", PASSWORD, ipAddresses);
|
verifyRegistrarCreation("blobio-3", "blobio-ga", PASSWORD, ipAddresses);
|
||||||
verifyRegistrarCreation("blobio-4", "blobio-ga", PASSWORD, ipAddresses);
|
verifyRegistrarCreation("blobio-4", "blobio-ga", PASSWORD, ipAddresses);
|
||||||
verifyRegistrarCreation("blobio-5", "blobio-eap", PASSWORD, ipAddresses);
|
verifyRegistrarCreation("blobio-5", "blobio-eap", PASSWORD, ipAddresses);
|
||||||
|
|
||||||
verifyRegistrarContactCreation("blobio-1", "contact@email.com");
|
verifyUser("blobio-1", "contact@email.com");
|
||||||
verifyRegistrarContactCreation("blobio-3", "contact@email.com");
|
verifyUser("blobio-3", "contact@email.com");
|
||||||
verifyRegistrarContactCreation("blobio-4", "contact@email.com");
|
verifyUser("blobio-4", "contact@email.com");
|
||||||
verifyRegistrarContactCreation("blobio-5", "contact@email.com");
|
verifyUser("blobio-5", "contact@email.com");
|
||||||
|
|
||||||
|
verifyIapPermission("contact@email.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -206,6 +241,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=" + getCertFilename()));
|
"--certfile=" + getCertFilename()));
|
||||||
assertThat(thrown).hasMessageThat().contains("option is required: [-a | --ip_allow_list]");
|
assertThat(thrown).hasMessageThat().contains("option is required: [-a | --ip_allow_list]");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -219,6 +255,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=" + getCertFilename()));
|
"--certfile=" + getCertFilename()));
|
||||||
assertThat(thrown).hasMessageThat().contains("option is required: [-r | --registrar]");
|
assertThat(thrown).hasMessageThat().contains("option is required: [-r | --registrar]");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -232,6 +269,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
assertThat(thrown)
|
assertThat(thrown)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.contains("Must specify exactly one client certificate file.");
|
.contains("Must specify exactly one client certificate file.");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -245,6 +283,36 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--certfile=" + getCertFilename(),
|
"--certfile=" + getCertFilename(),
|
||||||
"--registrar=blobio"));
|
"--registrar=blobio"));
|
||||||
assertThat(thrown).hasMessageThat().contains("option is required: [--email]");
|
assertThat(thrown).hasMessageThat().contains("option is required: [--email]");
|
||||||
|
verifyIapPermission(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSuccess_noConsoleUserGroup() throws Exception {
|
||||||
|
command.maybeGroupEmailAddress = Optional.empty();
|
||||||
|
runCommandForced(
|
||||||
|
"--ip_allow_list=1.1.1.1",
|
||||||
|
"--registrar=blobio",
|
||||||
|
"--email=contact@email.com",
|
||||||
|
"--certfile=" + getCertFilename());
|
||||||
|
|
||||||
|
verifyTldCreation("blobio-sunrise", "BLOBIOS0", START_DATE_SUNRISE, false);
|
||||||
|
verifyTldCreation("blobio-ga", "BLOBIOG2", GENERAL_AVAILABILITY, false);
|
||||||
|
verifyTldCreation("blobio-eap", "BLOBIOE3", GENERAL_AVAILABILITY, true);
|
||||||
|
|
||||||
|
ImmutableList<CidrAddressBlock> ipAddress =
|
||||||
|
ImmutableList.of(CidrAddressBlock.create("1.1.1.1"));
|
||||||
|
|
||||||
|
verifyRegistrarCreation("blobio-1", "blobio-sunrise", PASSWORD, ipAddress);
|
||||||
|
verifyRegistrarCreation("blobio-3", "blobio-ga", PASSWORD, ipAddress);
|
||||||
|
verifyRegistrarCreation("blobio-4", "blobio-ga", PASSWORD, ipAddress);
|
||||||
|
verifyRegistrarCreation("blobio-5", "blobio-eap", PASSWORD, ipAddress);
|
||||||
|
|
||||||
|
verifyUser("blobio-1", "contact@email.com");
|
||||||
|
verifyUser("blobio-3", "contact@email.com");
|
||||||
|
verifyUser("blobio-4", "contact@email.com");
|
||||||
|
verifyUser("blobio-5", "contact@email.com");
|
||||||
|
|
||||||
|
verifyIapPermission("contact@email.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -259,6 +327,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=/dev/null"));
|
"--certfile=/dev/null"));
|
||||||
assertThat(thrown).hasMessageThat().contains("No X509Certificate found");
|
assertThat(thrown).hasMessageThat().contains("No X509Certificate found");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -273,6 +342,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=" + getCertFilename()));
|
"--certfile=" + getCertFilename()));
|
||||||
assertThat(thrown).hasMessageThat().contains("Invalid registrar name: 3blo-bio");
|
assertThat(thrown).hasMessageThat().contains("Invalid registrar name: 3blo-bio");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -287,6 +357,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=" + getCertFilename()));
|
"--certfile=" + getCertFilename()));
|
||||||
assertThat(thrown).hasMessageThat().contains("Invalid registrar name: bl");
|
assertThat(thrown).hasMessageThat().contains("Invalid registrar name: bl");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -301,6 +372,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=" + getCertFilename()));
|
"--certfile=" + getCertFilename()));
|
||||||
assertThat(thrown).hasMessageThat().contains("Invalid registrar name: blobiotoooolong");
|
assertThat(thrown).hasMessageThat().contains("Invalid registrar name: blobiotoooolong");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -315,6 +387,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=" + getCertFilename()));
|
"--certfile=" + getCertFilename()));
|
||||||
assertThat(thrown).hasMessageThat().contains("Invalid registrar name: blo#bio");
|
assertThat(thrown).hasMessageThat().contains("Invalid registrar name: blo#bio");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -330,6 +403,7 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=" + getCertFilename()));
|
"--certfile=" + getCertFilename()));
|
||||||
assertThat(thrown).hasMessageThat().contains("VKey<Tld>(sql:blobio-sunrise)");
|
assertThat(thrown).hasMessageThat().contains("VKey<Tld>(sql:blobio-sunrise)");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -345,6 +419,8 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
|
|
||||||
verifyTldCreation("blobio-sunrise", "BLOBIOS0", START_DATE_SUNRISE, false);
|
verifyTldCreation("blobio-sunrise", "BLOBIOS0", START_DATE_SUNRISE, false);
|
||||||
verifyTldCreation("blobio-ga", "BLOBIOG2", GENERAL_AVAILABILITY, false);
|
verifyTldCreation("blobio-ga", "BLOBIOG2", GENERAL_AVAILABILITY, false);
|
||||||
|
|
||||||
|
verifyIapPermission("contact@email.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -366,6 +442,28 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=" + getCertFilename()));
|
"--certfile=" + getCertFilename()));
|
||||||
assertThat(thrown).hasMessageThat().contains("VKey<Registrar>(sql:blobio-1)");
|
assertThat(thrown).hasMessageThat().contains("VKey<Registrar>(sql:blobio-1)");
|
||||||
|
verifyIapPermission(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFailure_userExists() {
|
||||||
|
User user =
|
||||||
|
new User.Builder()
|
||||||
|
.setEmailAddress("contact@email.com")
|
||||||
|
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
||||||
|
.build();
|
||||||
|
UserDao.saveUser(user);
|
||||||
|
IllegalStateException thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalStateException.class,
|
||||||
|
() ->
|
||||||
|
runCommandForced(
|
||||||
|
"--ip_allow_list=1.1.1.1",
|
||||||
|
"--registrar=blobio",
|
||||||
|
"--email=contact@email.com",
|
||||||
|
"--certfile=" + getCertFilename()));
|
||||||
|
assertThat(thrown).hasMessageThat().contains("Found existing users: {contact@email.com");
|
||||||
|
verifyIapPermission(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -385,10 +483,46 @@ class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
|
|||||||
"--email=contact@email.com",
|
"--email=contact@email.com",
|
||||||
"--certfile=" + getCertFilename());
|
"--certfile=" + getCertFilename());
|
||||||
|
|
||||||
ImmutableList<CidrAddressBlock> ipAddress = ImmutableList.of(
|
ImmutableList<CidrAddressBlock> ipAddress =
|
||||||
CidrAddressBlock.create("1.1.1.1"));
|
ImmutableList.of(CidrAddressBlock.create("1.1.1.1"));
|
||||||
|
|
||||||
verifyRegistrarCreation("blobio-1", "blobio-sunrise", PASSWORD, ipAddress);
|
verifyRegistrarCreation("blobio-1", "blobio-sunrise", PASSWORD, ipAddress);
|
||||||
verifyRegistrarCreation("blobio-3", "blobio-ga", PASSWORD, ipAddress);
|
verifyRegistrarCreation("blobio-3", "blobio-ga", PASSWORD, ipAddress);
|
||||||
|
|
||||||
|
verifyIapPermission("contact@email.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSuccess_userExists_replaceExisting() throws Exception {
|
||||||
|
User user =
|
||||||
|
new User.Builder()
|
||||||
|
.setEmailAddress("contact@email.com")
|
||||||
|
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
||||||
|
.build();
|
||||||
|
UserDao.saveUser(user);
|
||||||
|
|
||||||
|
runCommandForced(
|
||||||
|
"--overwrite",
|
||||||
|
"--ip_allow_list=1.1.1.1",
|
||||||
|
"--registrar=blobio",
|
||||||
|
"--email=contact@email.com",
|
||||||
|
"--certfile=" + getCertFilename());
|
||||||
|
|
||||||
|
ImmutableList<CidrAddressBlock> ipAddress =
|
||||||
|
ImmutableList.of(CidrAddressBlock.create("1.1.1.1"));
|
||||||
|
|
||||||
|
verifyRegistrarCreation("blobio-1", "blobio-sunrise", PASSWORD, ipAddress);
|
||||||
|
verifyRegistrarCreation("blobio-3", "blobio-ga", PASSWORD, ipAddress);
|
||||||
|
|
||||||
|
verifyUser("blobio-1", "contact@email.com");
|
||||||
|
verifyUser("blobio-3", "contact@email.com");
|
||||||
|
verifyUser("blobio-4", "contact@email.com");
|
||||||
|
verifyUser("blobio-5", "contact@email.com");
|
||||||
|
|
||||||
|
// verify that the role is completely replaced, e.g., the global role is gone.
|
||||||
|
assertThat(UserDao.loadUser("contact@email.com").get().getUserRoles().getGlobalRole())
|
||||||
|
.isEqualTo(GlobalRole.NONE);
|
||||||
|
|
||||||
|
verifyIapPermission("contact@email.com");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,14 @@
|
|||||||
package google.registry.ui.server.registrar;
|
package google.registry.ui.server.registrar;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.OteAccountBuilderTest.verifyIapPermission;
|
||||||
|
import static google.registry.model.OteAccountBuilderTest.verifyUser;
|
||||||
import static google.registry.model.registrar.Registrar.loadByRegistrarId;
|
import static google.registry.model.registrar.Registrar.loadByRegistrarId;
|
||||||
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
||||||
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||||
import static org.joda.money.CurrencyUnit.USD;
|
import static org.joda.money.CurrencyUnit.USD;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@@ -35,10 +38,12 @@ import google.registry.request.Action.Method;
|
|||||||
import google.registry.request.auth.AuthResult;
|
import google.registry.request.auth.AuthResult;
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||||
import google.registry.security.XsrfTokenManager;
|
import google.registry.security.XsrfTokenManager;
|
||||||
|
import google.registry.testing.CloudTasksHelper;
|
||||||
import google.registry.testing.DeterministicStringGenerator;
|
import google.registry.testing.DeterministicStringGenerator;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.testing.FakeResponse;
|
import google.registry.testing.FakeResponse;
|
||||||
import google.registry.testing.SystemPropertyExtension;
|
import google.registry.testing.SystemPropertyExtension;
|
||||||
|
import google.registry.tools.IamClient;
|
||||||
import google.registry.ui.server.SendEmailUtils;
|
import google.registry.ui.server.SendEmailUtils;
|
||||||
import google.registry.util.EmailMessage;
|
import google.registry.util.EmailMessage;
|
||||||
import google.registry.util.RegistryEnvironment;
|
import google.registry.util.RegistryEnvironment;
|
||||||
@@ -65,6 +70,8 @@ public final class ConsoleOteSetupActionTest {
|
|||||||
@Order(value = Integer.MAX_VALUE)
|
@Order(value = Integer.MAX_VALUE)
|
||||||
final SystemPropertyExtension systemPropertyExtension = new SystemPropertyExtension();
|
final SystemPropertyExtension systemPropertyExtension = new SystemPropertyExtension();
|
||||||
|
|
||||||
|
private final IamClient iamClient = mock(IamClient.class);
|
||||||
|
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||||
private final FakeResponse response = new FakeResponse();
|
private final FakeResponse response = new FakeResponse();
|
||||||
private final ConsoleOteSetupAction action = new ConsoleOteSetupAction();
|
private final ConsoleOteSetupAction action = new ConsoleOteSetupAction();
|
||||||
private final User user =
|
private final User user =
|
||||||
@@ -100,6 +107,9 @@ public final class ConsoleOteSetupActionTest {
|
|||||||
|
|
||||||
action.optionalPassword = Optional.empty();
|
action.optionalPassword = Optional.empty();
|
||||||
action.passwordGenerator = new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz");
|
action.passwordGenerator = new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz");
|
||||||
|
action.maybeGroupEmailAddress = Optional.of("group@example.com");
|
||||||
|
action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
|
action.iamClient = iamClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -142,9 +152,7 @@ public final class ConsoleOteSetupActionTest {
|
|||||||
// checking that all the entities are there or that they have the correct values.
|
// checking that all the entities are there or that they have the correct values.
|
||||||
assertThat(loadByRegistrarId("myclientid-3")).isPresent();
|
assertThat(loadByRegistrarId("myclientid-3")).isPresent();
|
||||||
assertThat(Tld.get("myclientid-ga")).isNotNull();
|
assertThat(Tld.get("myclientid-ga")).isNotNull();
|
||||||
assertThat(
|
verifyUser("myclientid-5", "contact@registry.example");
|
||||||
loadByRegistrarId("myclientid-5").get().getContacts().asList().get(0).getEmailAddress())
|
|
||||||
.isEqualTo("contact@registry.example");
|
|
||||||
assertThat(response.getPayload())
|
assertThat(response.getPayload())
|
||||||
.contains("<h1>OT&E successfully created for registrar myclientid!</h1>");
|
.contains("<h1>OT&E successfully created for registrar myclientid!</h1>");
|
||||||
ArgumentCaptor<EmailMessage> contentCaptor = ArgumentCaptor.forClass(EmailMessage.class);
|
ArgumentCaptor<EmailMessage> contentCaptor = ArgumentCaptor.forClass(EmailMessage.class);
|
||||||
@@ -163,6 +171,14 @@ public final class ConsoleOteSetupActionTest {
|
|||||||
Gave user contact@registry.example web access to these Registrars
|
Gave user contact@registry.example web access to these Registrars
|
||||||
""");
|
""");
|
||||||
assertThat(response.getPayload()).contains("gtag('config', 'sampleId')");
|
assertThat(response.getPayload()).contains("gtag('config', 'sampleId')");
|
||||||
|
verifyIapPermission(
|
||||||
|
"contact@registry.example", action.maybeGroupEmailAddress, cloudTasksHelper, iamClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPost_authorized_noConsoleGroup() {
|
||||||
|
action.maybeGroupEmailAddress = Optional.empty();
|
||||||
|
testPost_authorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -15,10 +15,13 @@
|
|||||||
package google.registry.ui.server.registrar;
|
package google.registry.ui.server.registrar;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.OteAccountBuilderTest.verifyIapPermission;
|
||||||
|
import static google.registry.model.OteAccountBuilderTest.verifyUser;
|
||||||
import static google.registry.model.registrar.Registrar.loadByRegistrarId;
|
import static google.registry.model.registrar.Registrar.loadByRegistrarId;
|
||||||
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
||||||
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||||
import static org.joda.money.CurrencyUnit.USD;
|
import static org.joda.money.CurrencyUnit.USD;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@@ -29,17 +32,18 @@ import google.registry.model.console.User;
|
|||||||
import google.registry.model.console.UserRoles;
|
import google.registry.model.console.UserRoles;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.model.registrar.RegistrarAddress;
|
import google.registry.model.registrar.RegistrarAddress;
|
||||||
import google.registry.model.registrar.RegistrarPoc;
|
|
||||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||||
import google.registry.request.Action.Method;
|
import google.registry.request.Action.Method;
|
||||||
import google.registry.request.auth.AuthResult;
|
import google.registry.request.auth.AuthResult;
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
||||||
import google.registry.security.XsrfTokenManager;
|
import google.registry.security.XsrfTokenManager;
|
||||||
|
import google.registry.testing.CloudTasksHelper;
|
||||||
import google.registry.testing.DeterministicStringGenerator;
|
import google.registry.testing.DeterministicStringGenerator;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.testing.FakeResponse;
|
import google.registry.testing.FakeResponse;
|
||||||
import google.registry.testing.SystemPropertyExtension;
|
import google.registry.testing.SystemPropertyExtension;
|
||||||
|
import google.registry.tools.IamClient;
|
||||||
import google.registry.ui.server.SendEmailUtils;
|
import google.registry.ui.server.SendEmailUtils;
|
||||||
import google.registry.util.EmailMessage;
|
import google.registry.util.EmailMessage;
|
||||||
import google.registry.util.RegistryEnvironment;
|
import google.registry.util.RegistryEnvironment;
|
||||||
@@ -73,6 +77,8 @@ final class ConsoleRegistrarCreatorActionTest {
|
|||||||
.setEmailAddress("marla.singer@example.com")
|
.setEmailAddress("marla.singer@example.com")
|
||||||
.setUserRoles(new UserRoles())
|
.setUserRoles(new UserRoles())
|
||||||
.build();
|
.build();
|
||||||
|
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||||
|
private final IamClient iamClient = mock(IamClient.class);
|
||||||
|
|
||||||
@Mock HttpServletRequest request;
|
@Mock HttpServletRequest request;
|
||||||
@Mock GmailClient gmailClient;
|
@Mock GmailClient gmailClient;
|
||||||
@@ -119,6 +125,10 @@ final class ConsoleRegistrarCreatorActionTest {
|
|||||||
action.passcodeGenerator = new DeterministicStringGenerator("314159265");
|
action.passcodeGenerator = new DeterministicStringGenerator("314159265");
|
||||||
|
|
||||||
action.analyticsConfig = ImmutableMap.of("googleAnalyticsId", "sampleId");
|
action.analyticsConfig = ImmutableMap.of("googleAnalyticsId", "sampleId");
|
||||||
|
|
||||||
|
action.maybeGroupEmailAddress = Optional.of("group@example.com");
|
||||||
|
action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||||
|
action.iamClient = iamClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -152,8 +162,7 @@ final class ConsoleRegistrarCreatorActionTest {
|
|||||||
assertThat(response.getPayload()).contains("gtag('config', 'sampleId')");
|
assertThat(response.getPayload()).contains("gtag('config', 'sampleId')");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
void runTestPost_authorized_minimalAddress() {
|
||||||
void testPost_authorized_minimalAddress() {
|
|
||||||
action.clientId = Optional.of("myclientid");
|
action.clientId = Optional.of("myclientid");
|
||||||
action.name = Optional.of("registrar name");
|
action.name = Optional.of("registrar name");
|
||||||
action.billingAccount = Optional.of("USD=billing-account");
|
action.billingAccount = Optional.of("USD=billing-account");
|
||||||
@@ -209,14 +218,22 @@ final class ConsoleRegistrarCreatorActionTest {
|
|||||||
.setCountryCode("CC")
|
.setCountryCode("CC")
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
assertThat(registrar.getContacts())
|
verifyUser("myclientid", "myclientid@registry.example");
|
||||||
.containsExactly(
|
}
|
||||||
new RegistrarPoc.Builder()
|
|
||||||
.setRegistrar(registrar)
|
@Test
|
||||||
.setName("myclientid@registry.example")
|
void testPost_authorized_minimalAddress_consoleUserGroup() {
|
||||||
.setEmailAddress("myclientid@registry.example")
|
runTestPost_authorized_minimalAddress();
|
||||||
.setLoginEmailAddress("myclientid@registry.example")
|
verifyIapPermission(
|
||||||
.build());
|
"myclientid@registry.example", action.maybeGroupEmailAddress, cloudTasksHelper, iamClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPost_authorized_minimalAddress_NoConsoleUserGroup() {
|
||||||
|
action.maybeGroupEmailAddress = Optional.empty();
|
||||||
|
runTestPost_authorized_minimalAddress();
|
||||||
|
verifyIapPermission(
|
||||||
|
"myclientid@registry.example", action.maybeGroupEmailAddress, cloudTasksHelper, iamClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
package google.registry.util;
|
package google.registry.util;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
import com.google.common.base.Ascii;
|
import com.google.common.base.Ascii;
|
||||||
|
|
||||||
/** Registry environments. */
|
/** Registry environments. */
|
||||||
@@ -59,6 +61,20 @@ public enum RegistryEnvironment {
|
|||||||
private static final boolean ON_JETTY =
|
private static final boolean ON_JETTY =
|
||||||
Boolean.parseBoolean(System.getProperty(JETTY_PROPERTY, "false"));
|
Boolean.parseBoolean(System.getProperty(JETTY_PROPERTY, "false"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A thread local boolean that can be set in tests to indicate some code is running in a local
|
||||||
|
* test server.
|
||||||
|
*
|
||||||
|
* <p>Certain API calls (like calls to Cloud Tasks) are hard to stub when they run in the test
|
||||||
|
* server because the test server does not allow arbitrary injection of dependencies. Instead,
|
||||||
|
* code running in the server can check this value and decide whether to skip these API calls.
|
||||||
|
*
|
||||||
|
* <p>The value is set to false by default and can only be set to true in unit test environment.
|
||||||
|
* It is set to {@code true} in {@code start()} and {@code false} in {@code stop()} in {@code
|
||||||
|
* TestServer}.
|
||||||
|
*/
|
||||||
|
private static final ThreadLocal<Boolean> IN_TEST_SERVER = ThreadLocal.withInitial(() -> false);
|
||||||
|
|
||||||
/** Sets this enum as the name of the registry environment. */
|
/** Sets this enum as the name of the registry environment. */
|
||||||
public RegistryEnvironment setup() {
|
public RegistryEnvironment setup() {
|
||||||
return setup(SystemPropertySetter.PRODUCTION_IMPL);
|
return setup(SystemPropertySetter.PRODUCTION_IMPL);
|
||||||
@@ -81,4 +97,13 @@ public enum RegistryEnvironment {
|
|||||||
public static boolean isOnJetty() {
|
public static boolean isOnJetty() {
|
||||||
return ON_JETTY;
|
return ON_JETTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setIsInTestDriver(boolean value) {
|
||||||
|
checkState(RegistryEnvironment.get() == RegistryEnvironment.UNITTEST);
|
||||||
|
IN_TEST_SERVER.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isInTestServer() {
|
||||||
|
return IN_TEST_SERVER.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user