From 1b88cc94b25ee5ad195db11bd4ae6628a03fe540 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Tue, 11 Jun 2024 16:42:05 +0200 Subject: [PATCH] wip1 --- .../ApiV1ContactgroupsController.php | 64 ++++--- .../controllers/ApiV1ContactsController.php | 166 +++++++++++++----- 2 files changed, 158 insertions(+), 72 deletions(-) diff --git a/application/controllers/ApiV1ContactgroupsController.php b/application/controllers/ApiV1ContactgroupsController.php index 2971cb7e7..cecfba50b 100644 --- a/application/controllers/ApiV1ContactgroupsController.php +++ b/application/controllers/ApiV1ContactgroupsController.php @@ -6,6 +6,7 @@ use Icinga\Exception\Http\HttpBadRequestException; use Icinga\Exception\Http\HttpException; +use Icinga\Exception\Http\HttpNotFoundException; use Icinga\Module\Notifications\Common\Database; use Icinga\Util\Environment; use Icinga\Util\Json; @@ -142,13 +143,13 @@ function (Filter\Condition $condition) { $db->beginTransaction(); if ($identifier === null) { - $identifier = $data['id']; - - if ($this->getContactgroupId($identifier) !== null) { + if ($this->getContactgroupId($data['id']) !== null) { throw new HttpException('422', 'Contactgroup already exists'); } $this->addContactgroup($data); + + $identifier = $data['id']; } else { $contactgroupId = $this->getContactgroupId($identifier); if ($contactgroupId === null) { @@ -194,14 +195,7 @@ function (Filter\Condition $condition) { $db->delete('contactgroup_member', ['contactgroup_id = ?' => $identifier]); if (! empty($data['users'])) { - $this->assertUsersExist($data['users']); - - foreach ($data['users'] as $userId) { - $db->insert('contactgroup_member', [ - 'contactgroup_id' => $identifier, - 'contact_id' => $userId - ]); - } + $this->addUsers($contactgroupId, $data['users']); } $responseCode = 204; @@ -267,22 +261,26 @@ private function fetchUserIdentifiers(int $contactgroupId): ?array /** * Assert that the given user IDs exist * - * @param array $userIds + * @param string $identifier + * + * @return int * - * @throws HttpException if a group does not exist + * @throws HttpNotFoundException if the user with the given identifier does not exist */ - private function assertUsersExist(array $userIds): void + private function getUserId(string $identifier): int { - $existingUserIds = Database::get()->fetchCol( + $user = Database::get()->fetchOne( (new Select()) ->from('contact') ->columns('id') - ->where(['id IN (?)' => $userIds]) + ->where(['external_uuid = ?' => $identifier]) ); - if (count($existingUserIds) !== count($userIds)) { - throw new HttpException('404', 'Undefined user identifier given'); + if ($user === false) { + throw new HttpNotFoundException('Undefined user identifier given'); } + + return $user->id; } /** @@ -308,8 +306,6 @@ private function getContactgroupId(string $identifier): ?int * Add a new contactgroup with the given data * * @param array $data - * - * @throws HttpException if a user does not exist */ private function addContactgroup(array $data): void { @@ -322,13 +318,27 @@ private function addContactgroup(array $data): void $id = $db->lastInsertId(); if (! empty($data['users'])) { - $this->assertUsersExist($data['users']); - foreach ($data['users'] as $contactId) { - $db->insert('contactgroup_member', [ - 'contactgroup_id' => $id, - 'contact_id' => $contactId - ]); - } + $this->addUsers($id, $data['users']); + } + } + + /** + * Add the given users as contactgroup_member with the given id + * + * @param int $contactgroupId + * @param array $users + * + * @return void + */ + private function addUsers(int $contactgroupId, array $users): void + { + foreach ($users as $identifier) { + $contactId = $this->getUserId($identifier); + + Database::get()->insert('contactgroup_member', [ + 'contactgroup_id' => $contactgroupId, + 'contact_id' => $contactId + ]); } } diff --git a/application/controllers/ApiV1ContactsController.php b/application/controllers/ApiV1ContactsController.php index cfa40ff5d..3ad3a9581 100644 --- a/application/controllers/ApiV1ContactsController.php +++ b/application/controllers/ApiV1ContactsController.php @@ -6,6 +6,7 @@ use Icinga\Exception\Http\HttpBadRequestException; use Icinga\Exception\Http\HttpException; +use Icinga\Exception\Http\HttpNotFoundException; use Icinga\Module\Notifications\Common\Database; use Icinga\Util\Environment; use Icinga\Util\Json; @@ -164,13 +165,12 @@ function (Filter\Condition $condition) { $db->beginTransaction(); if ($identifier === null) { - $identifier = $data['id']; - - if ($this->getContactId($identifier) !== null) { + if ($this->getContactId($data['id']) !== null) { throw new HttpException('422', 'Contact already exists'); } $this->addContact($data); + $identifier = $data['id']; } else { $contactId = $this->getContactId($identifier); if ($contactId === null) { @@ -181,9 +181,10 @@ function (Filter\Condition $condition) { throw new HttpException('422', 'Contact already exists'); } - $identifier = $data['id']; $this->removeContact($contactId); $this->addContact($data); + + $identifier = $data['id']; } $db->commitTransaction(); @@ -219,24 +220,11 @@ function (Filter\Condition $condition) { $db->delete('contactgroup_member', ['contact_id = ?' => $contactId]); if (! empty($data['addresses'])) { - foreach ($data['addresses'] as $type => $address) { - $db->insert('contact_address', [ - 'contact_id' => $contactId, - 'type' => $type, - 'address' => $address - ]); - } + $this->addAddresses($contactId, $data['addresses']); } if (! empty($data['groups'])) { - $this->assertGroupsExist($data['groups']); - - foreach ($data['groups'] as $group) { - $db->insert('contactgroup_member', [ - 'contact_id' => $contactId, - 'contactgroup_id' => $group - ]); - } + $this->addGroups($contactId, $data['groups']); } $responseCode = 204; @@ -282,7 +270,8 @@ function (Filter\Condition $condition) { * @param string $channelName * * @return int - * @throws HttpException if the channel does not exist + * + * @throws HttpNotFoundException if the channel does not exist */ private function getChannelId(string $channelName): int { @@ -294,7 +283,7 @@ private function getChannelId(string $channelName): int ); if ($channel === false) { - throw new HttpException('404', 'Channel not found'); + throw new HttpNotFoundException('Channel not found'); } return $channel->id; @@ -341,24 +330,28 @@ private function fetchGroupIdentifiers(int $contactId): ?array } /** - * Assert that the given group IDs exist + * Get the group id with the given identifier * - * @param array $groupIds + * @param string $identifier * - * @throws HttpException 404 if a group does not exist + * @return int + * + * @throws HttpNotFoundException if the contactgroup with the given identifier does not exist */ - private function assertGroupsExist(array $groupIds): void + private function getGroupId(string $identifier): int { - $existingGroupIds = Database::get()->fetchCol( + $group = Database::get()->fetchOne( (new Select()) ->from('contactgroup') ->columns('id') - ->where(['id IN (?)' => $groupIds]) + ->where(['external_uuid = ?' => $identifier]) ); - if (count($existingGroupIds) !== count($groupIds)) { - throw new HttpException('404', 'Undefined group identifier given'); + if ($group === false) { + throw new HttpNotFoundException('Undefined group identifier given'); } + + return $group->id; } /** @@ -385,12 +378,16 @@ protected function getContactId(string $identifier): ?int * * @param array $data * - * @throws HttpException if a group or default_channel does not exist + * @return void */ private function addContact(array $data): void { $db = Database::get(); + if (isset($data['username'])) { + $this->assertUniqueUsername($data['username']); + } + $db->insert('contact', [ 'full_name' => $data['full_name'], 'username' => $data['username'] ?? null, @@ -401,24 +398,99 @@ private function addContact(array $data): void $contactId = $db->lastInsertId(); if (! empty($data['addresses'])) { - foreach ($data['addresses'] as $type => $address) { - $db->insert('contact_address', [ - 'contact_id' => $contactId, - 'type' => $type, - 'address' => $address - ]); - } + $this->addAddresses($contactId, $data['addresses']); } if (! empty($data['groups'])) { - $this->assertGroupsExist($data['groups']); - - foreach ($data['groups'] as $groupId) { - $db->insert('contactgroup_member', [ - 'contact_id' => $contactId, - 'contactgroup_id' => $groupId - ]); - } + $this->addGroups($contactId, $data['groups']); + } + } + + /** + * Assert that the username is unique + * + * @param string $username + * + * @return void + * + * @throws HttpBadRequestException if the username already exists + */ + private function assertUniqueUsername(string $username): void + { + $user = Database::get()->fetchOne( + (new Select()) + ->from('contact') + ->columns(1) + ->where(['username = ?' => $username]) + ); + + if ($user !== false) { + $this->httpBadRequest('Username already exists'); + } + } + + /** + * Assert that the address type exists + * + * @param array $addressTypes + * + * @return void + * + * @throws HttpBadRequestException if the username already exists + */ + private function assertAddressTypesExist(array $addressTypes): void + { + $types = Database::get()->fetchCol( + (new Select()) + ->from('available_channel_type') + ->columns(1) + ->where(['type IN (?)' => $addressTypes]) + ); + + if (count($types) !== count($addressTypes)) { + $this->httpBadRequest('An undefined address type given'); + } + } + + /** + * Add the groups to the given contact + * + * @param int $contactId + * @param array $groups + * + * @return void + */ + private function addGroups(int $contactId, array $groups): void + { + foreach ($groups as $groupIdentifier) { + $groupId = $this->getGroupId($groupIdentifier); + + Database::get()->insert('contactgroup_member', [ + 'contact_id' => $contactId, + 'contactgroup_id' => $groupId + ]); + } + } + + /** + * Add the addresses to the given contact + * + * @param int $contactId + * @param array $addresses + * + * @return void + */ + private function addAddresses(int $contactId, array $addresses): void + { + $this->assertAddressTypesExist(array_keys($addresses)); + + foreach ($addresses as $type => $address) { + //TODO: Check if type exists, db allows any type + Database::get()->insert('contact_address', [ + 'contact_id' => $contactId, + 'type' => $type, + 'address' => $address + ]); } } @@ -426,6 +498,8 @@ private function addContact(array $data): void * Remove the contact with the given id * * @param int $id + * + * @return void */ private function removeContact(int $id): void { @@ -441,6 +515,8 @@ private function removeContact(int $id): void * * @param array $data * + * @return void + * * @throws HttpBadRequestException */ private function assertValidData(array $data): void