6
6
7
7
use Icinga \Exception \Http \HttpBadRequestException ;
8
8
use Icinga \Exception \Http \HttpException ;
9
+ use Icinga \Exception \Http \HttpNotFoundException ;
9
10
use Icinga \Module \Notifications \Common \Database ;
10
11
use Icinga \Util \Environment ;
11
12
use Icinga \Util \Json ;
@@ -164,13 +165,12 @@ function (Filter\Condition $condition) {
164
165
$ db ->beginTransaction ();
165
166
166
167
if ($ identifier === null ) {
167
- $ identifier = $ data ['id ' ];
168
-
169
- if ($ this ->getContactId ($ identifier ) !== null ) {
168
+ if ($ this ->getContactId ($ data ['id ' ]) !== null ) {
170
169
throw new HttpException ('422 ' , 'Contact already exists ' );
171
170
}
172
171
173
172
$ this ->addContact ($ data );
173
+ $ identifier = $ data ['id ' ];
174
174
} else {
175
175
$ contactId = $ this ->getContactId ($ identifier );
176
176
if ($ contactId === null ) {
@@ -181,9 +181,10 @@ function (Filter\Condition $condition) {
181
181
throw new HttpException ('422 ' , 'Contact already exists ' );
182
182
}
183
183
184
- $ identifier = $ data ['id ' ];
185
184
$ this ->removeContact ($ contactId );
186
185
$ this ->addContact ($ data );
186
+
187
+ $ identifier = $ data ['id ' ];
187
188
}
188
189
189
190
$ db ->commitTransaction ();
@@ -219,24 +220,11 @@ function (Filter\Condition $condition) {
219
220
$ db ->delete ('contactgroup_member ' , ['contact_id = ? ' => $ contactId ]);
220
221
221
222
if (! empty ($ data ['addresses ' ])) {
222
- foreach ($ data ['addresses ' ] as $ type => $ address ) {
223
- $ db ->insert ('contact_address ' , [
224
- 'contact_id ' => $ contactId ,
225
- 'type ' => $ type ,
226
- 'address ' => $ address
227
- ]);
228
- }
223
+ $ this ->addAddresses ($ contactId , $ data ['addresses ' ]);
229
224
}
230
225
231
226
if (! empty ($ data ['groups ' ])) {
232
- $ this ->assertGroupsExist ($ data ['groups ' ]);
233
-
234
- foreach ($ data ['groups ' ] as $ group ) {
235
- $ db ->insert ('contactgroup_member ' , [
236
- 'contact_id ' => $ contactId ,
237
- 'contactgroup_id ' => $ group
238
- ]);
239
- }
227
+ $ this ->addGroups ($ contactId , $ data ['groups ' ]);
240
228
}
241
229
242
230
$ responseCode = 204 ;
@@ -282,7 +270,8 @@ function (Filter\Condition $condition) {
282
270
* @param string $channelName
283
271
*
284
272
* @return int
285
- * @throws HttpException if the channel does not exist
273
+ *
274
+ * @throws HttpNotFoundException if the channel does not exist
286
275
*/
287
276
private function getChannelId (string $ channelName ): int
288
277
{
@@ -294,7 +283,7 @@ private function getChannelId(string $channelName): int
294
283
);
295
284
296
285
if ($ channel === false ) {
297
- throw new HttpException ( ' 404 ' , 'Channel not found ' );
286
+ throw new HttpNotFoundException ( 'Channel not found ' );
298
287
}
299
288
300
289
return $ channel ->id ;
@@ -341,24 +330,28 @@ private function fetchGroupIdentifiers(int $contactId): ?array
341
330
}
342
331
343
332
/**
344
- * Assert that the given group IDs exist
333
+ * Get the group id with the given identifier
345
334
*
346
- * @param array $groupIds
335
+ * @param string $identifier
347
336
*
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
349
340
*/
350
- private function assertGroupsExist ( array $ groupIds ): void
341
+ private function getGroupId ( string $ identifier ): int
351
342
{
352
- $ existingGroupIds = Database::get ()->fetchCol (
343
+ $ group = Database::get ()->fetchOne (
353
344
(new Select ())
354
345
->from ('contactgroup ' )
355
346
->columns ('id ' )
356
- ->where (['id IN (?) ' => $ groupIds ])
347
+ ->where (['external_uuid = ? ' => $ identifier ])
357
348
);
358
349
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 ' );
361
352
}
353
+
354
+ return $ group ->id ;
362
355
}
363
356
364
357
/**
@@ -385,12 +378,16 @@ protected function getContactId(string $identifier): ?int
385
378
*
386
379
* @param array $data
387
380
*
388
- * @throws HttpException if a group or default_channel does not exist
381
+ * @return void
389
382
*/
390
383
private function addContact (array $ data ): void
391
384
{
392
385
$ db = Database::get ();
393
386
387
+ if (isset ($ data ['username ' ])) {
388
+ $ this ->assertUniqueUsername ($ data ['username ' ]);
389
+ }
390
+
394
391
$ db ->insert ('contact ' , [
395
392
'full_name ' => $ data ['full_name ' ],
396
393
'username ' => $ data ['username ' ] ?? null ,
@@ -401,31 +398,108 @@ private function addContact(array $data): void
401
398
$ contactId = $ db ->lastInsertId ();
402
399
403
400
if (! empty ($ data ['addresses ' ])) {
404
- foreach ($ data ['addresses ' ] as $ type => $ address ) {
405
- $ db ->insert ('contact_address ' , [
406
- 'contact_id ' => $ contactId ,
407
- 'type ' => $ type ,
408
- 'address ' => $ address
409
- ]);
410
- }
401
+ $ this ->addAddresses ($ contactId , $ data ['addresses ' ]);
411
402
}
412
403
413
404
if (! empty ($ data ['groups ' ])) {
414
- $ this ->assertGroupsExist ($ data ['groups ' ]);
415
-
416
- foreach ($ data ['groups ' ] as $ groupId ) {
417
- $ db ->insert ('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 $ username ): void
419
+ {
420
+ $ user = Database::get ()->fetchOne (
421
+ (new Select ())
422
+ ->from ('contact ' )
423
+ ->columns (1 )
424
+ ->where (['username = ? ' => $ username ])
425
+ );
426
+
427
+ if ($ user !== false ) {
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 $ addressTypes ): void
442
+ {
443
+ $ types = Database::get ()->fetchCol (
444
+ (new Select ())
445
+ ->from ('available_channel_type ' )
446
+ ->columns (1 )
447
+ ->where (['type IN (?) ' => $ addressTypes ])
448
+ );
449
+
450
+ if (count ($ types ) !== count ($ 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 $ contactId , array $ groups ): void
464
+ {
465
+ foreach ($ groups as $ 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 $ contactId , array $ addresses ): void
484
+ {
485
+ $ this ->assertAddressTypesExist (array_keys ($ addresses ));
486
+
487
+ foreach ($ addresses as $ 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
+ ]);
422
494
}
423
495
}
424
496
425
497
/**
426
498
* Remove the contact with the given id
427
499
*
428
500
* @param int $id
501
+ *
502
+ * @return void
429
503
*/
430
504
private function removeContact (int $ id ): void
431
505
{
@@ -441,6 +515,8 @@ private function removeContact(int $id): void
441
515
*
442
516
* @param array $data
443
517
*
518
+ * @return void
519
+ *
444
520
* @throws HttpBadRequestException
445
521
*/
446
522
private function assertValidData (array $ data ): void
0 commit comments