diff options
author | Vincent Petry <vincent@nextcloud.com> | 2020-12-01 13:56:54 +0300 |
---|---|---|
committer | Vincent Petry <vincent@nextcloud.com> | 2020-12-11 20:15:47 +0300 |
commit | 17971cd34a6ecb0cdf4e926e41414f13a2bd4c41 (patch) | |
tree | abb522f422fd26ff1654eabdaacfe54ed5d09a94 /lib | |
parent | be0ed4a7f5f3b7eaa8acef96258862929dfd729f (diff) |
Add listable flags attribute for conversations
Added ability to set a conversation as listable for regular users and/or
guest users from the guest app.
This only implements the flag, endpoint and UI to manage it but not yet
making it appear in search results.
Signed-off-by: Vincent Petry <vincent@nextcloud.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Capabilities.php | 1 | ||||
-rw-r--r-- | lib/Chat/Parser/SystemMessage.php | 21 | ||||
-rw-r--r-- | lib/Chat/SystemMessage/Listener.php | 18 | ||||
-rw-r--r-- | lib/Command/Room/Create.php | 17 | ||||
-rw-r--r-- | lib/Command/Room/TRoomCommand.php | 16 | ||||
-rw-r--r-- | lib/Command/Room/Update.php | 17 | ||||
-rw-r--r-- | lib/Controller/RoomController.php | 17 | ||||
-rw-r--r-- | lib/Manager.php | 2 | ||||
-rw-r--r-- | lib/Migration/Version2100Date20201201102528.php | 60 | ||||
-rw-r--r-- | lib/Room.php | 62 | ||||
-rw-r--r-- | lib/Signaling/Listener.php | 1 |
11 files changed, 232 insertions, 0 deletions
diff --git a/lib/Capabilities.php b/lib/Capabilities.php index 8dd4cca51..a95bc5531 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -74,6 +74,7 @@ class Capabilities implements IPublicCapability { 'invite-groups-and-mails', 'locked-one-to-one-rooms', 'read-only-rooms', + 'listable-rooms', 'chat-read-marker', 'webinary-lobby', 'start-call-flag', diff --git a/lib/Chat/Parser/SystemMessage.php b/lib/Chat/Parser/SystemMessage.php index b840dd8d2..48e9fa1f6 100644 --- a/lib/Chat/Parser/SystemMessage.php +++ b/lib/Chat/Parser/SystemMessage.php @@ -165,6 +165,27 @@ class SystemMessage { } elseif ($cliIsActor) { $parsedMessage = $this->l->t('An administrator locked the conversation'); } + } elseif ($message === 'listable_participants') { + $parsedMessage = $this->l->t('{actor} made the conversation listable for participants only'); + if ($currentUserIsActor) { + $parsedMessage = $this->l->t('You made the conversation listable for participants only'); + } elseif ($cliIsActor) { + $parsedMessage = $this->l->t('An administrator made the conversation listable for participants only'); + } + } elseif ($message === 'listable_users') { + $parsedMessage = $this->l->t('{actor} made the conversation listable for users only'); + if ($currentUserIsActor) { + $parsedMessage = $this->l->t('You made the conversation listable for users only'); + } elseif ($cliIsActor) { + $parsedMessage = $this->l->t('An administrator made the conversation listable for users only'); + } + } elseif ($message === 'listable_all') { + $parsedMessage = $this->l->t('{actor} made the conversation listable for everyone'); + if ($currentUserIsActor) { + $parsedMessage = $this->l->t('You made the conversation listable for everyone'); + } elseif ($cliIsActor) { + $parsedMessage = $this->l->t('An administrator made the conversation listable for everyone'); + } } elseif ($message === 'lobby_timer_reached') { $parsedMessage = $this->l->t('The conversation is now open to everyone'); } elseif ($message === 'lobby_none') { diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php index 6c019b90a..3672aa25e 100644 --- a/lib/Chat/SystemMessage/Listener.php +++ b/lib/Chat/SystemMessage/Listener.php @@ -176,6 +176,24 @@ class Listener { $listener->sendSystemMessage($room, 'read_only_off'); } }); + $dispatcher->addListener(Room::EVENT_AFTER_LISTABLE_SET, static function (ModifyRoomEvent $event) { + $room = $event->getRoom(); + + if ($room->getType() === Room::CHANGELOG_CONVERSATION) { + return; + } + + /** @var self $listener */ + $listener = \OC::$server->query(self::class); + + if ($event->getNewValue() === Room::LISTABLE_PARTICIPANTS) { + $listener->sendSystemMessage($room, 'listable_participants'); + } elseif ($event->getNewValue() === Room::LISTABLE_USERS) { + $listener->sendSystemMessage($room, 'listable_users'); + } elseif ($event->getNewValue() === Room::LISTABLE_ALL) { + $listener->sendSystemMessage($room, 'listable_all'); + } + }); $dispatcher->addListener(Room::EVENT_AFTER_LOBBY_STATE_SET, static function (ModifyLobbyEvent $event) { if ($event->getNewValue() === $event->getOldValue()) { return; diff --git a/lib/Command/Room/Create.php b/lib/Command/Room/Create.php index 7d595cb2f..eaaae0396 100644 --- a/lib/Command/Room/Create.php +++ b/lib/Command/Room/Create.php @@ -71,6 +71,11 @@ class Create extends Base { InputOption::VALUE_NONE, 'Creates the room with read-only access only if set' )->addOption( + 'listable', + null, + InputOption::VALUE_NONE, + 'Creates the room with the given listable scope' + )->addOption( 'password', null, InputOption::VALUE_REQUIRED, @@ -95,10 +100,21 @@ class Create extends Base { $groups = $input->getOption('group'); $public = $input->getOption('public'); $readonly = $input->getOption('readonly'); + $listable = $input->getOption('listable'); $password = $input->getOption('password'); $owner = $input->getOption('owner'); $moderators = $input->getOption('moderator'); + if (!in_array($readOnly, [null, '0', '1'], true)) { + $output->writeln('<error>Invalid value for option "--readonly" given.</error>'); + return 1; + } + + if (!in_array($listable, [null, '0', '1', '2', '3'], true)) { + $output->writeln('<error>Invalid value for option "--listable" given.</error>'); + return 1; + } + $roomType = $public ? Room::PUBLIC_CALL : Room::GROUP_CALL; try { $room = $this->roomService->createConversation($roomType, $name); @@ -116,6 +132,7 @@ class Create extends Base { } $this->setRoomReadOnly($room, $readonly); + $this->setListable($room, $listable); if ($password !== null) { $this->setRoomPassword($room, $password); diff --git a/lib/Command/Room/TRoomCommand.php b/lib/Command/Room/TRoomCommand.php index f29862320..68c3d238c 100644 --- a/lib/Command/Room/TRoomCommand.php +++ b/lib/Command/Room/TRoomCommand.php @@ -152,6 +152,22 @@ trait TRoomCommand { } /** + * @param Room $room + * @param int $listable + * + * @throws InvalidArgumentException + */ + protected function setRoomListable(Room $room, int $listable): void { + if ($room->getListable() === $listable) { + return; + } + + if (!$room->setListable($listable)) { + throw new InvalidArgumentException('Unable to change room state.'); + } + } + + /** * @param Room $room * @param string $password * diff --git a/lib/Command/Room/Update.php b/lib/Command/Room/Update.php index 76480a116..af87053e5 100644 --- a/lib/Command/Room/Update.php +++ b/lib/Command/Room/Update.php @@ -67,6 +67,11 @@ class Update extends Base { InputOption::VALUE_REQUIRED, 'Modifies the room to be read-only (value 1) or read-write (value 0)' )->addOption( + 'listable', + null, + InputOption::VALUE_NONE, + 'Modifies the room\'s listable scope' + )->addOption( 'password', null, InputOption::VALUE_REQUIRED, @@ -85,6 +90,7 @@ class Update extends Base { $description = $input->getOption('description'); $public = $input->getOption('public'); $readOnly = $input->getOption('readonly'); + $listable = $input->getOption('listable'); $password = $input->getOption('password'); $owner = $input->getOption('owner'); @@ -98,6 +104,11 @@ class Update extends Base { return 1; } + if (!in_array($listable, [null, '0', '1', '2', '3'], true)) { + $output->writeln('<error>Invalid value for option "--listable" given.</error>'); + return 1; + } + try { $room = $this->manager->getRoomByToken($token); } catch (RoomNotFoundException $e) { @@ -127,6 +138,10 @@ class Update extends Base { $this->setRoomReadOnly($room, ($readOnly === '1')); } + if ($listable !== null) { + $this->setRoomListable($room, (int)$listable); + } + if ($password !== null) { $this->setRoomPassword($room, $password); } @@ -152,6 +167,8 @@ class Update extends Base { case 'public': case 'readonly': return ['1', '0']; + case 'listable': + return ['2', '1', '0']; case 'owner': return $this->completeParticipantValues($context); diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 06d7e6334..c05c98bdd 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -531,6 +531,7 @@ class RoomController extends AEnvironmentAwareController { 'participantType' => Participant::GUEST, 'participantFlags' => Participant::FLAG_DISCONNECTED, 'readOnly' => Room::READ_WRITE, + 'listable' => $room->getListable(), 'hasPassword' => $room->hasPassword(), 'hasCall' => false, 'canStartCall' => false, @@ -605,6 +606,7 @@ class RoomController extends AEnvironmentAwareController { 'objectId' => $room->getObjectId(), 'participantType' => $attendee->getParticipantType(), 'readOnly' => $room->getReadOnly(), + 'listable' => $room->getListable(), 'hasCall' => $room->getActiveSince() instanceof \DateTimeInterface, 'lastActivity' => $lastActivity, 'isFavorite' => $attendee->isFavorite(), @@ -1470,6 +1472,21 @@ class RoomController extends AEnvironmentAwareController { } /** + * @NoAdminRequired + * @RequireModeratorParticipant + * + * @param int $state + * @return DataResponse + */ + public function setListable(int $scope): DataResponse { + if (!$this->room->setListable($scope)) { + return new DataResponse([], Http::STATUS_BAD_REQUEST); + } + + return new DataResponse(); + } + + /** * @PublicPage * @RequireModeratorParticipant * diff --git a/lib/Manager.php b/lib/Manager.php index f5ea5ccd6..62389cda3 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -167,6 +167,7 @@ class Manager { (int) $row['r_id'], (int) $row['type'], (int) $row['read_only'], + (int) $row['listable'], (int) $row['lobby_state'], (int) $row['sip_enabled'], $assignedSignalingServer, @@ -704,6 +705,7 @@ class Manager { if ($row === false) { $room = $this->createRoom(Room::CHANGELOG_CONVERSATION, $userId); $room->setReadOnly(Room::READ_ONLY); + $room->setListable(Room::LISTABLE_PARTICIPANTS); $this->participantService->addUsers($room,[[ 'actorType' => Attendee::ACTOR_USERS, diff --git a/lib/Migration/Version2100Date20201201102528.php b/lib/Migration/Version2100Date20201201102528.php new file mode 100644 index 000000000..b59fcb5d1 --- /dev/null +++ b/lib/Migration/Version2100Date20201201102528.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020, Vincent Petry <vincent@nextcloud.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Talk\Migration; + +use Closure; +use Doctrine\DBAL\Types\Type; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +/** + * Add listable column to the rooms table. + */ +class Version2100Date20201201102528 extends SimpleMigrationStep { + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + if ($schema->hasTable('talk_rooms')) { + $table = $schema->getTable('talk_rooms'); + + if (!$table->hasColumn('listable')) { + $table->addColumn('listable', Type::INTEGER, [ + 'notnull' => true, + 'length' => 6, + 'default' => 0, + ]); + } + } + + return $schema; + } +} diff --git a/lib/Room.php b/lib/Room.php index 8f9ed2278..7a3cf2885 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -62,6 +62,21 @@ class Room { public const READ_WRITE = 0; public const READ_ONLY = 1; + /** + * Only visible when joined + */ + public const LISTABLE_PARTICIPANTS = 0; + + /** + * Searchable by all regular users and moderators, even when not joined, excluding guest users + */ + public const LISTABLE_USERS = 1; + + /** + * Searchable by everyone, which includes guest users (from guest app), even when not joined + */ + public const LISTABLE_ALL = 2; + public const START_CALL_EVERYONE = 0; public const START_CALL_USERS = 1; public const START_CALL_MODERATORS = 2; @@ -82,6 +97,8 @@ class Room { public const EVENT_AFTER_TYPE_SET = self::class . '::postSetType'; public const EVENT_BEFORE_READONLY_SET = self::class . '::preSetReadOnly'; public const EVENT_AFTER_READONLY_SET = self::class . '::postSetReadOnly'; + public const EVENT_BEFORE_LISTABLE_SET = self::class . '::preSetListable'; + public const EVENT_AFTER_LISTABLE_SET = self::class . '::postSetListable'; public const EVENT_BEFORE_LOBBY_STATE_SET = self::class . '::preSetLobbyState'; public const EVENT_AFTER_LOBBY_STATE_SET = self::class . '::postSetLobbyState'; public const EVENT_BEFORE_SIP_ENABLED_SET = self::class . '::preSetSIPEnabled'; @@ -131,6 +148,8 @@ class Room { /** @var int */ private $readOnly; /** @var int */ + private $listable; + /** @var int */ private $lobbyState; /** @var int */ private $sipEnabled; @@ -175,6 +194,7 @@ class Room { int $id, int $type, int $readOnly, + int $listable, int $lobbyState, int $sipEnabled, ?int $assignedSignalingServer, @@ -199,6 +219,7 @@ class Room { $this->id = $id; $this->type = $type; $this->readOnly = $readOnly; + $this->listable = $listable; $this->lobbyState = $lobbyState; $this->sipEnabled = $sipEnabled; $this->assignedSignalingServer = $assignedSignalingServer; @@ -228,6 +249,10 @@ class Room { return $this->readOnly; } + public function getListable(): int { + return $this->listable; + } + public function getLobbyState(): int { $this->validateTimer(); return $this->lobbyState; @@ -346,6 +371,7 @@ class Room { 'lobby-state' => $this->getLobbyState(), 'lobby-timer' => $this->getLobbyTimer(), 'read-only' => $this->getReadOnly(), + 'listable' => $this->getListable(), 'active-since' => $this->getActiveSince(), 'sip-enabled' => $this->getSIPEnabled(), ]; @@ -781,6 +807,42 @@ class Room { } /** + * @param int $newState New listable scope from self::LISTABLE_* + * Also it's only allowed on rooms of type + * `self::GROUP_CALL` and `self::PUBLIC_CALL` + * @return bool True when the change was valid, false otherwise + */ + public function setListable(int $newState): bool { + $oldState = $this->getListable(); + if ($newState === $oldState) { + return true; + } + + if (!in_array($this->getType(), [self::GROUP_CALL, self::PUBLIC_CALL, self::CHANGELOG_CONVERSATION], true)) { + return false; + } + + if ($newState < 0 || $newState > 3) { + return false; + } + + $event = new ModifyRoomEvent($this, 'listable', $newState, $oldState); + $this->dispatcher->dispatch(self::EVENT_BEFORE_LISTABLE_SET, $event); + + $query = $this->db->getQueryBuilder(); + $query->update('talk_rooms') + ->set('listable', $query->createNamedParameter($newState, IQueryBuilder::PARAM_INT)) + ->where($query->expr()->eq('id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT))); + $query->execute(); + + $this->listable = $newState; + + $this->dispatcher->dispatch(self::EVENT_AFTER_LISTABLE_SET, $event); + + return true; + } + + /** * @param int $newState Currently it is only allowed to change between * `Webinary::LOBBY_NON_MODERATORS` and `Webinary::LOBBY_NONE` * Also it's not allowed in one-to-one conversations, diff --git a/lib/Signaling/Listener.php b/lib/Signaling/Listener.php index f62d32005..d5625d167 100644 --- a/lib/Signaling/Listener.php +++ b/lib/Signaling/Listener.php @@ -140,6 +140,7 @@ class Listener { $dispatcher->addListener(Room::EVENT_AFTER_PASSWORD_SET, $listener); $dispatcher->addListener(Room::EVENT_AFTER_TYPE_SET, $listener); $dispatcher->addListener(Room::EVENT_AFTER_READONLY_SET, $listener); + $dispatcher->addListener(Room::EVENT_AFTER_LISTABLE_SET, $listener); $dispatcher->addListener(Room::EVENT_AFTER_LOBBY_STATE_SET, $listener); $dispatcher->addListener(Room::EVENT_AFTER_SIP_ENABLED_SET, $listener); // TODO remove handler with "roomModified" in favour of handler with |