From c9ac9437fd8663fd13980c2614841a19b3645996 Mon Sep 17 00:00:00 2001 From: Pavlo Tkach <3469726+ptkach@users.noreply.github.com> Date: Sat, 14 Jun 2025 13:37:11 -0400 Subject: [PATCH] Add java code for RegitrarPoc id (#2770) --- .../app/settings/contact/contact.service.ts | 23 +- .../contact/contactDetails.component.ts | 6 +- .../app/shared/services/backend.service.ts | 25 ++- .../model/registrar/RegistrarPoc.java | 9 + .../ui/server/console/ConsoleModule.java | 7 +- .../console/settings/ContactAction.java | 106 ++++++--- .../model/registrar/RegistrarTest.java | 2 + .../schema/registrar/RegistrarPocTest.java | 6 +- .../tools/RegistrarPocCommandTest.java | 17 +- .../console/settings/ContactActionTest.java | 207 ++++++------------ .../module/frontend/frontend_routing.txt | 2 +- .../google/registry/module/routing.txt | 2 +- .../sql/schema/db-schema.sql.generated | 1 + 13 files changed, 215 insertions(+), 198 deletions(-) diff --git a/console-webapp/src/app/settings/contact/contact.service.ts b/console-webapp/src/app/settings/contact/contact.service.ts index 8936553d7..992718ea8 100644 --- a/console-webapp/src/app/settings/contact/contact.service.ts +++ b/console-webapp/src/app/settings/contact/contact.service.ts @@ -24,7 +24,7 @@ export type contactType = | 'LEGAL' | 'MARKETING' | 'TECH' - | 'RDAP'; + | 'WHOIS'; type contactTypesToUserFriendlyTypes = { [type in contactType]: string }; @@ -35,7 +35,7 @@ export const contactTypeToTextMap: contactTypesToUserFriendlyTypes = { LEGAL: 'Legal contact', MARKETING: 'Marketing contact', TECH: 'Technical contact', - RDAP: 'RDAP-Inquiry contact', + WHOIS: 'RDAP-Inquiry contact', }; type UserFriendlyType = (typeof contactTypeToTextMap)[contactType]; @@ -59,7 +59,10 @@ export interface ViewReadyContact extends Contact { export function contactTypeToViewReadyContact(c: Contact): ViewReadyContact { return { ...c, - userFriendlyTypes: c.types?.map((cType) => contactTypeToTextMap[cType]), + userFriendlyTypes: (c.types || []).map( + (cType) => contactTypeToTextMap[cType] + ), + types: c.types || [], }; } @@ -98,19 +101,21 @@ export class ContactService { ); } - saveContacts(contacts: ViewReadyContact[]): Observable { + updateContact(contact: ViewReadyContact) { return this.backend - .postContacts(this.registrarService.registrarId(), contacts) + .updateContact(this.registrarService.registrarId(), contact) .pipe(switchMap((_) => this.fetchContacts())); } addContact(contact: ViewReadyContact) { - const newContacts = this.contacts().concat([contact]); - return this.saveContacts(newContacts); + return this.backend + .createContact(this.registrarService.registrarId(), contact) + .pipe(switchMap((_) => this.fetchContacts())); } deleteContact(contact: ViewReadyContact) { - const newContacts = this.contacts().filter((c) => c !== contact); - return this.saveContacts(newContacts); + return this.backend + .deleteContact(this.registrarService.registrarId(), contact) + .pipe(switchMap((_) => this.fetchContacts())); } } diff --git a/console-webapp/src/app/settings/contact/contactDetails.component.ts b/console-webapp/src/app/settings/contact/contactDetails.component.ts index 0a24ad460..f9158d1c0 100644 --- a/console-webapp/src/app/settings/contact/contactDetails.component.ts +++ b/console-webapp/src/app/settings/contact/contactDetails.component.ts @@ -69,9 +69,13 @@ export class ContactDetailsComponent { save(e: SubmitEvent) { e.preventDefault(); + if ((this.contactService.contactInEdit.types || []).length === 0) { + this._snackBar.open('Required to select contact type'); + return; + } const request = this.contactService.isContactNewView ? this.contactService.addContact(this.contactService.contactInEdit) - : this.contactService.saveContacts(this.contactService.contacts()); + : this.contactService.updateContact(this.contactService.contactInEdit); request.subscribe({ complete: () => { this.goBack(); diff --git a/console-webapp/src/app/shared/services/backend.service.ts b/console-webapp/src/app/shared/services/backend.service.ts index 7c4753dbb..1998881b7 100644 --- a/console-webapp/src/app/shared/services/backend.service.ts +++ b/console-webapp/src/app/shared/services/backend.service.ts @@ -70,13 +70,26 @@ export class BackendService { .pipe(catchError((err) => this.errorCatcher(err))); } - postContacts( - registrarId: string, - contacts: Contact[] - ): Observable { - return this.http.post( + updateContact(registrarId: string, contact: Contact): Observable { + return this.http.put( `/console-api/settings/contacts?registrarId=${registrarId}`, - contacts + contact + ); + } + + createContact(registrarId: string, contact: Contact): Observable { + return this.http.post( + `/console-api/settings/contacts?registrarId=${registrarId}`, + contact + ); + } + + deleteContact(registrarId: string, contact: Contact): Observable { + return this.http.delete( + `/console-api/settings/contacts?registrarId=${registrarId}`, + { + body: JSON.stringify(contact), + } ); } diff --git a/core/src/main/java/google/registry/model/registrar/RegistrarPoc.java b/core/src/main/java/google/registry/model/registrar/RegistrarPoc.java index 5c06ebba6..49236a3a6 100644 --- a/core/src/main/java/google/registry/model/registrar/RegistrarPoc.java +++ b/core/src/main/java/google/registry/model/registrar/RegistrarPoc.java @@ -93,6 +93,10 @@ public class RegistrarPoc extends ImmutableObject implements Jsonifiable, Unsafe } } + @Expose + @Column(insertable = false, updatable = false) + protected Long id; + /** The name of the contact. */ @Expose String name; @@ -179,6 +183,10 @@ public class RegistrarPoc extends ImmutableObject implements Jsonifiable, Unsafe tm().putAll(contacts); } + public Long getId() { + return id; + } + public String getName() { return name; } @@ -295,6 +303,7 @@ public class RegistrarPoc extends ImmutableObject implements Jsonifiable, Unsafe .put("visibleInDomainWhoisAsAbuse", visibleInDomainWhoisAsAbuse) .put("allowedToSetRegistryLockPassword", allowedToSetRegistryLockPassword) .put("registryLockAllowed", isRegistryLockAllowed()) + .put("id", getId()) .build(); } diff --git a/core/src/main/java/google/registry/ui/server/console/ConsoleModule.java b/core/src/main/java/google/registry/ui/server/console/ConsoleModule.java index a4741664a..7b49fec55 100644 --- a/core/src/main/java/google/registry/ui/server/console/ConsoleModule.java +++ b/core/src/main/java/google/registry/ui/server/console/ConsoleModule.java @@ -19,7 +19,6 @@ import static google.registry.request.RequestParameters.extractOptionalIntParame import static google.registry.request.RequestParameters.extractOptionalParameter; import static google.registry.request.RequestParameters.extractRequiredParameter; -import com.google.common.collect.ImmutableSet; import com.google.gson.Gson; import com.google.gson.JsonElement; import dagger.Module; @@ -192,10 +191,10 @@ public final class ConsoleModule { } @Provides - @Parameter("contacts") - public static Optional> provideContacts( + @Parameter("contact") + public static Optional provideContacts( Gson gson, @OptionalJsonPayload Optional payload) { - return payload.map(s -> ImmutableSet.copyOf(gson.fromJson(s, RegistrarPoc[].class))); + return payload.map(s -> gson.fromJson(s, RegistrarPoc.class)); } @Provides diff --git a/core/src/main/java/google/registry/ui/server/console/settings/ContactAction.java b/core/src/main/java/google/registry/ui/server/console/settings/ContactAction.java index 322e62460..246392c88 100644 --- a/core/src/main/java/google/registry/ui/server/console/settings/ContactAction.java +++ b/core/src/main/java/google/registry/ui/server/console/settings/ContactAction.java @@ -19,8 +19,10 @@ import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.Sets.difference; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; +import static google.registry.request.Action.Method.DELETE; import static google.registry.request.Action.Method.GET; import static google.registry.request.Action.Method.POST; +import static google.registry.request.Action.Method.PUT; import static jakarta.servlet.http.HttpServletResponse.SC_OK; import com.google.common.collect.HashMultimap; @@ -40,59 +42,123 @@ import google.registry.request.Action.GkeService; import google.registry.request.Parameter; import google.registry.request.auth.Auth; import google.registry.ui.forms.FormException; -import google.registry.ui.server.RegistrarFormFields; import google.registry.ui.server.console.ConsoleApiAction; import google.registry.ui.server.console.ConsoleApiParams; import jakarta.inject.Inject; -import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.function.BiFunction; @Action( service = GaeService.DEFAULT, gkeService = GkeService.CONSOLE, path = ContactAction.PATH, - method = {GET, POST}, + method = {GET, POST, DELETE, PUT}, auth = Auth.AUTH_PUBLIC_LOGGED_IN) public class ContactAction extends ConsoleApiAction { static final String PATH = "/console-api/settings/contacts"; private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final Optional> contacts; + private final Optional contact; private final String registrarId; @Inject public ContactAction( ConsoleApiParams consoleApiParams, @Parameter("registrarId") String registrarId, - @Parameter("contacts") Optional> contacts) { + @Parameter("contact") Optional contact) { super(consoleApiParams); this.registrarId = registrarId; - this.contacts = contacts; + this.contact = contact; } @Override protected void getHandler(User user) { checkPermission(user, registrarId, ConsolePermission.VIEW_REGISTRAR_DETAILS); - ImmutableList am = + ImmutableList contacts = tm().transact( () -> tm() .createQueryComposer(RegistrarPoc.class) .where("registrarId", Comparator.EQ, registrarId) .stream() - .filter(r -> !r.getTypes().isEmpty()) .collect(toImmutableList())); consoleApiParams.response().setStatus(SC_OK); - consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(am)); + consoleApiParams.response().setPayload(consoleApiParams.gson().toJson(contacts)); + } + + @Override + protected void deleteHandler(User user) { + updateContacts( + user, + (registrar, oldContacts) -> + oldContacts.stream() + .filter( + oldContact -> + !oldContact.getEmailAddress().equals(contact.get().getEmailAddress())) + .collect(toImmutableSet())); } @Override protected void postHandler(User user) { + updateContacts( + user, + (registrar, oldContacts) -> { + RegistrarPoc newContact = contact.get(); + return ImmutableSet.builder() + .addAll(oldContacts) + .add( + new RegistrarPoc() + .asBuilder() + .setTypes(newContact.getTypes()) + .setVisibleInWhoisAsTech(newContact.getVisibleInWhoisAsTech()) + .setVisibleInWhoisAsAdmin(newContact.getVisibleInWhoisAsAdmin()) + .setVisibleInDomainWhoisAsAbuse(newContact.getVisibleInDomainWhoisAsAbuse()) + .setFaxNumber(newContact.getFaxNumber()) + .setName(newContact.getName()) + .setEmailAddress(newContact.getEmailAddress()) + .setPhoneNumber(newContact.getPhoneNumber()) + .setRegistrar(registrar) + .build()) + .build(); + }); + } + + @Override + protected void putHandler(User user) { + updateContacts( + user, + (registrar, oldContacts) -> { + RegistrarPoc updatedContact = contact.get(); + return oldContacts.stream() + .map( + oldContact -> + oldContact.getId().equals(updatedContact.getId()) + ? oldContact + .asBuilder() + .setTypes(updatedContact.getTypes()) + .setVisibleInWhoisAsTech(updatedContact.getVisibleInWhoisAsTech()) + .setVisibleInWhoisAsAdmin(updatedContact.getVisibleInWhoisAsAdmin()) + .setVisibleInDomainWhoisAsAbuse( + updatedContact.getVisibleInDomainWhoisAsAbuse()) + .setFaxNumber(updatedContact.getFaxNumber()) + .setName(updatedContact.getName()) + .setEmailAddress(updatedContact.getEmailAddress()) + .setPhoneNumber(updatedContact.getPhoneNumber()) + .build() + : oldContact) + .collect(toImmutableSet()); + }); + } + + private void updateContacts( + User user, + BiFunction, ImmutableSet> + contactsUpdater) { checkPermission(user, registrarId, ConsolePermission.EDIT_REGISTRAR_DETAILS); - checkArgument(contacts.isPresent(), "Contacts parameter is not present"); + checkArgument(contact.isPresent(), "Contact parameter is not present"); Registrar registrar = Registrar.loadByRegistrarId(registrarId) .orElseThrow( @@ -101,20 +167,10 @@ public class ContactAction extends ConsoleApiAction { String.format("Unknown registrar %s", registrarId))); ImmutableSet oldContacts = registrar.getContacts(); - ImmutableSet updatedContacts = - RegistrarFormFields.getRegistrarContactBuilders( - oldContacts, - Collections.singletonMap( - "contacts", - contacts.get().stream() - .map(RegistrarPoc::toJsonMap) - .collect(toImmutableList()))) - .stream() - .map(builder -> builder.setRegistrar(registrar).build()) - .collect(toImmutableSet()); + ImmutableSet newContacts = contactsUpdater.apply(registrar, oldContacts); try { - checkContactRequirements(oldContacts, updatedContacts); + checkContactRequirements(oldContacts, newContacts); } catch (FormException e) { logger.atWarning().withCause(e).log( "Error processing contacts post request for registrar: %s", registrarId); @@ -123,14 +179,13 @@ public class ContactAction extends ConsoleApiAction { tm().transact( () -> { - RegistrarPoc.updateContacts(registrar, updatedContacts); + RegistrarPoc.updateContacts(registrar, newContacts); Registrar updatedRegistrar = registrar.asBuilder().setContactsRequireSyncing(true).build(); tm().put(updatedRegistrar); sendExternalUpdatesIfNecessary( - EmailInfo.create(registrar, updatedRegistrar, oldContacts, updatedContacts)); + EmailInfo.create(registrar, updatedRegistrar, oldContacts, newContacts)); }); - consoleApiParams.response().setStatus(SC_OK); } @@ -169,6 +224,7 @@ public class ContactAction extends ConsoleApiAction { throw new ContactRequirementException(t); } } + enforcePrimaryContactRestrictions(oldContactsByType, newContactsByType); ensurePhoneNumberNotRemovedForContactTypes(oldContactsByType, newContactsByType, Type.TECH); Optional domainWhoisAbuseContact = diff --git a/core/src/test/java/google/registry/model/registrar/RegistrarTest.java b/core/src/test/java/google/registry/model/registrar/RegistrarTest.java index f12ab8c5d..34654b05a 100644 --- a/core/src/test/java/google/registry/model/registrar/RegistrarTest.java +++ b/core/src/test/java/google/registry/model/registrar/RegistrarTest.java @@ -44,6 +44,7 @@ import google.registry.model.registrar.Registrar.Type; import google.registry.model.tld.Tld; import google.registry.model.tld.Tld.TldType; import google.registry.model.tld.Tlds; +import google.registry.testing.DatabaseHelper; import google.registry.util.CidrAddressBlock; import google.registry.util.SerializeUtils; import java.math.BigDecimal; @@ -340,6 +341,7 @@ class RegistrarTest extends EntityTestCase { .setFaxNumber("+1.2125551213") .setTypes(ImmutableSet.of(RegistrarPoc.Type.TECH, RegistrarPoc.Type.ABUSE)) .build()); + abuseAdminContact = DatabaseHelper.loadByKey(abuseAdminContact.createVKey()); ImmutableSortedSet techContacts = registrar.getContactsOfType(RegistrarPoc.Type.TECH); assertThat(techContacts).containsExactly(newTechContact, newTechAbuseContact).inOrder(); diff --git a/core/src/test/java/google/registry/schema/registrar/RegistrarPocTest.java b/core/src/test/java/google/registry/schema/registrar/RegistrarPocTest.java index c62aabaa3..12589f330 100644 --- a/core/src/test/java/google/registry/schema/registrar/RegistrarPocTest.java +++ b/core/src/test/java/google/registry/schema/registrar/RegistrarPocTest.java @@ -15,10 +15,10 @@ package google.registry.schema.registrar; import static com.google.common.truth.Truth.assertThat; +import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; import static google.registry.model.registrar.RegistrarPoc.Type.WHOIS; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatabaseHelper.insertInDb; -import static google.registry.testing.DatabaseHelper.loadByEntity; import static google.registry.testing.SqlHelper.saveRegistrar; import com.google.common.collect.ImmutableSet; @@ -63,7 +63,9 @@ class RegistrarPocTest { @Test void testPersistence_succeeds() { insertInDb(testRegistrarPoc); - assertThat(loadByEntity(testRegistrarPoc)).isEqualTo(testRegistrarPoc); + assertAboutImmutableObjects() + .that(testRegistrarPoc) + .isEqualExceptFields(testRegistrarPoc, "id"); } @Test diff --git a/core/src/test/java/google/registry/tools/RegistrarPocCommandTest.java b/core/src/test/java/google/registry/tools/RegistrarPocCommandTest.java index 2eab7be2d..c71544528 100644 --- a/core/src/test/java/google/registry/tools/RegistrarPocCommandTest.java +++ b/core/src/test/java/google/registry/tools/RegistrarPocCommandTest.java @@ -15,6 +15,7 @@ package google.registry.tools; import static com.google.common.truth.Truth.assertThat; +import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; import static google.registry.model.registrar.RegistrarPoc.Type.ABUSE; import static google.registry.model.registrar.RegistrarPoc.Type.ADMIN; import static google.registry.model.registrar.RegistrarPoc.Type.TECH; @@ -102,8 +103,9 @@ class RegistrarPocCommandTest extends CommandTestCase { "--visible_in_domain_whois_as_abuse=false", "NewRegistrar"); RegistrarPoc registrarPoc = loadRegistrar("NewRegistrar").getContacts().asList().get(1); - assertThat(registrarPoc) - .isEqualTo( + assertAboutImmutableObjects() + .that(registrarPoc) + .isEqualExceptFields( new RegistrarPoc.Builder() .setRegistrar(registrar) .setName("Judith Registrar") @@ -115,7 +117,8 @@ class RegistrarPocCommandTest extends CommandTestCase { .setVisibleInWhoisAsAdmin(true) .setVisibleInWhoisAsTech(false) .setVisibleInDomainWhoisAsAbuse(false) - .build()); + .build(), + "id"); } @Test @@ -261,8 +264,9 @@ class RegistrarPocCommandTest extends CommandTestCase { "--visible_in_domain_whois_as_abuse=true", "NewRegistrar"); RegistrarPoc registrarPoc = loadRegistrar("NewRegistrar").getContacts().asList().get(1); - assertThat(registrarPoc) - .isEqualTo( + assertAboutImmutableObjects() + .that(registrarPoc) + .isEqualExceptFields( new RegistrarPoc.Builder() .setRegistrar(registrar) .setName("Jim Doe") @@ -272,7 +276,8 @@ class RegistrarPocCommandTest extends CommandTestCase { .setVisibleInWhoisAsAdmin(true) .setVisibleInWhoisAsTech(false) .setVisibleInDomainWhoisAsAbuse(true) - .build()); + .build(), + "id"); } @Test diff --git a/core/src/test/java/google/registry/ui/server/console/settings/ContactActionTest.java b/core/src/test/java/google/registry/ui/server/console/settings/ContactActionTest.java index 00338b69a..911012bfa 100644 --- a/core/src/test/java/google/registry/ui/server/console/settings/ContactActionTest.java +++ b/core/src/test/java/google/registry/ui/server/console/settings/ContactActionTest.java @@ -20,8 +20,10 @@ import static google.registry.model.registrar.RegistrarPoc.Type.ABUSE; import static google.registry.model.registrar.RegistrarPoc.Type.ADMIN; import static google.registry.model.registrar.RegistrarPoc.Type.MARKETING; import static google.registry.model.registrar.RegistrarPoc.Type.TECH; +import static google.registry.testing.DatabaseHelper.deleteResource; import static google.registry.testing.DatabaseHelper.insertInDb; import static google.registry.testing.DatabaseHelper.loadAllOf; +import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.SqlHelper.saveRegistrar; import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN; @@ -57,7 +59,7 @@ import org.junit.jupiter.api.Test; /** Tests for {@link google.registry.ui.server.console.settings.ContactAction}. */ class ContactActionTest extends ConsoleActionBaseTestCase { private static String jsonRegistrar1 = - "{\"name\":\"Test Registrar 1\"," + "{\"id\":%s,\"name\":\"Test Registrar 1\"," + "\"emailAddress\":\"test.registrar1@example.com\"," + "\"registrarId\":\"registrarId\"," + "\"phoneNumber\":\"+1.9999999999\",\"faxNumber\":\"+1.9999999991\"," @@ -73,17 +75,18 @@ class ContactActionTest extends ConsoleActionBaseTestCase { void beforeEach() { testRegistrar = saveRegistrar("registrarId"); adminPoc = - new RegistrarPoc.Builder() - .setRegistrar(testRegistrar) - .setName("Test Registrar 1") - .setEmailAddress("test.registrar1@example.com") - .setPhoneNumber("+1.9999999999") - .setFaxNumber("+1.9999999991") - .setTypes(ImmutableSet.of(ADMIN)) - .setVisibleInWhoisAsAdmin(true) - .setVisibleInWhoisAsTech(false) - .setVisibleInDomainWhoisAsAbuse(false) - .build(); + persistResource( + new RegistrarPoc.Builder() + .setRegistrar(testRegistrar) + .setName("Test Registrar 1") + .setEmailAddress("test.registrar1@example.com") + .setPhoneNumber("+1.9999999999") + .setFaxNumber("+1.9999999991") + .setTypes(ImmutableSet.of(ADMIN)) + .setVisibleInWhoisAsAdmin(true) + .setVisibleInWhoisAsTech(false) + .setVisibleInDomainWhoisAsAbuse(false) + .build()); techPoc = adminPoc .asBuilder() @@ -109,39 +112,26 @@ class ContactActionTest extends ConsoleActionBaseTestCase { @Test void testSuccess_getContactInfo() throws IOException { - insertInDb(adminPoc); - ContactAction action = createAction(Action.Method.GET, fteUser, testRegistrar.getRegistrarId()); + ContactAction action = + createAction(Action.Method.GET, fteUser, testRegistrar.getRegistrarId(), null); action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); - assertThat(response.getPayload()).isEqualTo("[" + jsonRegistrar1 + "]"); + assertThat(response.getPayload()).contains(String.format(jsonRegistrar1, adminPoc.getId())); } @Test void testSuccess_noOp() throws IOException { - insertInDb(adminPoc); ContactAction action = - createAction(Action.Method.POST, fteUser, testRegistrar.getRegistrarId(), adminPoc); + createAction(Action.Method.PUT, fteUser, testRegistrar.getRegistrarId(), adminPoc); action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); verify(consoleApiParams.sendEmailUtils().gmailClient, never()).sendEmail(any()); } - @Test - void testSuccess_onlyContactsWithNonEmptyType() throws IOException { - adminPoc = adminPoc.asBuilder().setTypes(ImmutableSet.of()).build(); - insertInDb(adminPoc); - ContactAction action = createAction(Action.Method.GET, fteUser, testRegistrar.getRegistrarId()); - action.run(); - assertThat(response.getStatus()).isEqualTo(SC_OK); - assertThat(response.getPayload()).isEqualTo("[]"); - } - @Test void testSuccess_postCreateContactInfo() throws IOException { - insertInDb(adminPoc); ContactAction action = - createAction( - Action.Method.POST, fteUser, testRegistrar.getRegistrarId(), adminPoc, techPoc); + createAction(Action.Method.POST, fteUser, testRegistrar.getRegistrarId(), techPoc); action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); assertThat( @@ -154,10 +144,14 @@ class ContactActionTest extends ConsoleActionBaseTestCase { @Test void testSuccess_postUpdateContactInfo() throws IOException { - insertInDb(techPoc.asBuilder().setEmailAddress("incorrect@email.com").build()); + RegistrarPoc techPocIncorrect = + persistResource(techPoc.asBuilder().setEmailAddress("incorrect@email.com").build()); ContactAction action = createAction( - Action.Method.POST, fteUser, testRegistrar.getRegistrarId(), adminPoc, techPoc); + Action.Method.PUT, + fteUser, + testRegistrar.getRegistrarId(), + techPocIncorrect.asBuilder().setEmailAddress(techPoc.getEmailAddress()).build()); action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); HashMap testResult = new HashMap<>(); @@ -174,12 +168,12 @@ class ContactActionTest extends ConsoleActionBaseTestCase { @Test void testFailure_postUpdateContactInfo_duplicateEmails() throws IOException { + insertInDb(techPoc); ContactAction action = createAction( Action.Method.POST, fteUser, testRegistrar.getRegistrarId(), - adminPoc, techPoc.asBuilder().setEmailAddress("test.registrar1@example.com").build()); action.run(); assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST); @@ -189,16 +183,16 @@ class ContactActionTest extends ConsoleActionBaseTestCase { assertThat( loadAllOf(RegistrarPoc.class).stream() .filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId())) + .map(r -> r.getName()) .collect(toImmutableList())) - .isEmpty(); + .containsExactly("Test Registrar 1", "Test Registrar 2"); } @Test void testFailure_postUpdateContactInfo_requiredContactRemoved() throws IOException { - insertInDb(adminPoc); ContactAction action = createAction( - Action.Method.POST, + Action.Method.PUT, fteUser, testRegistrar.getRegistrarId(), adminPoc.asBuilder().setTypes(ImmutableSet.of(ABUSE)).build()); @@ -214,11 +208,10 @@ class ContactActionTest extends ConsoleActionBaseTestCase { @Test void testFailure_postUpdateContactInfo_phoneNumberRemoved() throws IOException { - adminPoc = adminPoc.asBuilder().setTypes(ImmutableSet.of(ADMIN, TECH)).build(); - insertInDb(adminPoc); + adminPoc = persistResource(adminPoc.asBuilder().setTypes(ImmutableSet.of(ADMIN, TECH)).build()); ContactAction action = createAction( - Action.Method.POST, + Action.Method.PUT, fteUser, testRegistrar.getRegistrarId(), adminPoc @@ -244,25 +237,19 @@ class ContactActionTest extends ConsoleActionBaseTestCase { Action.Method.POST, fteUser, testRegistrar.getRegistrarId(), - adminPoc.asBuilder().setPhoneNumber(null).setVisibleInDomainWhoisAsAbuse(true).build()); + techPoc.asBuilder().setPhoneNumber(null).setVisibleInDomainWhoisAsAbuse(true).build()); action.run(); assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST); assertThat(response.getPayload()) .isEqualTo("The abuse contact visible in domain WHOIS query must have a phone number"); - assertThat( - loadAllOf(RegistrarPoc.class).stream() - .filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId())) - .collect(toImmutableList())) - .isEmpty(); } @Test void testFailure_postUpdateContactInfo_whoisContactPhoneNumberRemoved() throws IOException { - adminPoc = adminPoc.asBuilder().setVisibleInDomainWhoisAsAbuse(true).build(); - insertInDb(adminPoc); + adminPoc = persistResource(adminPoc.asBuilder().setVisibleInDomainWhoisAsAbuse(true).build()); ContactAction action = createAction( - Action.Method.POST, + Action.Method.PUT, fteUser, testRegistrar.getRegistrarId(), adminPoc.asBuilder().setVisibleInDomainWhoisAsAbuse(false).build()); @@ -277,88 +264,17 @@ class ContactActionTest extends ConsoleActionBaseTestCase { .containsExactly(adminPoc); } - @Test - void testFailure_postUpdateContactInfo_newContactCannotSetRegistryLockPassword() - throws IOException { - ContactAction action = - createAction( - Action.Method.POST, - fteUser, - testRegistrar.getRegistrarId(), - adminPoc - .asBuilder() - .setAllowedToSetRegistryLockPassword(true) - .setRegistryLockEmailAddress("lock@example.com") - .build()); - action.run(); - assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST); - assertThat(response.getPayload()) - .isEqualTo("Cannot set registry lock password directly on new contact"); - assertThat( - loadAllOf(RegistrarPoc.class).stream() - .filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId())) - .collect(toImmutableList())) - .isEmpty(); - } - - @Test - void testFailure_postUpdateContactInfo_cannotModifyRegistryLockEmail() throws IOException { - adminPoc = - adminPoc - .asBuilder() - .setRegistryLockEmailAddress("lock@example.com") - .setAllowedToSetRegistryLockPassword(true) - .build(); - insertInDb(adminPoc); - ContactAction action = - createAction( - Action.Method.POST, - fteUser, - testRegistrar.getRegistrarId(), - adminPoc.asBuilder().setRegistryLockEmailAddress("unlock@example.com").build()); - action.run(); - assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST); - assertThat(response.getPayload()) - .isEqualTo("Cannot modify registryLockEmailAddress through the UI"); - assertThat( - loadAllOf(RegistrarPoc.class).stream() - .filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId())) - .collect(toImmutableList())) - .containsExactly(adminPoc); - } - - @Test - void testFailure_postUpdateContactInfo_cannotSetIsAllowedToSetRegistryLockPassword() - throws IOException { - adminPoc = - adminPoc - .asBuilder() - .setRegistryLockEmailAddress("lock@example.com") - .setAllowedToSetRegistryLockPassword(false) - .build(); - insertInDb(adminPoc); - ContactAction action = - createAction( - Action.Method.POST, - fteUser, - testRegistrar.getRegistrarId(), - adminPoc.asBuilder().setAllowedToSetRegistryLockPassword(true).build()); - action.run(); - assertThat(response.getStatus()).isEqualTo(SC_BAD_REQUEST); - assertThat(response.getPayload()) - .isEqualTo("Cannot modify isAllowedToSetRegistryLockPassword through the UI"); - assertThat( - loadAllOf(RegistrarPoc.class).stream() - .filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId())) - .collect(toImmutableList())) - .containsExactly(adminPoc); - } - @Test void testSuccess_sendsEmail() throws IOException, AddressException { - insertInDb(techPoc.asBuilder().setEmailAddress("incorrect@email.com").build()); + deleteResource(adminPoc); + techPoc = persistResource(techPoc); + Long id = techPoc.getId(); ContactAction action = - createAction(Action.Method.POST, fteUser, testRegistrar.getRegistrarId(), techPoc); + createAction( + Action.Method.PUT, + fteUser, + testRegistrar.getRegistrarId(), + techPoc.asBuilder().setEmailAddress("incorrect@example.com").build()); action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); verify(consoleApiParams.sendEmailUtils().gmailClient, times(1)) @@ -373,23 +289,29 @@ class ContactActionTest extends ConsoleActionBaseTestCase { + "\n" + "contacts:\n" + " ADDED:\n" - + " {name=Test Registrar 2," - + " emailAddress=test.registrar2@example.com, registrarId=registrarId," + + " {id=" + + id + + ", name=Test Registrar 2," + + " emailAddress=incorrect@example.com, registrarId=registrarId," + " registryLockEmailAddress=null, phoneNumber=+1.1234567890," + " faxNumber=+1.1234567891, types=[TECH]," + " visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=true," + " visibleInDomainWhoisAsAbuse=false," + " allowedToSetRegistryLockPassword=false}\n" + " REMOVED:\n" - + " {name=Test Registrar 2, emailAddress=incorrect@email.com," + + " {id=" + + id + + ", name=Test Registrar 2, emailAddress=test.registrar2@example.com," + " registrarId=registrarId, registryLockEmailAddress=null," + " phoneNumber=+1.1234567890, faxNumber=+1.1234567891, types=[TECH]," + " visibleInWhoisAsAdmin=false," + " visibleInWhoisAsTech=true, visibleInDomainWhoisAsAbuse=false," + " allowedToSetRegistryLockPassword=false}\n" + " FINAL CONTENTS:\n" - + " {name=Test Registrar 2," - + " emailAddress=test.registrar2@example.com, registrarId=registrarId," + + " {id=" + + id + + ", name=Test Registrar 2," + + " emailAddress=incorrect@example.com, registrarId=registrarId," + " registryLockEmailAddress=null, phoneNumber=+1.1234567890," + " faxNumber=+1.1234567891, types=[TECH]," + " visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=true," @@ -401,10 +323,9 @@ class ContactActionTest extends ConsoleActionBaseTestCase { @Test void testSuccess_postDeleteContactInfo() throws IOException { - insertInDb(adminPoc, techPoc, marketingPoc); + insertInDb(techPoc, marketingPoc); ContactAction action = - createAction( - Action.Method.POST, fteUser, testRegistrar.getRegistrarId(), adminPoc, techPoc); + createAction(Action.Method.DELETE, fteUser, testRegistrar.getRegistrarId(), marketingPoc); action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); assertThat( @@ -417,10 +338,9 @@ class ContactActionTest extends ConsoleActionBaseTestCase { @Test void testFailure_postDeleteContactInfo_missingPermission() throws IOException { - insertInDb(adminPoc); ContactAction action = createAction( - Action.Method.POST, + Action.Method.DELETE, new User.Builder() .setEmailAddress("email@email.com") .setUserRoles( @@ -438,9 +358,12 @@ class ContactActionTest extends ConsoleActionBaseTestCase { @Test void testFailure_changesAdminEmail() throws Exception { - insertInDb(adminPoc.asBuilder().setEmailAddress("oldemail@example.com").build()); ContactAction action = - createAction(Action.Method.POST, fteUser, testRegistrar.getRegistrarId(), adminPoc); + createAction( + Action.Method.PUT, + fteUser, + testRegistrar.getRegistrarId(), + adminPoc.asBuilder().setEmailAddress("testemail@example.com").build()); action.run(); FakeResponse fakeResponse = response; assertThat(fakeResponse.getStatus()).isEqualTo(400); @@ -449,16 +372,14 @@ class ContactActionTest extends ConsoleActionBaseTestCase { } private ContactAction createAction( - Action.Method method, User user, String registrarId, RegistrarPoc... contacts) + Action.Method method, User user, String registrarId, RegistrarPoc contact) throws IOException { consoleApiParams = ConsoleApiParamsUtils.createFake(AuthResult.createUser(user)); when(consoleApiParams.request().getMethod()).thenReturn(method.toString()); response = (FakeResponse) consoleApiParams.response(); if (method.equals(Action.Method.GET)) { return new ContactAction(consoleApiParams, registrarId, Optional.empty()); - } else { - return new ContactAction( - consoleApiParams, registrarId, Optional.of(ImmutableSet.copyOf(contacts))); } + return new ContactAction(consoleApiParams, registrarId, Optional.of(contact)); } } diff --git a/core/src/test/resources/google/registry/module/frontend/frontend_routing.txt b/core/src/test/resources/google/registry/module/frontend/frontend_routing.txt index 0696df9ee..0088f6899 100644 --- a/core/src/test/resources/google/registry/module/frontend/frontend_routing.txt +++ b/core/src/test/resources/google/registry/module/frontend/frontend_routing.txt @@ -11,7 +11,7 @@ CONSOLE /console-api/registrar ConsoleUpdateRegistrarAction POST CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET n USER PUBLIC -CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC +CONSOLE /console-api/settings/contacts ContactAction GET,POST,DELETE,PUT n USER PUBLIC CONSOLE /console-api/settings/rdap-fields RdapRegistrarFieldsAction POST n USER PUBLIC CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC diff --git a/core/src/test/resources/google/registry/module/routing.txt b/core/src/test/resources/google/registry/module/routing.txt index f89d1b622..8ec087d6a 100644 --- a/core/src/test/resources/google/registry/module/routing.txt +++ b/core/src/test/resources/google/registry/module/routing.txt @@ -79,7 +79,7 @@ CONSOLE /console-api/registrar ConsoleUpdateRegistr CONSOLE /console-api/registrars RegistrarsAction GET,POST n USER PUBLIC CONSOLE /console-api/registry-lock ConsoleRegistryLockAction GET,POST n USER PUBLIC CONSOLE /console-api/registry-lock-verify ConsoleRegistryLockVerifyAction GET n USER PUBLIC -CONSOLE /console-api/settings/contacts ContactAction GET,POST n USER PUBLIC +CONSOLE /console-api/settings/contacts ContactAction GET,POST,DELETE,PUT n USER PUBLIC CONSOLE /console-api/settings/rdap-fields RdapRegistrarFieldsAction POST n USER PUBLIC CONSOLE /console-api/settings/security SecurityAction POST n USER PUBLIC CONSOLE /console-api/userdata ConsoleUserDataAction GET n USER PUBLIC diff --git a/db/src/main/resources/sql/schema/db-schema.sql.generated b/db/src/main/resources/sql/schema/db-schema.sql.generated index e766b22a5..2465a2e86 100644 --- a/db/src/main/resources/sql/schema/db-schema.sql.generated +++ b/db/src/main/resources/sql/schema/db-schema.sql.generated @@ -674,6 +674,7 @@ registrar_id text not null, allowed_to_set_registry_lock_password boolean not null, fax_number text, + id bigint, name text, phone_number text, registry_lock_email_address text,