66
77use  Icinga \Exception \Http \HttpBadRequestException ;
88use  Icinga \Exception \Http \HttpException ;
9+ use  Icinga \Exception \Http \HttpNotFoundException ;
910use  Icinga \Module \Notifications \Common \Database ;
1011use  Icinga \Util \Environment ;
1112use  Icinga \Util \Json ;
@@ -164,13 +165,12 @@ function (Filter\Condition $condition) {
164165                $ dbbeginTransaction ();
165166
166167                if  ($ identifiernull ) {
167-                     $ identifier$ data'id ' ];
168- 
169-                     if  ($ this getContactId ($ identifiernull ) {
168+                     if  ($ this getContactId ($ data'id ' ]) !== null ) {
170169                        throw  new  HttpException ('422 ' , 'Contact already exists ' );
171170                    }
172171
173172                    $ this addContact ($ data
173+                     $ identifier$ data'id ' ];
174174                } else  {
175175                    $ contactId$ this getContactId ($ identifier
176176                    if  ($ contactIdnull ) {
@@ -181,9 +181,10 @@ function (Filter\Condition $condition) {
181181                        throw  new  HttpException ('422 ' , 'Contact already exists ' );
182182                    }
183183
184-                     $ identifier$ data'id ' ];
185184                    $ this removeContact ($ contactId
186185                    $ this addContact ($ data
186+ 
187+                     $ identifier$ data'id ' ];
187188                }
188189
189190                $ dbcommitTransaction ();
@@ -219,24 +220,11 @@ function (Filter\Condition $condition) {
219220                    $ dbdelete ('contactgroup_member ' , ['contact_id = ? '  => $ contactId
220221
221222                    if  (! empty ($ data'addresses ' ])) {
222-                         foreach  ($ data'addresses ' ] as  $ type$ address
223-                             $ dbinsert ('contact_address ' , [
224-                                 'contact_id '     => $ contactId
225-                                 'type '           => $ type
226-                                 'address '        => $ address
227-                             ]);
228-                         }
223+                         $ this addAddresses ($ contactId$ data'addresses ' ]);
229224                    }
230225
231226                    if  (! empty ($ data'groups ' ])) {
232-                         $ this assertGroupsExist ($ data'groups ' ]);
233- 
234-                         foreach  ($ data'groups ' ] as  $ group
235-                             $ dbinsert ('contactgroup_member ' , [
236-                                 'contact_id '         => $ contactId
237-                                 'contactgroup_id '    => $ group
238-                             ]);
239-                         }
227+                         $ this addGroups ($ contactId$ data'groups ' ]);
240228                    }
241229
242230                    $ responseCode204 ;
@@ -282,7 +270,8 @@ function (Filter\Condition $condition) {
282270     * @param string $channelName 
283271     * 
284272     * @return int 
285-      * @throws HttpException if the channel does not exist 
273+      * 
274+      * @throws HttpNotFoundException if the channel does not exist 
286275     */ 
287276    private  function  getChannelId (string  $ channelNameint 
288277    {
@@ -294,7 +283,7 @@ private function getChannelId(string $channelName): int
294283        );
295284
296285        if  ($ channelfalse ) {
297-             throw  new  HttpException ( ' 404 ' ,  'Channel not found ' );
286+             throw  new  HttpNotFoundException ( 'Channel not found ' );
298287        }
299288
300289        return  $ channelid ;
@@ -341,24 +330,28 @@ private function fetchGroupIdentifiers(int $contactId): ?array
341330    }
342331
343332    /** 
344-      * Assert that  the given  group IDs exist  
333+      * Get  the group id with the given identifier  
345334     * 
346-      * @param array $groupIds  
335+      * @param string $identifier  
347336     * 
348-      * @throws HttpException 404 if a group does not exist 
337+      * @return int 
338+      * 
339+      * @throws HttpNotFoundException if the contactgroup with the given identifier does not exist 
349340     */ 
350-     private  function  assertGroupsExist ( array   $ groupIds void 
341+     private  function  getGroupId ( string   $ identifier int 
351342    {
352-         $ existingGroupIds get ()->fetchCol (
343+         $ group get ()->fetchOne (
353344            (new  Select ())
354345                ->from ('contactgroup ' )
355346                ->columns ('id ' )
356-                 ->where (['id IN (?) '  => $ groupIds 
347+                 ->where (['external_uuid = ? '  => $ identifier 
357348        );
358349
359-         if  (count ( $ existingGroupIds ) !==  count ( $ groupIds ) ) {
360-             throw  new  HttpException ( ' 404 ' ,  'Undefined group identifier given ' );
350+         if  ($ group  ===  false ) {
351+             throw  new  HttpNotFoundException ( 'Undefined group identifier given ' );
361352        }
353+ 
354+         return  $ groupid ;
362355    }
363356
364357    /** 
@@ -385,12 +378,16 @@ protected function getContactId(string $identifier): ?int
385378     * 
386379     * @param array $data 
387380     * 
388-      * @throws HttpException if a group or default_channel does not exist  
381+      * @return void  
389382     */ 
390383    private  function  addContact (array  $ datavoid 
391384    {
392385        $ dbget ();
393386
387+         if  (isset ($ data'username ' ])) {
388+             $ this assertUniqueUsername ($ data'username ' ]);
389+         }
390+ 
394391        $ dbinsert ('contact ' , [
395392            'full_name '              => $ data'full_name ' ],
396393            'username '               => $ data'username ' ] ?? null ,
@@ -401,31 +398,108 @@ private function addContact(array $data): void
401398        $ contactId$ dblastInsertId ();
402399
403400        if  (! empty ($ data'addresses ' ])) {
404-             foreach  ($ data'addresses ' ] as  $ type$ address
405-                 $ dbinsert ('contact_address ' , [
406-                     'contact_id '     => $ contactId
407-                     'type '           => $ type
408-                     'address '        => $ address
409-                 ]);
410-             }
401+             $ this addAddresses ($ contactId$ data'addresses ' ]);
411402        }
412403
413404        if  (! empty ($ data'groups ' ])) {
414-             $ this assertGroupsExist ($ data'groups ' ]);
415- 
416-             foreach  ($ data'groups ' ] as  $ groupId
417-                 $ dbinsert ('contactgroup_member ' , [
418-                     'contact_id '         => $ contactId
419-                     'contactgroup_id '    => $ groupId
420-                 ]);
421-             }
405+             $ this addGroups ($ contactId$ data'groups ' ]);
406+         }
407+     }
408+ 
409+     /** 
410+      * Assert that the username is unique 
411+      * 
412+      * @param string $username 
413+      * 
414+      * @return void 
415+      * 
416+      * @throws HttpBadRequestException if the username already exists 
417+      */ 
418+     private  function  assertUniqueUsername (string  $ usernamevoid 
419+     {
420+         $ userget ()->fetchOne (
421+             (new  Select ())
422+                 ->from ('contact ' )
423+                 ->columns (1 )
424+                 ->where (['username = ? '  => $ username
425+         );
426+ 
427+         if  ($ userfalse ) {
428+             $ this httpBadRequest ('Username already exists ' );
429+         }
430+     }
431+ 
432+     /** 
433+      * Assert that the address type exists 
434+      * 
435+      * @param array $addressTypes 
436+      * 
437+      * @return void 
438+      * 
439+      * @throws HttpBadRequestException if the username already exists 
440+      */ 
441+     private  function  assertAddressTypesExist (array  $ addressTypesvoid 
442+     {
443+         $ typesget ()->fetchCol (
444+             (new  Select ())
445+                 ->from ('available_channel_type ' )
446+                 ->columns (1 )
447+                 ->where (['type IN (?) '  => $ addressTypes
448+         );
449+ 
450+         if  (count ($ typescount ($ addressTypes
451+             $ this httpBadRequest ('An undefined address type given ' );
452+         }
453+     }
454+ 
455+     /** 
456+      * Add the groups to the given contact 
457+      * 
458+      * @param int $contactId 
459+      * @param array $groups 
460+      * 
461+      * @return void 
462+      */ 
463+     private  function  addGroups (int  $ contactIdarray  $ groupsvoid 
464+     {
465+         foreach  ($ groupsas  $ groupIdentifier
466+             $ groupId$ this getGroupId ($ groupIdentifier
467+ 
468+             Database::get ()->insert ('contactgroup_member ' , [
469+                 'contact_id '         => $ contactId
470+                 'contactgroup_id '    => $ groupId
471+             ]);
472+         }
473+     }
474+ 
475+     /** 
476+      * Add the addresses to the given contact 
477+      * 
478+      * @param int $contactId 
479+      * @param array $addresses 
480+      * 
481+      * @return void 
482+      */ 
483+     private  function  addAddresses (int  $ contactIdarray  $ addressesvoid 
484+     {
485+         $ this assertAddressTypesExist (array_keys ($ addresses
486+ 
487+         foreach  ($ addressesas  $ type$ address
488+             //TODO: Check if type exists, db allows any type 
489+             Database::get ()->insert ('contact_address ' , [
490+                 'contact_id '     => $ contactId
491+                 'type '           => $ type
492+                 'address '        => $ address
493+             ]);
422494        }
423495    }
424496
425497    /** 
426498     * Remove the contact with the given id 
427499     * 
428500     * @param int $id 
501+      * 
502+      * @return void 
429503     */ 
430504    private  function  removeContact (int  $ idvoid 
431505    {
@@ -441,6 +515,8 @@ private function removeContact(int $id): void
441515     * 
442516     * @param array $data 
443517     * 
518+      * @return void 
519+      * 
444520     * @throws HttpBadRequestException 
445521     */ 
446522    private  function  assertValidData (array  $ datavoid 
0 commit comments