diff options
author | Joas Schilling <coding@schilljs.com> | 2022-06-10 17:14:43 +0300 |
---|---|---|
committer | Joas Schilling <coding@schilljs.com> | 2022-06-29 11:36:07 +0300 |
commit | 52cc89975c88a1f1e3ea2af8b4ca2b165df0b6bb (patch) | |
tree | 30667f96f30a43b47a4872796052214f2e3f5225 | |
parent | 2c3d71673b3ebccc9cbf008a0b86015442b4257c (diff) |
Implement password policy checker
Signed-off-by: Joas Schilling <coding@schilljs.com>
-rw-r--r-- | docs/conversation.md | 6 | ||||
-rw-r--r-- | lib/Command/Room/TRoomCommand.php | 9 | ||||
-rw-r--r-- | lib/Controller/RoomController.php | 10 | ||||
-rw-r--r-- | lib/Room.php | 30 | ||||
-rw-r--r-- | lib/Service/RoomService.php | 33 | ||||
-rw-r--r-- | src/components/ConversationSettings/LinkShareSettings.vue | 10 | ||||
-rw-r--r-- | tests/php/Signaling/BackendNotifierTest.php | 2 |
7 files changed, 67 insertions, 33 deletions
diff --git a/docs/conversation.md b/docs/conversation.md index 4956578e2..54a6b7ed6 100644 --- a/docs/conversation.md +++ b/docs/conversation.md @@ -247,10 +247,16 @@ * Response: - Status code: + `200 OK` + + `400 Bad Request` When the password does not match the password policy. Show `ocs.data.message` to the user in this case + `403 Forbidden` When the current user is not a moderator or owner + `403 Forbidden` When the conversation is not a public conversation + `404 Not Found` When the conversation could not be found for the participant + - Data: + field | type | Description + ---|---|--- + `message` | string | Only available on `400 Bad Request`, translated error with the violated password policy rules + ## Set default or call permissions for a conversation * Method: `PUT` diff --git a/lib/Command/Room/TRoomCommand.php b/lib/Command/Room/TRoomCommand.php index 280f96b8d..157682cf0 100644 --- a/lib/Command/Room/TRoomCommand.php +++ b/lib/Command/Room/TRoomCommand.php @@ -35,6 +35,7 @@ use OCA\Talk\Participant; use OCA\Talk\Room; use OCA\Talk\Service\ParticipantService; use OCA\Talk\Service\RoomService; +use OCP\HintException; use OCP\IGroup; use OCP\IGroupManager; use OCP\IUser; @@ -183,8 +184,12 @@ trait TRoomCommand { throw new InvalidArgumentException('Unable to add password protection to private room.'); } - if (!$room->setPassword($password)) { - throw new InvalidArgumentException('Unable to change room password.'); + try { + if (!$this->roomService->setPassword($room, $password)) { + throw new InvalidArgumentException('Unable to change room password.'); + } + } catch (HintException $e) { + throw new InvalidArgumentException($e->getHint()); } } diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 3d5e542ed..40c457de3 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -56,6 +56,7 @@ use OCP\AppFramework\Utility\ITimeFactory; use OCP\Comments\IComment; use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\ICloudIdManager; +use OCP\HintException; use OCP\IConfig; use OCP\IGroup; use OCP\IGroupManager; @@ -1315,7 +1316,14 @@ class RoomController extends AEnvironmentAwareController { return new DataResponse([], Http::STATUS_FORBIDDEN); } - $this->room->setPassword($password); + try { + $this->roomService->setPassword($this->room, $password); + } catch (HintException $e) { + return new DataResponse([ + 'message' => $e->getHint(), + ], Http::STATUS_BAD_REQUEST); + } + return new DataResponse(); } diff --git a/lib/Room.php b/lib/Room.php index a965dda8c..e022c938f 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -426,6 +426,10 @@ class Room { return $this->password; } + public function setPassword(string $password): void { + $this->password = $password; + } + public function getRemoteServer(): string { return $this->remoteServer; } @@ -693,32 +697,6 @@ class Room { } /** - * @param string $password Currently it is only allowed to have a password for Room::TYPE_PUBLIC - * @return bool True when the change was valid, false otherwise - */ - public function setPassword(string $password): bool { - if ($this->getType() !== self::TYPE_PUBLIC) { - return false; - } - - $hash = $password !== '' ? $this->hasher->hash($password) : ''; - - $event = new ModifyRoomEvent($this, 'password', $password); - $this->dispatcher->dispatch(self::EVENT_BEFORE_PASSWORD_SET, $event); - - $update = $this->db->getQueryBuilder(); - $update->update('talk_rooms') - ->set('password', $update->createNamedParameter($hash)) - ->where($update->expr()->eq('id', $update->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT))); - $update->executeStatement(); - $this->password = $hash; - - $this->dispatcher->dispatch(self::EVENT_AFTER_PASSWORD_SET, $event); - - return true; - } - - /** * @param \DateTime $now * @return bool */ diff --git a/lib/Service/RoomService.php b/lib/Service/RoomService.php index ca5f8cb8a..984317d0e 100644 --- a/lib/Service/RoomService.php +++ b/lib/Service/RoomService.php @@ -35,8 +35,10 @@ use OCA\Talk\Room; use OCA\Talk\Webinary; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; +use OCP\HintException; use OCP\IDBConnection; use OCP\IUser; +use OCP\Security\Events\ValidatePasswordPolicyEvent; use OCP\Security\IHasher; use OCP\Share\IManager as IShareManager; @@ -473,6 +475,37 @@ class RoomService { return true; } + /** + * @param string $password Currently it is only allowed to have a password for Room::TYPE_PUBLIC + * @return bool True when the change was valid, false otherwise + * @throws HintException + */ + public function setPassword(Room $room, string $password): bool { + if ($room->getType() !== Room::TYPE_PUBLIC) { + return false; + } + + $event = new ValidatePasswordPolicyEvent($password); + $this->dispatcher->dispatchTyped($event); + + $hash = $password !== '' ? $this->hasher->hash($password) : ''; + + $event = new ModifyRoomEvent($room, 'password', $password); + $this->dispatcher->dispatch(Room::EVENT_BEFORE_PASSWORD_SET, $event); + + $update = $this->db->getQueryBuilder(); + $update->update('talk_rooms') + ->set('password', $update->createNamedParameter($hash)) + ->where($update->expr()->eq('id', $update->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))); + $update->executeStatement(); + + $room->setPassword($hash); + + $this->dispatcher->dispatch(Room::EVENT_AFTER_PASSWORD_SET, $event); + + return true; + } + public function verifyPassword(Room $room, string $password): array { $event = new VerifyRoomPasswordEvent($room, $password); $this->dispatcher->dispatch(Room::EVENT_PASSWORD_VERIFY, $event); diff --git a/src/components/ConversationSettings/LinkShareSettings.vue b/src/components/ConversationSettings/LinkShareSettings.vue index 8b53cb0d6..14706ed41 100644 --- a/src/components/ConversationSettings/LinkShareSettings.vue +++ b/src/components/ConversationSettings/LinkShareSettings.vue @@ -163,9 +163,13 @@ export default { } else { showSuccess(t('spreed', 'Conversation password has been removed')) } - } catch (e) { - console.error('Error saving conversation password', e) - showError(t('spreed', 'Error occurred while saving conversation password')) + } catch (error) { + console.error('Error saving conversation password', error) + if (error?.response?.data?.ocs?.data?.message) { + showError(error.response.data.ocs.data.message) + } else { + showError(t('spreed', 'Error occurred while saving conversation password')) + } } this.isSaving = false }, diff --git a/tests/php/Signaling/BackendNotifierTest.php b/tests/php/Signaling/BackendNotifierTest.php index 7ba8c4e48..051188a53 100644 --- a/tests/php/Signaling/BackendNotifierTest.php +++ b/tests/php/Signaling/BackendNotifierTest.php @@ -462,7 +462,7 @@ class BackendNotifierTest extends TestCase { public function testRoomPasswordChanged() { $room = $this->manager->createRoom(Room::TYPE_PUBLIC); - $room->setPassword('password'); + $this->roomService->setPassword($room, 'password'); $this->assertMessageWasSent($room, [ 'type' => 'update', |