Skip to content

Commit

Permalink
Added search provider for listed conversations
Browse files Browse the repository at this point in the history
Signed-off-by: Vincent Petry <vincent@nextcloud.com>
  • Loading branch information
PVince81 committed Dec 10, 2020
1 parent 139264a commit ba01861
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 10 deletions.
2 changes: 2 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
use OCA\Talk\PublicShareAuth\TemplateLoader as PublicShareAuthTemplateLoader;
use OCA\Talk\Room;
use OCA\Talk\Search\ConversationSearch;
use OCA\Talk\Search\ListedConversationSearch;
use OCA\Talk\Search\CurrentMessageSearch;
use OCA\Talk\Search\MessageSearch;
use OCA\Talk\Search\UnifiedSearchCSSLoader;
Expand Down Expand Up @@ -98,6 +99,7 @@ public function register(IRegistrationContext $context): void {
$context->registerEventListener(\OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent::class, UnifiedSearchCSSLoader::class);

$context->registerSearchProvider(ConversationSearch::class);
$context->registerSearchProvider(ListedConversationSearch::class);
$context->registerSearchProvider(CurrentMessageSearch::class);
$context->registerSearchProvider(MessageSearch::class);

Expand Down
86 changes: 77 additions & 9 deletions lib/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
use OCP\IL10N;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IGroupManager;
use OCP\Security\IHasher;
use OCP\Security\ISecureRandom;

Expand All @@ -65,6 +66,8 @@ class Manager {
private $secureRandom;
/** @var IUserManager */
private $userManager;
/** @var IGroupManager */
private $groupManager;
/** @var ICommentsManager */
private $commentsManager;
/** @var TalkSession */
Expand All @@ -86,6 +89,7 @@ public function __construct(IDBConnection $db,
ParticipantService $participantService,
ISecureRandom $secureRandom,
IUserManager $userManager,
IGroupManager $groupManager,
CommentsManager $commentsManager,
TalkSession $talkSession,
IEventDispatcher $dispatcher,
Expand All @@ -100,6 +104,7 @@ public function __construct(IDBConnection $db,
$this->participantService = $participantService;
$this->secureRandom = $secureRandom;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->commentsManager = $commentsManager;
$this->talkSession = $talkSession;
$this->dispatcher = $dispatcher;
Expand Down Expand Up @@ -331,6 +336,54 @@ public function getRoomsForUser(string $userId, bool $includeLastMessage = false
return $rooms;
}

/**
* Returns rooms that are listable where the current user is not a participant.
*
* @param string $userId user id
* @param string $term search term
* @return Room[]
*/
public function getListedRoomsForUser(string $userId, string $term = ''): array {
$allowedRoomTypes = [Room::GROUP_CALL, Room::PUBLIC_CALL];
$allowedListedTypes = [Room::LISTABLE_ALL];
if (!$this->isGuestUser($userId)) {
$listedType[] = Room::LISTABLE_USERS;
}
$query = $this->db->getQueryBuilder();
$query->select('r.*')
->selectAlias('r.id', 'r_id')
->from('talk_rooms', 'r')
->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
$query->expr()->eq('a.actor_id', $query->createNamedParameter($userId)),
$query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_USERS)),
$query->expr()->eq('a.room_id', 'r.id')
))
->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX(
$query->expr()->eq('a.id', 's.attendee_id')
))
->where($query->expr()->isNull('a.id'))
->andWhere($query->expr()->in('r.type', $query->createNamedParameter($allowedRoomTypes, IQueryBuilder::PARAM_INT_ARRAY)))
->andWhere($query->expr()->in('r.type', $query->createNamedParameter($allowedListedTypes, IQueryBuilder::PARAM_INT_ARRAY)));

if ($term !== '') {
$query->andWhere(
$query->expr()->ilike('name', $query->createNamedParameter(
'%' . $this->db->escapeLikeParameter($term). '%'
))
);
}

$result = $query->execute();
$rooms = [];
while ($row = $result->fetch()) {
$room = $this->createRoomObject($row);
$rooms[] = $room;
}
$result->closeCursor();

return $rooms;
}

/**
* Does *not* return public rooms for participants that have not been invited
*
Expand Down Expand Up @@ -812,16 +865,19 @@ public function resolveRoomDisplayName(Room $room, string $userId): string {
return $otherParticipant;
}

try {
if ($userId === '') {
$sessionId = $this->talkSession->getSessionForRoom($room->getToken());
$room->getParticipantBySession($sessionId);
} else {
$room->getParticipant($userId);
// FIXME: also check guest user case
if ($room->getListable() === Room::LISTABLE_PARTICIPANTS) {
try {
if ($userId === '') {
$sessionId = $this->talkSession->getSessionForRoom($room->getToken());
$room->getParticipantBySession($sessionId);
} else {
$room->getParticipant($userId);
}
} catch (ParticipantNotFoundException $e) {
// Do not leak the name of rooms the user is not a part of
return $this->l->t('Private conversation');
}
} catch (ParticipantNotFoundException $e) {
// Do not leak the name of rooms the user is not a part of
return $this->l->t('Private conversation');
}

return $room->getName();
Expand Down Expand Up @@ -924,6 +980,18 @@ public function isValidParticipant(string $userId): bool {
return $this->userManager->userExists($userId);
}

/**
* Returns whether the given user id is a guest user from
* the guest app
*
* @param string $userId user id to check
* @return bool true if the user is a guest, false otherwise
*/
public function isGuestUser(string $userId): bool {
// FIXME: retrieve guest group name from app ?
return $this->groupManager->isInGroup($userId, 'guest_app');
}

protected function loadLastMessageInfo(IQueryBuilder $query): void {
$query->leftJoin('r','comments', 'c', $query->expr()->eq('r.last_message', 'c.id'));
$query->selectAlias('c.id', 'comment_id');
Expand Down
111 changes: 111 additions & 0 deletions lib/Search/ListedConversationSearch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?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\Search;

use OCA\Talk\AppInfo\Application;
use OCA\Talk\Manager;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\Search\IProvider;
use OCP\Search\ISearchQuery;
use OCP\Search\SearchResult;
use OCP\Search\SearchResultEntry;

class ListedConversationSearch implements IProvider {

/** @var Manager */
protected $manager;
/** @var IURLGenerator */
protected $url;
/** @var IL10N */
protected $l;

public function __construct(
Manager $manager,
IURLGenerator $url,
IL10N $l
) {
$this->manager = $manager;
$this->url = $url;
$this->l = $l;
}

/**
* @inheritDoc
*/
public function getId(): string {
return 'talk-listed-conversations';
}

/**
* @inheritDoc
*/
public function getName(): string {
return $this->l->t('Listed Conversations');
}

/**
* @inheritDoc
*/
public function getOrder(string $route, array $routeParameters): int {
if (strpos($route, Application::APP_ID . '.') === 0) {
// Active app, prefer Talk results
return -1;
}

return 25;
}

/**
* @inheritDoc
*/
public function search(IUser $user, ISearchQuery $query): SearchResult {
$rooms = $this->manager->getListedRoomsForUser($user->getUID(), $query->getTerm());

$result = [];
foreach ($rooms as $room) {
$iconClass = '';
if ($room->getObjectType() === 'share:password') {
$iconClass = 'conversation-icon icon-password';
} else {
$iconClass = 'conversation-icon icon-public';
}

$result[] = new SearchResultEntry(
'',
$room->getDisplayName($user->getUID()),
'',
$this->url->linkToRouteAbsolute('spreed.Page.showCall', ['token' => $room->getToken()]),
$iconClass,
true
);
}

return SearchResult::complete(
$this->l->t('Listed Conversations'),
$result
);
}
}
1 change: 1 addition & 0 deletions tests/php/Controller/SignalingControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,7 @@ public function testLeaveRoomWithOldSession() {
$participantService,
$this->secureRandom,
$this->createMock(IUserManager::class),
$this->createMock(IGroupManager::class),
$this->createMock(CommentsManager::class),
$this->createMock(TalkSession::class),
$dispatcher,
Expand Down
1 change: 1 addition & 0 deletions tests/php/Signaling/BackendNotifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ public function setUp(): void {
$this->participantService,
$this->secureRandom,
$this->createMock(IUserManager::class),
$groupManager,
$this->createMock(CommentsManager::class),
$this->createMock(TalkSession::class),
$this->dispatcher,
Expand Down
2 changes: 1 addition & 1 deletion tests/psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@
</UndefinedDocblockClass>
</file>
<file src="lib/Manager.php">
<InvalidArgument occurrences="8"/>
<InvalidArgument occurrences="10"/>
</file>
<file src="lib/MatterbridgeManager.php">
<UndefinedClass occurrences="3">
Expand Down

0 comments on commit ba01861

Please sign in to comment.