1
0
mirror of https://github.com/google/nomulus synced 2026-01-08 07:11:44 +00:00

Allow for removal of registry lock passwords in User objects (#2609)

This essentially enables the "forgot password" flow
This commit is contained in:
gbrodman
2024-11-14 16:01:17 -05:00
committed by GitHub
parent 78cc1b2937
commit e54075fea3
4 changed files with 107 additions and 5 deletions

View File

@@ -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.
*
* <p>Currently, two flavors are supported: one that checkes for the OIDC token as a regular bearer
* <p>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

View File

@@ -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());
}
}

View File

@@ -91,10 +91,16 @@ public class CreateUserCommandTest extends CommandTestCase<CreateUserCommand> {
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<CreateUserCommand> {
.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");
}
}

View File

@@ -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<UpdateUserCommand> {
.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<UpdateUserCommand> {
.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");
}
}