1
0
mirror of https://github.com/google/nomulus synced 2025-12-23 06:15:42 +00:00

Enable Users and Domains actions, add email notification (#2700)

This commit is contained in:
Pavlo Tkach
2025-02-28 16:57:49 -05:00
committed by GitHub
parent ea1e8d5cc5
commit 6c7bf5e5dd
22 changed files with 31 additions and 32 deletions

View File

@@ -27,12 +27,10 @@ export const DISABLED_ELEMENTS_PER_ROLE = {
NONE: [ NONE: [
RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT, RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT,
RESTRICTED_ELEMENTS.OTE, RESTRICTED_ELEMENTS.OTE,
RESTRICTED_ELEMENTS.USERS,
RESTRICTED_ELEMENTS.BULK_DELETE,
RESTRICTED_ELEMENTS.SUSPEND, RESTRICTED_ELEMENTS.SUSPEND,
], ],
SUPPORT_LEAD: [RESTRICTED_ELEMENTS.USERS], SUPPORT_LEAD: [],
SUPPORT_AGENT: [RESTRICTED_ELEMENTS.USERS], SUPPORT_AGENT: [],
}; };
@Directive({ @Directive({

View File

@@ -31,12 +31,14 @@ import com.google.api.services.directory.Directory;
import com.google.api.services.directory.model.UserName; import com.google.api.services.directory.model.UserName;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import google.registry.config.RegistryConfig.Config; import google.registry.config.RegistryConfig.Config;
import google.registry.model.console.ConsolePermission; import google.registry.model.console.ConsolePermission;
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.UserRoles; import google.registry.model.console.UserRoles;
import google.registry.model.registrar.Registrar;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.Action.GkeService; import google.registry.request.Action.GkeService;
@@ -44,6 +46,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.tools.IamClient; import google.registry.tools.IamClient;
import google.registry.util.DiffUtils;
import google.registry.util.StringGenerator; import google.registry.util.StringGenerator;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@@ -96,24 +99,14 @@ public class ConsoleUsersAction extends ConsoleApiAction {
@Override @Override
protected void postHandler(User user) { protected void postHandler(User user) {
// Temporary flag while testing checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
if (user.getUserRoles().isAdmin()) { tm().transact(this::runPostInTransaction);
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
tm().transact(this::runPostInTransaction);
} else {
consoleApiParams.response().setStatus(SC_FORBIDDEN);
}
} }
@Override @Override
protected void putHandler(User user) { protected void putHandler(User user) {
// Temporary flag while testing checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
if (user.getUserRoles().isAdmin()) { tm().transact(this::runUpdateInTransaction);
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
tm().transact(this::runUpdateInTransaction);
} else {
consoleApiParams.response().setStatus(SC_FORBIDDEN);
}
} }
@Override @Override
@@ -135,13 +128,8 @@ public class ConsoleUsersAction extends ConsoleApiAction {
@Override @Override
protected void deleteHandler(User user) { protected void deleteHandler(User user) {
// Temporary flag while testing checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
if (user.getUserRoles().isAdmin()) { tm().transact(this::runDeleteInTransaction);
checkPermission(user, registrarId, ConsolePermission.MANAGE_USERS);
tm().transact(this::runDeleteInTransaction);
} else {
consoleApiParams.response().setStatus(SC_FORBIDDEN);
}
} }
private void runPostInTransaction() throws IOException { private void runPostInTransaction() throws IOException {
@@ -163,6 +151,8 @@ public class ConsoleUsersAction extends ConsoleApiAction {
this.userData.get().emailAddress, this.userData.get().emailAddress,
registrarId, registrarId,
RegistrarRole.valueOf(this.userData.get().role)); RegistrarRole.valueOf(this.userData.get().role));
sendConfirmationEmail(registrarId, this.userData.get().emailAddress, "Added existing user");
consoleApiParams.response().setStatus(SC_OK); consoleApiParams.response().setStatus(SC_OK);
} }
@@ -186,6 +176,7 @@ public class ConsoleUsersAction extends ConsoleApiAction {
VKey<User> key = VKey.create(User.class, email); VKey<User> key = VKey.create(User.class, email);
tm().delete(key); tm().delete(key);
User.revokeIapPermission(email, maybeGroupEmailAddress, cloudTasksUtils, null, iamClient); User.revokeIapPermission(email, maybeGroupEmailAddress, cloudTasksUtils, null, iamClient);
sendConfirmationEmail(registrarId, email, "Deleted user");
} }
consoleApiParams.response().setStatus(SC_OK); consoleApiParams.response().setStatus(SC_OK);
@@ -232,7 +223,7 @@ public class ConsoleUsersAction extends ConsoleApiAction {
User.Builder builder = new User.Builder().setUserRoles(userRoles).setEmailAddress(newEmail); User.Builder builder = new User.Builder().setUserRoles(userRoles).setEmailAddress(newEmail);
tm().put(builder.build()); tm().put(builder.build());
User.grantIapPermission(newEmail, maybeGroupEmailAddress, cloudTasksUtils, null, iamClient); User.grantIapPermission(newEmail, maybeGroupEmailAddress, cloudTasksUtils, null, iamClient);
sendConfirmationEmail(registrarId, newEmail, "Created user");
consoleApiParams.response().setStatus(SC_CREATED); consoleApiParams.response().setStatus(SC_CREATED);
consoleApiParams consoleApiParams
.response() .response()
@@ -251,6 +242,8 @@ public class ConsoleUsersAction extends ConsoleApiAction {
this.userData.get().emailAddress, this.userData.get().emailAddress,
registrarId, registrarId,
RegistrarRole.valueOf(this.userData.get().role)); RegistrarRole.valueOf(this.userData.get().role));
sendConfirmationEmail(registrarId, this.userData.get().emailAddress, "Updated user");
consoleApiParams.response().setStatus(SC_OK); consoleApiParams.response().setStatus(SC_OK);
} }
@@ -315,6 +308,20 @@ public class ConsoleUsersAction extends ConsoleApiAction {
.collect(toImmutableList())); .collect(toImmutableList()));
} }
private boolean sendConfirmationEmail(String registrarId, String emailAddress, String operation) {
Optional<Registrar> registrar = Registrar.loadByRegistrarId(registrarId);
if (registrar.isEmpty()) { // Shouldn't happen, but worth checking
setFailedResponse(
"Failed to send an email to registrar " + registrarId, SC_INTERNAL_SERVER_ERROR);
return false;
}
sendExternalUpdates(
ImmutableMap.of("Console users updated", new DiffUtils.DiffPair(operation, emailAddress)),
registrar.get(),
ImmutableSet.of());
return true;
}
public record UserData( public record UserData(
@Expose String emailAddress, @Expose String role, @Expose @Nullable String password) {} @Expose String emailAddress, @Expose String role, @Expose @Nullable String password) {}
} }

View File

@@ -15,7 +15,6 @@
package google.registry.ui.server.console.domains; package google.registry.ui.server.console.domains;
import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK; import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
@@ -81,11 +80,6 @@ public class ConsoleBulkDomainAction extends ConsoleApiAction {
@Override @Override
protected void postHandler(User user) { protected void postHandler(User user) {
// Temporary flag while testing
if (!user.getUserRoles().isAdmin()) {
consoleApiParams.response().setStatus(SC_FORBIDDEN);
return;
}
JsonElement jsonPayload = JsonElement jsonPayload =
optionalJsonPayload.orElseThrow( optionalJsonPayload.orElseThrow(
() -> new IllegalArgumentException("Bulk action payload must be present")); () -> new IllegalArgumentException("Bulk action payload must be present"));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 75 KiB