mirror of
https://github.com/google/nomulus
synced 2026-01-07 22:15:30 +00:00
Anonymize support users in console history, add minor UI updates (#2851)
This commit is contained in:
@@ -15,15 +15,19 @@
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserRoles;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.GaeService;
|
||||
import google.registry.request.Action.GkeService;
|
||||
@@ -43,8 +47,8 @@ public class ConsoleHistoryDataAction extends ConsoleApiAction {
|
||||
|
||||
private static final String SQL_USER_HISTORY =
|
||||
"""
|
||||
SELECT * FROM "ConsoleUpdateHistory"
|
||||
WHERE acting_user = :actingUser
|
||||
SELECT * FROM "ConsoleUpdateHistory"
|
||||
WHERE acting_user = :actingUser
|
||||
""";
|
||||
|
||||
private static final String SQL_REGISTRAR_HISTORY =
|
||||
@@ -59,14 +63,18 @@ public class ConsoleHistoryDataAction extends ConsoleApiAction {
|
||||
private final String registrarId;
|
||||
private final Optional<String> consoleUserEmail;
|
||||
|
||||
private final String supportEmail;
|
||||
|
||||
@Inject
|
||||
public ConsoleHistoryDataAction(
|
||||
ConsoleApiParams consoleApiParams,
|
||||
@Config("supportEmail") String supportEmail,
|
||||
@Parameter("registrarId") String registrarId,
|
||||
@Parameter("consoleUserEmail") Optional<String> consoleUserEmail) {
|
||||
super(consoleApiParams);
|
||||
this.registrarId = registrarId;
|
||||
this.consoleUserEmail = consoleUserEmail;
|
||||
this.supportEmail = supportEmail;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,7 +103,9 @@ public class ConsoleHistoryDataAction extends ConsoleApiAction {
|
||||
.setHint("org.hibernate.fetchSize", 1000)
|
||||
.getResultList());
|
||||
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(queryResult));
|
||||
List<ConsoleUpdateHistory> formattedHistoryList =
|
||||
replaceActiveUserIfNecessary(queryResult, user);
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(formattedHistoryList));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
@@ -110,7 +120,39 @@ public class ConsoleHistoryDataAction extends ConsoleApiAction {
|
||||
.setParameter("registrarId", registrarId)
|
||||
.setHint("org.hibernate.fetchSize", 1000)
|
||||
.getResultList());
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(queryResult));
|
||||
|
||||
List<ConsoleUpdateHistory> formattedHistoryList =
|
||||
replaceActiveUserIfNecessary(queryResult, user);
|
||||
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(formattedHistoryList));
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
/** Anonymizes support users in history logs if the user viewing the log is a registrar user. */
|
||||
private List<ConsoleUpdateHistory> replaceActiveUserIfNecessary(
|
||||
List<ConsoleUpdateHistory> historyList, User requestingUser) {
|
||||
// Check if the user *viewing* the history is a registrar user (not a support user)
|
||||
if (GlobalRole.NONE.equals(requestingUser.getUserRoles().getGlobalRole())) {
|
||||
User genericSupportUser = // Fixed typo
|
||||
new User.Builder()
|
||||
.setEmailAddress(this.supportEmail)
|
||||
.setUserRoles(new UserRoles.Builder().build()) // Simplified roles
|
||||
.build();
|
||||
|
||||
return historyList.stream()
|
||||
.map(
|
||||
history -> {
|
||||
// Check if the user who performed the action was a support user
|
||||
if (!GlobalRole.NONE.equals(
|
||||
history.getActingUser().getUserRoles().getGlobalRole())) {
|
||||
return history.asBuilder().setActingUser(genericSupportUser).build();
|
||||
}
|
||||
// If acting user was a registrar user show them as-is
|
||||
return history;
|
||||
})
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
// If the viewing user is a support user, return the list unmodified
|
||||
return historyList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.apache.http.HttpStatus.SC_OK;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.console.ConsolePermission;
|
||||
import google.registry.model.console.ConsoleUpdateHistory;
|
||||
import google.registry.model.console.User;
|
||||
@@ -47,6 +48,8 @@ import org.joda.time.DateTime;
|
||||
method = {POST},
|
||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||
public class ConsoleUpdateRegistrarAction extends ConsoleApiAction {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final String CHANGE_LOG_ENTRY = "%s updated on %s, old -> %s, new -> %s";
|
||||
static final String PATH = "/console-api/registrar";
|
||||
private final Optional<Registrar> registrar;
|
||||
|
||||
@@ -124,6 +127,9 @@ public class ConsoleUpdateRegistrarAction extends ConsoleApiAction {
|
||||
new ConsoleUpdateHistory.Builder()
|
||||
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
|
||||
.setDescription(updatedRegistrar.getRegistrarId()));
|
||||
|
||||
logConsoleChangesIfNecessary(updatedRegistrar, existingRegistrar.get());
|
||||
|
||||
sendExternalUpdatesIfNecessary(
|
||||
EmailInfo.create(
|
||||
existingRegistrar.get(),
|
||||
@@ -134,4 +140,25 @@ public class ConsoleUpdateRegistrarAction extends ConsoleApiAction {
|
||||
|
||||
consoleApiParams.response().setStatus(SC_OK);
|
||||
}
|
||||
|
||||
private void logConsoleChangesIfNecessary(
|
||||
Registrar updatedRegistrar, Registrar existingRegistrar) {
|
||||
if (!updatedRegistrar.getAllowedTlds().containsAll(existingRegistrar.getAllowedTlds())) {
|
||||
logger.atInfo().log(
|
||||
CHANGE_LOG_ENTRY,
|
||||
"Allowed TLDs",
|
||||
updatedRegistrar.getRegistrarId(),
|
||||
existingRegistrar.getAllowedTlds(),
|
||||
updatedRegistrar.getAllowedTlds());
|
||||
}
|
||||
|
||||
if (updatedRegistrar.isRegistryLockAllowed() != existingRegistrar.isRegistryLockAllowed()) {
|
||||
logger.atInfo().log(
|
||||
CHANGE_LOG_ENTRY,
|
||||
"Registry lock",
|
||||
updatedRegistrar.getRegistrarId(),
|
||||
existingRegistrar.isRegistryLockAllowed(),
|
||||
updatedRegistrar.isRegistryLockAllowed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,10 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
class ConsoleHistoryDataActionTest extends ConsoleActionBaseTestCase {
|
||||
|
||||
private static final String SUPPORT_EMAIL = "supportEmailTest@test.com";
|
||||
private static final Gson GSON = new Gson();
|
||||
private User noPermissionUser;
|
||||
private User registrarPrimaryUser;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
@@ -56,6 +58,17 @@ class ConsoleHistoryDataActionTest extends ConsoleActionBaseTestCase {
|
||||
.build())
|
||||
.build());
|
||||
|
||||
registrarPrimaryUser =
|
||||
DatabaseHelper.persistResource(
|
||||
new User.Builder()
|
||||
.setEmailAddress("primary@example.com")
|
||||
.setUserRoles(
|
||||
new UserRoles.Builder()
|
||||
.setRegistrarRoles(
|
||||
ImmutableMap.of("TheRegistrar", RegistrarRole.PRIMARY_CONTACT))
|
||||
.build())
|
||||
.build());
|
||||
|
||||
DatabaseHelper.persistResources(
|
||||
ImmutableList.of(
|
||||
new ConsoleUpdateHistory.Builder()
|
||||
@@ -85,7 +98,7 @@ class ConsoleHistoryDataActionTest extends ConsoleActionBaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_getByRegistrar() {
|
||||
void testSuccess_getByRegistrar_notAnonymizedForSupportUser() {
|
||||
ConsoleHistoryDataAction action =
|
||||
createAction(AuthResult.createUser(fteUser), "TheRegistrar", Optional.empty());
|
||||
action.run();
|
||||
@@ -93,6 +106,35 @@ class ConsoleHistoryDataActionTest extends ConsoleActionBaseTestCase {
|
||||
List<Map<String, Object>> payload = GSON.fromJson(response.getPayload(), List.class);
|
||||
assertThat(payload.stream().map(record -> record.get("description")).collect(toImmutableList()))
|
||||
.containsExactly("TheRegistrar|Some change", "TheRegistrar|Another change");
|
||||
|
||||
// Assert that the support user sees the real acting users
|
||||
List<String> actingUserEmails =
|
||||
payload.stream()
|
||||
.map(record -> (Map<String, Object>) record.get("actingUser"))
|
||||
.map(userMap -> (String) userMap.get("emailAddress"))
|
||||
.collect(toImmutableList());
|
||||
|
||||
assertThat(actingUserEmails).containsExactly("fte@email.tld", "no.perms@example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_getByRegistrar_anonymizedForRegistrarUser() {
|
||||
ConsoleHistoryDataAction action =
|
||||
createAction(AuthResult.createUser(registrarPrimaryUser), "TheRegistrar", Optional.empty());
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
List<Map<String, Object>> payload = GSON.fromJson(response.getPayload(), List.class);
|
||||
assertThat(payload.stream().map(record -> record.get("description")).collect(toImmutableList()))
|
||||
.containsExactly("TheRegistrar|Some change", "TheRegistrar|Another change");
|
||||
|
||||
// Assert that the registrar user sees the anonymized support user
|
||||
List<String> actingUserEmails =
|
||||
payload.stream()
|
||||
.map(record -> (Map<String, Object>) record.get("actingUser"))
|
||||
.map(userMap -> (String) userMap.get("emailAddress"))
|
||||
.collect(toImmutableList());
|
||||
|
||||
assertThat(actingUserEmails).containsExactly(SUPPORT_EMAIL, "no.perms@example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -104,6 +146,13 @@ class ConsoleHistoryDataActionTest extends ConsoleActionBaseTestCase {
|
||||
List<Map<String, Object>> payload = GSON.fromJson(response.getPayload(), List.class);
|
||||
assertThat(payload.stream().map(record -> record.get("description")).collect(toImmutableList()))
|
||||
.containsExactly("TheRegistrar|Some change", "OtherRegistrar|Some change");
|
||||
|
||||
List<String> actingUserEmails =
|
||||
payload.stream()
|
||||
.map(record -> (Map<String, Object>) record.get("actingUser"))
|
||||
.map(userMap -> (String) userMap.get("emailAddress"))
|
||||
.collect(toImmutableList());
|
||||
assertThat(actingUserEmails).containsExactly("fte@email.tld", "fte@email.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -148,6 +197,7 @@ class ConsoleHistoryDataActionTest extends ConsoleActionBaseTestCase {
|
||||
consoleApiParams = ConsoleApiParamsUtils.createFake(authResult);
|
||||
when(consoleApiParams.request().getMethod()).thenReturn("GET");
|
||||
response = (FakeResponse) consoleApiParams.response();
|
||||
return new ConsoleHistoryDataAction(consoleApiParams, registrarId, consoleUserEmail);
|
||||
return new ConsoleHistoryDataAction(
|
||||
consoleApiParams, SUPPORT_EMAIL, registrarId, consoleUserEmail);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user