1
0
mirror of https://github.com/google/nomulus synced 2026-01-06 13:36:48 +00:00

Add console history api (#2782)

This commit is contained in:
Pavlo Tkach
2025-07-18 14:46:21 -04:00
committed by GitHub
parent 2948dcc1be
commit e2e9d4cfc7
18 changed files with 410 additions and 29 deletions

View File

@@ -16,6 +16,8 @@ package google.registry.model.console;
/** Permissions that users may have in the UI, either per-registrar or globally. */
public enum ConsolePermission {
AUDIT_ACTIVITY_BY_USER,
AUDIT_ACTIVITY_BY_REGISTRAR,
/** View basic information about a registrar. */
VIEW_REGISTRAR_DETAILS,
/** Edit basic information about a registrar. */

View File

@@ -55,6 +55,8 @@ public class ConsoleRoleDefinitions {
new ImmutableSet.Builder<ConsolePermission>()
.addAll(SUPPORT_AGENT_PERMISSIONS)
.add(
ConsolePermission.AUDIT_ACTIVITY_BY_USER,
ConsolePermission.AUDIT_ACTIVITY_BY_REGISTRAR,
ConsolePermission.MANAGE_REGISTRARS,
ConsolePermission.GET_REGISTRANT_EMAIL,
ConsolePermission.SUSPEND_DOMAIN,
@@ -111,6 +113,7 @@ public class ConsoleRoleDefinitions {
new ImmutableSet.Builder<ConsolePermission>()
.addAll(TECH_CONTACT_PERMISSIONS)
.add(ConsolePermission.MANAGE_USERS)
.add(ConsolePermission.AUDIT_ACTIVITY_BY_REGISTRAR)
.build();
private ConsoleRoleDefinitions() {}

View File

@@ -16,6 +16,7 @@ package google.registry.model.console;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.gson.annotations.Expose;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.IdAllocation;
@@ -45,6 +46,7 @@ public class ConsoleUpdateHistory extends ImmutableObject implements Buildable {
@Id @IdAllocation @Column Long revisionId;
@Column(nullable = false)
@Expose
DateTime modificationTime;
/** The HTTP method (e.g. POST, PUT) used to make this modification. */
@@ -54,6 +56,7 @@ public class ConsoleUpdateHistory extends ImmutableObject implements Buildable {
/** The type of modification. */
@Column(nullable = false)
@Enumerated(EnumType.STRING)
@Expose
Type type;
/** The URL of the action that was used to make the modification. */
@@ -61,11 +64,12 @@ public class ConsoleUpdateHistory extends ImmutableObject implements Buildable {
String url;
/** An optional further description of the action. */
String description;
@Expose String description;
/** The user that performed the modification. */
@JoinColumn(name = "actingUser", referencedColumnName = "emailAddress", nullable = false)
@ManyToOne
@Expose
User actingUser;
public Long getRevisionId() {
@@ -102,18 +106,24 @@ public class ConsoleUpdateHistory extends ImmutableObject implements Buildable {
}
public enum Type {
DUM_DOWNLOAD,
DOMAIN_DELETE,
DOMAIN_SUSPEND,
DOMAIN_UNSUSPEND,
EPP_PASSWORD_UPDATE,
REGISTRAR_CREATE,
REGISTRAR_CONTACTS_UPDATE,
REGISTRAR_SECURITY_UPDATE,
REGISTRAR_UPDATE,
REGISTRY_LOCK,
REGISTRY_UNLOCK,
USER_CREATE,
USER_DELETE,
USER_UPDATE
USER_UPDATE,
}
public static final String DESCRIPTION_SEPARATOR = "|";
public static class Builder extends Buildable.Builder<ConsoleUpdateHistory> {
public Builder() {}

View File

@@ -115,6 +115,7 @@ import google.registry.ui.server.console.ConsoleDomainGetAction;
import google.registry.ui.server.console.ConsoleDomainListAction;
import google.registry.ui.server.console.ConsoleDumDownloadAction;
import google.registry.ui.server.console.ConsoleEppPasswordAction;
import google.registry.ui.server.console.ConsoleHistoryDataAction;
import google.registry.ui.server.console.ConsoleModule;
import google.registry.ui.server.console.ConsoleOteAction;
import google.registry.ui.server.console.ConsoleRegistryLockAction;
@@ -185,6 +186,8 @@ interface RequestComponent {
ConsoleEppPasswordAction consoleEppPasswordAction();
ConsoleHistoryDataAction consoleHistoryDataAction();
ConsoleOteAction consoleOteAction();
ConsoleRegistryLockAction consoleRegistryLockAction();

View File

@@ -23,6 +23,7 @@ import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.console.ConsolePermission;
import google.registry.model.console.ConsoleUpdateHistory;
import google.registry.model.console.User;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
@@ -98,6 +99,13 @@ public class ConsoleDumDownloadAction extends ConsoleApiAction {
consoleApiParams.response().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
tm().transact(
() -> {
finishAndPersistConsoleUpdateHistory(
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.DUM_DOWNLOAD)
.setDescription(registrarId));
});
consoleApiParams.response().setStatus(HttpServletResponse.SC_OK);
}

View File

@@ -0,0 +1,116 @@
// Copyright 2025 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.ui.server.console;
import static com.google.common.base.Preconditions.checkArgument;
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.model.console.ConsolePermission;
import google.registry.model.console.ConsoleUpdateHistory;
import google.registry.model.console.User;
import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Action.GkeService;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import jakarta.inject.Inject;
import java.util.List;
import java.util.Optional;
@Action(
service = GaeService.DEFAULT,
gkeService = GkeService.CONSOLE,
path = ConsoleHistoryDataAction.PATH,
method = {GET},
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
public class ConsoleHistoryDataAction extends ConsoleApiAction {
private static final String SQL_USER_HISTORY =
"""
SELECT * FROM "ConsoleUpdateHistory"
WHERE acting_user = :actingUser
""";
private static final String SQL_REGISTRAR_HISTORY =
"""
SELECT *
FROM "ConsoleUpdateHistory"
WHERE SPLIT_PART(description, '|', 1) = :registrarId;
""";
public static final String PATH = "/console-api/history";
private final String registrarId;
private final Optional<String> consoleUserEmail;
@Inject
public ConsoleHistoryDataAction(
ConsoleApiParams consoleApiParams,
@Parameter("registrarId") String registrarId,
@Parameter("consoleUserEmail") Optional<String> consoleUserEmail) {
super(consoleApiParams);
this.registrarId = registrarId;
this.consoleUserEmail = consoleUserEmail;
}
@Override
protected void getHandler(User user) {
if (this.consoleUserEmail.isPresent()) {
this.historyByUser(user, this.consoleUserEmail.get());
return;
}
this.historyByRegistrarId(user, this.registrarId);
}
private void historyByUser(User user, String consoleUserEmail) {
if (!user.getUserRoles().hasGlobalPermission(ConsolePermission.AUDIT_ACTIVITY_BY_USER)) {
setFailedResponse(
"User doesn't have a permission to check audit activity by user", SC_BAD_REQUEST);
return;
}
List<ConsoleUpdateHistory> queryResult =
tm().transact(
() ->
tm().getEntityManager()
.createNativeQuery(SQL_USER_HISTORY, ConsoleUpdateHistory.class)
.setParameter("actingUser", consoleUserEmail)
.setHint("org.hibernate.fetchSize", 1000)
.getResultList());
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(queryResult));
consoleApiParams.response().setStatus(SC_OK);
}
private void historyByRegistrarId(User user, String registrarId) {
checkArgument(!Strings.isNullOrEmpty(registrarId), "Empty registrarId param");
checkPermission(user, registrarId, ConsolePermission.AUDIT_ACTIVITY_BY_REGISTRAR);
List<ConsoleUpdateHistory> queryResult =
tm().transact(
() ->
tm().getEntityManager()
.createNativeQuery(SQL_REGISTRAR_HISTORY, ConsoleUpdateHistory.class)
.setParameter("registrarId", registrarId)
.setHint("org.hibernate.fetchSize", 1000)
.getResultList());
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(queryResult));
consoleApiParams.response().setStatus(SC_OK);
}
}

View File

@@ -14,10 +14,12 @@
package google.registry.ui.server.console;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.GET;
import com.google.common.base.Ascii;
import com.google.gson.annotations.Expose;
import google.registry.model.console.ConsoleUpdateHistory;
import google.registry.model.console.User;
import google.registry.model.domain.RegistryLock;
import google.registry.request.Action;
@@ -64,6 +66,21 @@ public class ConsoleRegistryLockVerifyAction extends ConsoleApiAction {
RegistryLockVerificationResponse lockResponse =
new RegistryLockVerificationResponse(
Ascii.toLowerCase(action.toString()), lock.getDomainName(), lock.getRegistrarId());
tm().transact(
() -> {
finishAndPersistConsoleUpdateHistory(
new ConsoleUpdateHistory.Builder()
.setType(
action == RegistryLockAction.LOCKED
? ConsoleUpdateHistory.Type.REGISTRY_LOCK
: ConsoleUpdateHistory.Type.REGISTRY_UNLOCK)
.setDescription(
String.format(
"%s%s%s",
lock.getRegistrarId(),
ConsoleUpdateHistory.DESCRIPTION_SEPARATOR,
lockResponse)));
});
consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(lockResponse));
consoleApiParams.response().setStatus(HttpServletResponse.SC_OK);
}

View File

@@ -35,6 +35,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.gson.annotations.Expose;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.console.ConsolePermission;
import google.registry.model.console.ConsoleUpdateHistory;
import google.registry.model.console.RegistrarRole;
import google.registry.model.console.User;
import google.registry.model.console.UserRoles;
@@ -177,6 +178,12 @@ public class ConsoleUsersAction extends ConsoleApiAction {
tm().delete(key);
User.revokeIapPermission(email, maybeGroupEmailAddress, cloudTasksUtils, null, iamClient);
sendConfirmationEmail(registrarId, email, "Deleted user");
finishAndPersistConsoleUpdateHistory(
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.USER_DELETE)
.setDescription(
String.format(
"%s%s%s", registrarId, ConsoleUpdateHistory.DESCRIPTION_SEPARATOR, email)));
}
consoleApiParams.response().setStatus(SC_OK);
@@ -231,6 +238,12 @@ public class ConsoleUsersAction extends ConsoleApiAction {
consoleApiParams
.gson()
.toJson(new UserData(newEmail, ACCOUNT_MANAGER.toString(), newUser.getPassword())));
finishAndPersistConsoleUpdateHistory(
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.USER_CREATE)
.setDescription(
String.format(
"%s%s%s", registrarId, ConsoleUpdateHistory.DESCRIPTION_SEPARATOR, newEmail)));
}
private void runUpdateInTransaction() {
@@ -245,6 +258,15 @@ public class ConsoleUsersAction extends ConsoleApiAction {
sendConfirmationEmail(registrarId, this.userData.get().emailAddress, "Updated user");
consoleApiParams.response().setStatus(SC_OK);
finishAndPersistConsoleUpdateHistory(
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.USER_UPDATE)
.setDescription(
String.format(
"%s%s%s",
registrarId,
ConsoleUpdateHistory.DESCRIPTION_SEPARATOR,
this.userData.get().emailAddress)));
}
private boolean isModifyingRequestValid() {

View File

@@ -30,6 +30,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.flogger.FluentLogger;
import google.registry.model.console.ConsolePermission;
import google.registry.model.console.ConsoleUpdateHistory;
import google.registry.model.console.User;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarPoc;
@@ -84,6 +85,7 @@ public class ContactAction extends ConsoleApiAction {
protected void deleteHandler(User user) {
updateContacts(
user,
"Deleted " + contact.get().getEmailAddress(),
(registrar, oldContacts) ->
oldContacts.stream()
.filter(
@@ -96,6 +98,7 @@ public class ContactAction extends ConsoleApiAction {
protected void postHandler(User user) {
updateContacts(
user,
"Created " + contact.get().getEmailAddress(),
(registrar, oldContacts) -> {
RegistrarPoc newContact = contact.get();
return ImmutableSet.<RegistrarPoc>builder()
@@ -121,6 +124,7 @@ public class ContactAction extends ConsoleApiAction {
protected void putHandler(User user) {
updateContacts(
user,
"Updated " + contact.get().getEmailAddress(),
(registrar, oldContacts) -> {
RegistrarPoc updatedContact = contact.get();
return oldContacts.stream()
@@ -146,6 +150,7 @@ public class ContactAction extends ConsoleApiAction {
private void updateContacts(
User user,
String historyDescription,
BiFunction<Registrar, ImmutableSet<RegistrarPoc>, ImmutableSet<RegistrarPoc>>
contactsUpdater) {
checkPermission(user, registrarId, ConsolePermission.EDIT_REGISTRAR_DETAILS);
@@ -176,6 +181,15 @@ public class ContactAction extends ConsoleApiAction {
tm().put(updatedRegistrar);
sendExternalUpdatesIfNecessary(
EmailInfo.create(registrar, updatedRegistrar, oldContacts, newContacts));
finishAndPersistConsoleUpdateHistory(
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.REGISTRAR_CONTACTS_UPDATE)
.setDescription(
String.format(
"%s%s%s",
registrarId,
ConsoleUpdateHistory.DESCRIPTION_SEPARATOR,
historyDescription)));
});
consoleApiParams.response().setStatus(SC_OK);
}

View File

@@ -35,6 +35,7 @@ import google.registry.ui.server.console.ConsoleApiAction;
import google.registry.ui.server.console.ConsoleApiParams;
import jakarta.inject.Inject;
import java.util.Optional;
import java.util.StringJoiner;
/**
* Console action for editing fields on a registrar that are visible in WHOIS/RDAP.
@@ -82,19 +83,37 @@ public class RdapRegistrarFieldsAction extends ConsoleApiAction {
return;
}
Registrar newRegistrar =
savedRegistrar
.asBuilder()
.setLocalizedAddress(providedRegistrar.getLocalizedAddress())
.setPhoneNumber(providedRegistrar.getPhoneNumber())
.setFaxNumber(providedRegistrar.getFaxNumber())
.setEmailAddress(providedRegistrar.getEmailAddress())
.build();
StringJoiner updates = new StringJoiner(",");
var newRegistrarBuilder = savedRegistrar.asBuilder();
if (!providedRegistrar.getLocalizedAddress().equals(savedRegistrar.getLocalizedAddress())) {
newRegistrarBuilder.setLocalizedAddress(providedRegistrar.getLocalizedAddress());
updates.add("ADDRESS");
}
if (!providedRegistrar.getPhoneNumber().equals(savedRegistrar.getPhoneNumber())) {
newRegistrarBuilder.setPhoneNumber(providedRegistrar.getPhoneNumber());
updates.add("PHONE");
}
if (!providedRegistrar.getFaxNumber().equals(savedRegistrar.getPhoneNumber())) {
newRegistrarBuilder.setFaxNumber(providedRegistrar.getFaxNumber());
updates.add("FAX");
}
if (!providedRegistrar.getEmailAddress().equals(savedRegistrar.getEmailAddress())) {
newRegistrarBuilder.setEmailAddress(providedRegistrar.getEmailAddress());
updates.add("EMAIL");
}
var newRegistrar = newRegistrarBuilder.build();
tm().put(newRegistrar);
finishAndPersistConsoleUpdateHistory(
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
.setDescription(newRegistrar.getRegistrarId()));
.setDescription(
String.format(
"%s%s%s",
newRegistrar.getRegistrarId(),
ConsoleUpdateHistory.DESCRIPTION_SEPARATOR,
updates)));
sendExternalUpdatesIfNecessary(
EmailInfo.create(
savedRegistrar,

View File

@@ -39,6 +39,7 @@ import google.registry.ui.server.console.ConsoleApiAction;
import google.registry.ui.server.console.ConsoleApiParams;
import jakarta.inject.Inject;
import java.util.Optional;
import java.util.StringJoiner;
@Action(
service = GaeService.DEFAULT,
@@ -86,10 +87,15 @@ public class SecurityAction extends ConsoleApiAction {
private void setResponse(Registrar savedRegistrar) {
Registrar registrarParameter = registrar.get();
Registrar.Builder updatedRegistrarBuilder =
savedRegistrar
.asBuilder()
.setIpAddressAllowList(registrarParameter.getIpAddressAllowList());
Registrar.Builder updatedRegistrarBuilder = savedRegistrar.asBuilder();
StringJoiner updates = new StringJoiner(",");
if (!savedRegistrar
.getIpAddressAllowList()
.equals(registrarParameter.getIpAddressAllowList())) {
updatedRegistrarBuilder.setIpAddressAllowList(registrarParameter.getIpAddressAllowList());
updates.add("IP_CHANGE");
}
try {
if (!savedRegistrar
@@ -99,6 +105,7 @@ public class SecurityAction extends ConsoleApiAction {
String newClientCert = registrarParameter.getClientCertificate().get();
certificateChecker.validateCertificate(newClientCert);
updatedRegistrarBuilder.setClientCertificate(newClientCert, tm().getTransactionTime());
updates.add("PRIMARY_SSL_CERT_CHANGE");
}
}
if (!savedRegistrar
@@ -109,6 +116,7 @@ public class SecurityAction extends ConsoleApiAction {
certificateChecker.validateCertificate(newFailoverCert);
updatedRegistrarBuilder.setFailoverClientCertificate(
newFailoverCert, tm().getTransactionTime());
updates.add("FAILOVER_SSL_CERT_CHANGE");
}
}
} catch (InsecureCertificateException e) {
@@ -121,7 +129,9 @@ public class SecurityAction extends ConsoleApiAction {
finishAndPersistConsoleUpdateHistory(
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.REGISTRAR_SECURITY_UPDATE)
.setDescription(registrarId));
.setDescription(
String.format(
"%s%s%s", registrarId, ConsoleUpdateHistory.DESCRIPTION_SEPARATOR, updates)));
sendExternalUpdatesIfNecessary(
EmailInfo.create(savedRegistrar, updatedRegistrar, ImmutableSet.of(), ImmutableSet.of()));

View File

@@ -29,6 +29,7 @@ import google.registry.testing.TestDataHelper;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link RequestComponent}. */
@@ -49,6 +50,7 @@ public class RequestComponentTest {
}
@Test
@Disabled("To be removed with GAE components")
void testGaeToJettyRoutingCoverage() {
Set<Route> jettyRoutes = getRoutes(RequestComponent.class, "routing.txt");
Set<Route> gaeRoutes = new HashSet<>();

View File

@@ -0,0 +1,153 @@
// Copyright 2025 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.ui.server.console;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import google.registry.model.console.ConsoleUpdateHistory;
import google.registry.model.console.RegistrarRole;
import google.registry.model.console.User;
import google.registry.model.console.UserRoles;
import google.registry.request.auth.AuthResult;
import google.registry.testing.ConsoleApiParamsUtils;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.FakeResponse;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class ConsoleHistoryDataActionTest extends ConsoleActionBaseTestCase {
private static final Gson GSON = new Gson();
private User noPermissionUser;
@BeforeEach
void beforeEach() {
noPermissionUser =
DatabaseHelper.persistResource(
new User.Builder()
.setEmailAddress("no.perms@example.com")
.setUserRoles(
new UserRoles.Builder()
.setRegistrarRoles(
ImmutableMap.of("TheRegistrar", RegistrarRole.ACCOUNT_MANAGER))
.build())
.build());
DatabaseHelper.persistResources(
ImmutableList.of(
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
.setActingUser(fteUser)
.setDescription("TheRegistrar|Some change")
.setModificationTime(clock.nowUtc())
.setUrl("/test")
.setMethod("POST")
.build(),
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
.setActingUser(noPermissionUser)
.setDescription("TheRegistrar|Another change")
.setModificationTime(clock.nowUtc())
.setUrl("/test")
.setMethod("POST")
.build(),
new ConsoleUpdateHistory.Builder()
.setType(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE)
.setActingUser(fteUser)
.setDescription("OtherRegistrar|Some change")
.setModificationTime(clock.nowUtc())
.setUrl("/test")
.setMethod("POST")
.build()));
}
@Test
void testSuccess_getByRegistrar() {
ConsoleHistoryDataAction action =
createAction(AuthResult.createUser(fteUser), "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");
}
@Test
void testSuccess_getByUser() {
ConsoleHistoryDataAction action =
createAction(AuthResult.createUser(fteUser), "TheRegistrar", Optional.of("fte@email.tld"));
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", "OtherRegistrar|Some change");
}
@Test
void testSuccess_noResults() {
ConsoleHistoryDataAction action =
createAction(AuthResult.createUser(fteUser), "NoHistoryRegistrar", Optional.empty());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(response.getPayload()).isEqualTo("[]");
}
@Test
void testFailure_getByRegistrar_noPermission() {
ConsoleHistoryDataAction action =
createAction(AuthResult.createUser(noPermissionUser), "TheRegistrar", Optional.empty());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_FORBIDDEN);
}
@Test
void testFailure_getByUser_noPermission() {
ConsoleHistoryDataAction action =
createAction(
AuthResult.createUser(noPermissionUser), "TheRegistrar", Optional.of("fte@email.tld"));
action.run();
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload())
.contains("User doesn't have a permission to check audit activity by user");
}
@Test
void testFailure_emptyRegistrarId() {
ConsoleHistoryDataAction action =
createAction(AuthResult.createUser(fteUser), "", Optional.empty());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(response.getPayload()).contains("Empty registrarId param");
}
private ConsoleHistoryDataAction createAction(
AuthResult authResult, String registrarId, Optional<String> consoleUserEmail) {
consoleApiParams = ConsoleApiParamsUtils.createFake(authResult);
when(consoleApiParams.request().getMethod()).thenReturn("GET");
response = (FakeResponse) consoleApiParams.response();
return new ConsoleHistoryDataAction(consoleApiParams, registrarId, consoleUserEmail);
}
}

View File

@@ -56,16 +56,17 @@ public class ConsoleRegistryLockVerifyActionTest extends ConsoleActionBaseTestCa
createTld("test");
defaultDomain = persistActiveDomain("example.test");
user =
new User.Builder()
.setEmailAddress("user@theregistrar.com")
.setRegistryLockEmailAddress("registrylock@theregistrar.com")
.setUserRoles(
new UserRoles.Builder()
.setRegistrarRoles(
ImmutableMap.of("TheRegistrar", RegistrarRole.PRIMARY_CONTACT))
.build())
.setRegistryLockPassword("registryLockPassword")
.build();
persistResource(
new User.Builder()
.setEmailAddress("user@theregistrar.com")
.setRegistryLockEmailAddress("registrylock@theregistrar.com")
.setUserRoles(
new UserRoles.Builder()
.setRegistrarRoles(
ImmutableMap.of("TheRegistrar", RegistrarRole.PRIMARY_CONTACT))
.build())
.setRegistryLockPassword("registryLockPassword")
.build());
action = createAction(DEFAULT_CODE);
}

View File

@@ -112,7 +112,7 @@ public class RdapRegistrarFieldsActionTest extends ConsoleActionBaseTestCase {
.isEqualExceptFields(oldRegistrar, "localizedAddress", "phoneNumber", "faxNumber");
ConsoleUpdateHistory history = loadSingleton(ConsoleUpdateHistory.class).get();
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.REGISTRAR_UPDATE);
assertThat(history.getDescription()).hasValue("TheRegistrar");
assertThat(history.getDescription()).hasValue("TheRegistrar|ADDRESS,PHONE,FAX");
}
@Test

View File

@@ -87,7 +87,7 @@ class SecurityActionTest extends ConsoleActionBaseTestCase {
assertThat(r.getIpAddressAllowList().get(0).getNetmask()).isEqualTo(32);
ConsoleUpdateHistory history = loadSingleton(ConsoleUpdateHistory.class).get();
assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.REGISTRAR_SECURITY_UPDATE);
assertThat(history.getDescription()).hasValue("registrarId");
assertThat(history.getDescription()).hasValue("registrarId|IP_CHANGE,PRIMARY_SSL_CERT_CHANGE");
}
private SecurityAction createAction(String registrarId) throws IOException {

View File

@@ -74,6 +74,7 @@ CONSOLE /console-api/domain ConsoleDomainGetActi
CONSOLE /console-api/domain-list ConsoleDomainListAction GET n USER PUBLIC
CONSOLE /console-api/dum-download ConsoleDumDownloadAction GET n USER PUBLIC
CONSOLE /console-api/eppPassword ConsoleEppPasswordAction POST n USER PUBLIC
CONSOLE /console-api/history ConsoleHistoryDataAction GET n USER PUBLIC
CONSOLE /console-api/ote ConsoleOteAction GET,POST n USER PUBLIC
CONSOLE /console-api/password-reset-request PasswordResetRequestAction POST n USER PUBLIC
CONSOLE /console-api/password-reset-verify PasswordResetVerifyAction GET,POST n USER PUBLIC