1919import static com .google .common .collect .ImmutableSet .toImmutableSet ;
2020import static com .google .common .collect .Sets .difference ;
2121import static google .registry .persistence .transaction .TransactionManagerFactory .tm ;
22+ import static google .registry .request .Action .Method .DELETE ;
2223import static google .registry .request .Action .Method .GET ;
2324import static google .registry .request .Action .Method .POST ;
25+ import static google .registry .request .Action .Method .PUT ;
2426import static jakarta .servlet .http .HttpServletResponse .SC_OK ;
2527
2628import com .google .common .collect .HashMultimap ;
4042import google .registry .request .Parameter ;
4143import google .registry .request .auth .Auth ;
4244import google .registry .ui .forms .FormException ;
43- import google .registry .ui .server .RegistrarFormFields ;
4445import google .registry .ui .server .console .ConsoleApiAction ;
4546import google .registry .ui .server .console .ConsoleApiParams ;
4647import jakarta .inject .Inject ;
47- import java .util .Collections ;
4848import java .util .HashSet ;
4949import java .util .Objects ;
5050import java .util .Optional ;
5151import java .util .Set ;
52+ import java .util .function .BiFunction ;
5253
5354@ Action (
5455 service = GaeService .DEFAULT ,
5556 gkeService = GkeService .CONSOLE ,
5657 path = ContactAction .PATH ,
57- method = {GET , POST },
58+ method = {GET , POST , DELETE , PUT },
5859 auth = Auth .AUTH_PUBLIC_LOGGED_IN )
5960public class ContactAction extends ConsoleApiAction {
6061 static final String PATH = "/console-api/settings/contacts" ;
6162 private static final FluentLogger logger = FluentLogger .forEnclosingClass ();
62- private final Optional <ImmutableSet < RegistrarPoc >> contacts ;
63+ private final Optional <RegistrarPoc > contact ;
6364 private final String registrarId ;
6465
6566 @ Inject
6667 public ContactAction (
6768 ConsoleApiParams consoleApiParams ,
6869 @ Parameter ("registrarId" ) String registrarId ,
69- @ Parameter ("contacts " ) Optional <ImmutableSet < RegistrarPoc >> contacts ) {
70+ @ Parameter ("contact " ) Optional <RegistrarPoc > contact ) {
7071 super (consoleApiParams );
7172 this .registrarId = registrarId ;
72- this .contacts = contacts ;
73+ this .contact = contact ;
7374 }
7475
7576 @ Override
7677 protected void getHandler (User user ) {
7778 checkPermission (user , registrarId , ConsolePermission .VIEW_REGISTRAR_DETAILS );
78- ImmutableList <RegistrarPoc > am =
79+ ImmutableList <RegistrarPoc > contacts =
7980 tm ().transact (
8081 () ->
8182 tm ()
8283 .createQueryComposer (RegistrarPoc .class )
8384 .where ("registrarId" , Comparator .EQ , registrarId )
8485 .stream ()
85- .filter (r -> !r .getTypes ().isEmpty ())
8686 .collect (toImmutableList ()));
8787
8888 consoleApiParams .response ().setStatus (SC_OK );
89- consoleApiParams .response ().setPayload (consoleApiParams .gson ().toJson (am ));
89+ consoleApiParams .response ().setPayload (consoleApiParams .gson ().toJson (contacts ));
90+ }
91+
92+ @ Override
93+ protected void deleteHandler (User user ) {
94+ updateContacts (
95+ user ,
96+ (registrar , oldContacts ) ->
97+ oldContacts .stream ()
98+ .filter (
99+ oldContact ->
100+ !oldContact .getEmailAddress ().equals (contact .get ().getEmailAddress ()))
101+ .collect (toImmutableSet ()));
90102 }
91103
92104 @ Override
93105 protected void postHandler (User user ) {
106+ updateContacts (
107+ user ,
108+ (registrar , oldContacts ) -> {
109+ RegistrarPoc newContact = contact .get ();
110+ return ImmutableSet .<RegistrarPoc >builder ()
111+ .addAll (oldContacts )
112+ .add (
113+ new RegistrarPoc ()
114+ .asBuilder ()
115+ .setTypes (newContact .getTypes ())
116+ .setVisibleInWhoisAsTech (newContact .getVisibleInWhoisAsTech ())
117+ .setVisibleInWhoisAsAdmin (newContact .getVisibleInWhoisAsAdmin ())
118+ .setVisibleInDomainWhoisAsAbuse (newContact .getVisibleInDomainWhoisAsAbuse ())
119+ .setFaxNumber (newContact .getFaxNumber ())
120+ .setName (newContact .getName ())
121+ .setEmailAddress (newContact .getEmailAddress ())
122+ .setPhoneNumber (newContact .getPhoneNumber ())
123+ .setRegistrar (registrar )
124+ .build ())
125+ .build ();
126+ });
127+ }
128+
129+ @ Override
130+ protected void putHandler (User user ) {
131+ updateContacts (
132+ user ,
133+ (registrar , oldContacts ) -> {
134+ RegistrarPoc updatedContact = contact .get ();
135+ return oldContacts .stream ()
136+ .map (
137+ oldContact ->
138+ oldContact .getId ().equals (updatedContact .getId ())
139+ ? oldContact
140+ .asBuilder ()
141+ .setTypes (updatedContact .getTypes ())
142+ .setVisibleInWhoisAsTech (updatedContact .getVisibleInWhoisAsTech ())
143+ .setVisibleInWhoisAsAdmin (updatedContact .getVisibleInWhoisAsAdmin ())
144+ .setVisibleInDomainWhoisAsAbuse (
145+ updatedContact .getVisibleInDomainWhoisAsAbuse ())
146+ .setFaxNumber (updatedContact .getFaxNumber ())
147+ .setName (updatedContact .getName ())
148+ .setEmailAddress (updatedContact .getEmailAddress ())
149+ .setPhoneNumber (updatedContact .getPhoneNumber ())
150+ .build ()
151+ : oldContact )
152+ .collect (toImmutableSet ());
153+ });
154+ }
155+
156+ private void updateContacts (
157+ User user ,
158+ BiFunction <Registrar , ImmutableSet <RegistrarPoc >, ImmutableSet <RegistrarPoc >>
159+ contactsUpdater ) {
94160 checkPermission (user , registrarId , ConsolePermission .EDIT_REGISTRAR_DETAILS );
95- checkArgument (contacts .isPresent (), "Contacts parameter is not present" );
161+ checkArgument (contact .isPresent (), "Contact parameter is not present" );
96162 Registrar registrar =
97163 Registrar .loadByRegistrarId (registrarId )
98164 .orElseThrow (
@@ -101,20 +167,10 @@ protected void postHandler(User user) {
101167 String .format ("Unknown registrar %s" , registrarId )));
102168
103169 ImmutableSet <RegistrarPoc > oldContacts = registrar .getContacts ();
104- ImmutableSet <RegistrarPoc > updatedContacts =
105- RegistrarFormFields .getRegistrarContactBuilders (
106- oldContacts ,
107- Collections .singletonMap (
108- "contacts" ,
109- contacts .get ().stream ()
110- .map (RegistrarPoc ::toJsonMap )
111- .collect (toImmutableList ())))
112- .stream ()
113- .map (builder -> builder .setRegistrar (registrar ).build ())
114- .collect (toImmutableSet ());
170+ ImmutableSet <RegistrarPoc > newContacts = contactsUpdater .apply (registrar , oldContacts );
115171
116172 try {
117- checkContactRequirements (oldContacts , updatedContacts );
173+ checkContactRequirements (oldContacts , newContacts );
118174 } catch (FormException e ) {
119175 logger .atWarning ().withCause (e ).log (
120176 "Error processing contacts post request for registrar: %s" , registrarId );
@@ -123,14 +179,13 @@ protected void postHandler(User user) {
123179
124180 tm ().transact (
125181 () -> {
126- RegistrarPoc .updateContacts (registrar , updatedContacts );
182+ RegistrarPoc .updateContacts (registrar , newContacts );
127183 Registrar updatedRegistrar =
128184 registrar .asBuilder ().setContactsRequireSyncing (true ).build ();
129185 tm ().put (updatedRegistrar );
130186 sendExternalUpdatesIfNecessary (
131- EmailInfo .create (registrar , updatedRegistrar , oldContacts , updatedContacts ));
187+ EmailInfo .create (registrar , updatedRegistrar , oldContacts , newContacts ));
132188 });
133-
134189 consoleApiParams .response ().setStatus (SC_OK );
135190 }
136191
@@ -169,6 +224,7 @@ private static void checkContactRequirements(
169224 throw new ContactRequirementException (t );
170225 }
171226 }
227+
172228 enforcePrimaryContactRestrictions (oldContactsByType , newContactsByType );
173229 ensurePhoneNumberNotRemovedForContactTypes (oldContactsByType , newContactsByType , Type .TECH );
174230 Optional <RegistrarPoc > domainWhoisAbuseContact =
0 commit comments