diff --git a/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java b/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java
index 4c7d75a9e..c206f1fdd 100644
--- a/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java
+++ b/core/src/main/java/google/registry/request/auth/OidcTokenAuthenticationMechanism.java
@@ -36,9 +36,9 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
/**
- * An authenticam mechanism that verifies the OIDC token.
+ * An authentication mechanism that verifies the OIDC token.
*
- *
Currently, two flavors are supported: one that checkes for the OIDC token as a regular bearer
+ *
Currently, two flavors are supported: one that checks for the OIDC token as a regular bearer
* token, and another that checks for the OIDC token passed by IAP. In both cases, the {@link
* AuthResult} with the highest {@link AuthLevel} possible is returned. So, if the email address for
* which the token is minted exists both as a {@link User} and as a service account, the returned
diff --git a/core/src/main/java/google/registry/tools/CreateOrUpdateUserCommand.java b/core/src/main/java/google/registry/tools/CreateOrUpdateUserCommand.java
index 62b55e114..61ae060e9 100644
--- a/core/src/main/java/google/registry/tools/CreateOrUpdateUserCommand.java
+++ b/core/src/main/java/google/registry/tools/CreateOrUpdateUserCommand.java
@@ -14,6 +14,7 @@
package google.registry.tools;
+import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
@@ -41,6 +42,15 @@ public abstract class CreateOrUpdateUserCommand extends ConfirmingCommand {
+ " to remove the field.")
private String registryLockEmailAddress;
+ @Nullable
+ @Parameter(
+ names = "--registry_lock_password",
+ description =
+ "Sets the registry lock password for this user, or removes it (allowing the user to"
+ + " re-set it). Do not set the password explicitly unless in exceptional"
+ + " circumstances.")
+ private String registryLockPassword;
+
@Nullable
@Parameter(
names = "--admin",
@@ -94,6 +104,25 @@ public abstract class CreateOrUpdateUserCommand extends ConfirmingCommand {
builder.setRegistryLockEmailAddress(registryLockEmailAddress);
}
}
+ // Ditto the registry lock password
+ if (registryLockPassword != null) {
+ if (registryLockEmailAddress != null) {
+ // Edge case, make sure we're not removing an email and setting a password at the same time
+ checkArgument(
+ !registryLockEmailAddress.isEmpty(),
+ "Cannot set/remove registry lock password on a user without a registry lock email"
+ + " address");
+ } else {
+ checkArgument(
+ user != null && user.getRegistryLockEmailAddress().isPresent(),
+ "Cannot set/remove registry lock password on a user without a registry lock email"
+ + " address");
+ }
+ builder.removeRegistryLockPassword();
+ if (!registryLockPassword.isEmpty()) {
+ builder.setRegistryLockPassword(registryLockPassword);
+ }
+ }
tm().put(builder.build());
}
}
diff --git a/core/src/test/java/google/registry/tools/CreateUserCommandTest.java b/core/src/test/java/google/registry/tools/CreateUserCommandTest.java
index e365067e6..c281e3909 100644
--- a/core/src/test/java/google/registry/tools/CreateUserCommandTest.java
+++ b/core/src/test/java/google/registry/tools/CreateUserCommandTest.java
@@ -91,10 +91,16 @@ public class CreateUserCommandTest extends CommandTestCase {
runCommandForced(
"--email",
"user@example.test",
+ "--registrar_roles",
+ "TheRegistrar=PRIMARY_CONTACT",
"--registry_lock_email_address",
- "registrylockemail@otherexample.test");
- assertThat(loadExistingUser("user@example.test").getRegistryLockEmailAddress())
- .hasValue("registrylockemail@otherexample.test");
+ "registrylockemail@otherexample.test",
+ "--registry_lock_password",
+ "password");
+ User user = loadExistingUser("user@example.test");
+ assertThat(user.getRegistryLockEmailAddress()).hasValue("registrylockemail@otherexample.test");
+ assertThat(user.verifyRegistryLockPassword("password")).isTrue();
+ assertThat(user.verifyRegistryLockPassword("foobar")).isFalse();
}
@Test
@@ -174,4 +180,18 @@ public class CreateUserCommandTest extends CommandTestCase {
.hasMessageThat()
.isEqualTo("Provided email this is not valid is not a valid email address");
}
+
+ @Test
+ void testFailure_registryLockPassword_withoutEmail() {
+ assertThat(
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ runCommandForced(
+ "--email", "user@example.test", "--registry_lock_password", "password")))
+ .hasMessageThat()
+ .isEqualTo(
+ "Cannot set/remove registry lock password on a user without a registry lock email"
+ + " address");
+ }
}
diff --git a/core/src/test/java/google/registry/tools/UpdateUserCommandTest.java b/core/src/test/java/google/registry/tools/UpdateUserCommandTest.java
index f3135eaed..502f130cd 100644
--- a/core/src/test/java/google/registry/tools/UpdateUserCommandTest.java
+++ b/core/src/test/java/google/registry/tools/UpdateUserCommandTest.java
@@ -16,6 +16,7 @@ package google.registry.tools;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatabaseHelper.loadExistingUser;
+import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.DatabaseHelper.putInDb;
import static org.junit.Assert.assertThrows;
@@ -98,6 +99,44 @@ public class UpdateUserCommandTest extends CommandTestCase {
.isEqualTo(GlobalRole.FTE);
}
+ @Test
+ void testSuccess_removePassword() throws Exception {
+ // Empty password value removes the password
+ persistResource(
+ loadExistingUser("user@example.test")
+ .asBuilder()
+ .setUserRoles(
+ new UserRoles.Builder()
+ .setRegistrarRoles(ImmutableMap.of("TheRegistrar", RegistrarRole.TECH_CONTACT))
+ .build())
+ .setRegistryLockEmailAddress("registrylock@example.test")
+ .setRegistryLockPassword("password")
+ .build());
+ assertThat(loadExistingUser("user@example.test").hasRegistryLockPassword()).isTrue();
+ runCommandForced("--email", "user@example.test", "--registry_lock_password", "");
+ assertThat(loadExistingUser("user@example.test").hasRegistryLockPassword()).isFalse();
+ }
+
+ @Test
+ void testSuccess_setsPassword() throws Exception {
+ persistResource(
+ loadExistingUser("user@example.test")
+ .asBuilder()
+ .setUserRoles(
+ new UserRoles.Builder()
+ .setRegistrarRoles(ImmutableMap.of("TheRegistrar", RegistrarRole.TECH_CONTACT))
+ .build())
+ .setRegistryLockEmailAddress("registrylock@example.test")
+ .setRegistryLockPassword("password")
+ .build());
+ assertThat(loadExistingUser("user@example.test").verifyRegistryLockPassword("password"))
+ .isTrue();
+ runCommandForced("--email", "user@example.test", "--registry_lock_password", "foobar");
+ assertThat(loadExistingUser("user@example.test").verifyRegistryLockPassword("password"))
+ .isFalse();
+ assertThat(loadExistingUser("user@example.test").verifyRegistryLockPassword("foobar")).isTrue();
+ }
+
@Test
void testFailure_doesntExist() {
assertThat(
@@ -122,4 +161,18 @@ public class UpdateUserCommandTest extends CommandTestCase {
.hasMessageThat()
.isEqualTo("Provided email this is not valid is not a valid email address");
}
+
+ @Test
+ void testFailure_setPassword_noEmail() {
+ assertThat(
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ runCommandForced(
+ "--email", "user@example.test", "--registry_lock_password", "foobar")))
+ .hasMessageThat()
+ .isEqualTo(
+ "Cannot set/remove registry lock password on a user without a registry lock email"
+ + " address");
+ }
}