Skip to content

Commit

Permalink
Set share owner properly
Browse files Browse the repository at this point in the history
Signed-off-by: Gary Kim <[email protected]>
  • Loading branch information
gary-kim committed Aug 25, 2021
1 parent bc611f6 commit 4987824
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 20 deletions.
2 changes: 2 additions & 0 deletions lib/BackgroundJob/RetryJob.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @copyright Copyright (c) 2021 Gary Kim <[email protected]>
Expand Down
2 changes: 1 addition & 1 deletion lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1096,7 +1096,7 @@ public function addParticipantToRoom(string $newParticipant, string $source = 'u

$participantsToAdd[] = [
'actorType' => Attendee::ACTOR_FEDERATED_USERS,
'actorId' => $newUser->getId() . '@' . $newUser->getRemote(),
'actorId' => $newUser->getId(),
'displayName' => $newUser->getDisplayId(),
];
} else {
Expand Down
28 changes: 28 additions & 0 deletions lib/Exceptions/RoomHasNoModeratorException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2021 Gary Kim <[email protected]>
*
* @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\Exceptions;

class RoomHasNoModeratorException extends \Exception {
}
67 changes: 59 additions & 8 deletions lib/Federation/Notifications.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,18 @@
use OCA\FederatedFileSharing\AddressHandler;
use OCA\Talk\AppInfo\Application;
use OCA\Talk\BackgroundJob\RetryJob;
use OCA\Talk\Exceptions\RoomHasNoModeratorException;
use OCA\Talk\MatterbridgeManager;
use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\AttendeeMapper;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCP\BackgroundJob\IJobList;
use OCP\Federation\ICloudFederationFactory;
use OCP\Federation\ICloudFederationNotification;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\IUser;
use OCP\IUserManager;
use Psr\Log\LoggerInterface;

class Notifications {
Expand All @@ -50,41 +58,84 @@ class Notifications {
/** @var IJobList */
private $jobList;

/** @var IUserManager */
private $userManager;

/** @var AttendeeMapper */
private $attendeeMapper;

/** @var MatterbridgeManager */
private $matterbridgeManager;

public function __construct(
ICloudFederationFactory $cloudFederationFactory,
AddressHandler $addressHandler,
LoggerInterface $logger,
ICloudFederationProviderManager $federationProviderManager,
IJobList $jobList
IJobList $jobList,
IUserManager $userManager,
AttendeeMapper $attendeeMapper,
MatterbridgeManager $matterbridgeManager
) {
$this->cloudFederationFactory = $cloudFederationFactory;
$this->addressHandler = $addressHandler;
$this->logger = $logger;
$this->federationProviderManager = $federationProviderManager;
$this->jobList = $jobList;
$this->userManager = $userManager;
$this->attendeeMapper = $attendeeMapper;
$this->matterbridgeManager = $matterbridgeManager;
}

public function sendRemoteShare(string $providerId, string $token, string $shareWith, string $name, string $owner, string $ownerFederatedId,
string $sharedBy, string $sharedByFederatedId, string $shareType, string $roomName, string $roomType): bool {
/**
* @throws \OCP\HintException
* @throws RoomHasNoModeratorException
* @throws \OCP\DB\Exception
*/
public function sendRemoteShare(string $providerId, string $token, string $shareWith, string $sharedBy,
string $sharedByFederatedId, string $shareType, Room $room): bool {
[$user, $remote] = $this->addressHandler->splitUserRemote($shareWith);

$roomName = $room->getName();
$roomType = $room->getType();
$roomToken = $room->getToken();

if (!($user && $remote)) {
$this->logger->info(
"could not share $name, invalid contact $shareWith",
"could not share $roomToken, invalid contact $shareWith",
['app' => Application::APP_ID]
);
return false;
}

/** @var IUser|null $roomOwner */
$roomOwner = null;
try {
$roomOwners = $this->attendeeMapper->getActorsByParticipantTypes($room->getId(), [Participant::OWNER]);
if (!empty($roomOwners) && $roomOwners[0]->getActorType() === Attendee::ACTOR_USERS) {
$roomOwner = $this->userManager->get($roomOwners[0]->getActorId());
}
} catch (\Exception $e) {
// Get a local moderator instead
try {
$roomOwners = $this->attendeeMapper->getActorsByParticipantTypes($room->getId(), [Participant::MODERATOR]);
if (!empty($roomOwners) && $roomOwners[0]->getActorType() === Attendee::ACTOR_USERS) {
$roomOwner = $this->userManager->get($roomOwners[0]->getActorId());
}
} catch (\Exception $e) {
throw new RoomHasNoModeratorException();
}
}

$remote = $this->prepareRemoteUrl($remote);

$share = $this->cloudFederationFactory->getCloudFederationShare(
$user . '@' . $remote,
$name,
$roomToken,
'',
$providerId,
$ownerFederatedId,
$owner,
$roomOwner->getCloudId(),
$roomOwner->getDisplayName(),
$sharedByFederatedId,
$sharedBy,
$token,
Expand All @@ -104,7 +155,7 @@ public function sendRemoteShare(string $providerId, string $token, string $share
return true;
}
$this->logger->info(
"failed sharing $name with $shareWith",
"failed sharing $roomToken with $shareWith",
['app' => Application::APP_ID]
);

Expand Down
25 changes: 22 additions & 3 deletions lib/Model/AttendeeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public function getById(int $id): Attendee {
$query = $this->db->getQueryBuilder();
$query->select('*')
->from($this->getTableName())
->where($query->expr()->eq('id', $query->createNamedParameter($id)));
->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));

return $this->findEntity($query);
}
Expand All @@ -90,8 +90,8 @@ public function getByRemoteIdAndToken(int $id, string $token): Attendee {
$query = $this->db->getQueryBuilder();
$query->select('*')
->from($this->getTableName())
->where($query->expr()->eq('id', $query->createNamedParameter($id)))
->andWhere($query->expr()->eq('access_token', $query->createNamedParameter($token)));
->where($query->expr()->eq('remote_id', $query->createNamedParameter($id, IQueryBuilder::PARAM_STR)))
->andWhere($query->expr()->eq('access_token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR)));

return $this->findEntity($query);
}
Expand All @@ -116,6 +116,25 @@ public function getActorsByType(int $roomId, string $actorType, ?int $lastJoined
return $this->findEntities($query);
}

/**
* @param int $roomId
* @param array $participantType
* @return Attendee[]
* @throws DBException
*/
public function getActorsByParticipantTypes(int $roomId, array $participantType): array {
$query = $this->db->getQueryBuilder();
$query->select('*')
->from($this->getTableName())
->where($query->expr()->eq('room_id', $query->createNamedParameter($roomId, IQueryBuilder::PARAM_INT)));

if (!empty($participantType)) {
$query->andWhere($query->expr()->in('participant_type', $query->createNamedParameter($participantType, IQueryBuilder::PARAM_INT_ARRAY)));
}

return $this->findEntities($query);
}

/**
* @param int $roomId
* @param string $actorType
Expand Down
4 changes: 2 additions & 2 deletions lib/Service/ParticipantService.php
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ public function joinRoomAsNewGuest(Room $room, string $password, bool $passedPas
/**
* @param Room $room
* @param array $participants
* @param IUser|null $addedBy
* @param IUser|null $addedBy User that is attempting to add these users (must be set for federated users to be added)
*/
public function addUsers(Room $room, array $participants, ?IUser $addedBy = null): void {
if (empty($participants)) {
Expand Down Expand Up @@ -366,7 +366,7 @@ public function addUsers(Room $room, array $participants, ?IUser $addedBy = null
}

private function sendRemoteShare(Room $room, IUser $addedBy, string $addingUserId, string $token, int $attendeeId) {
$this->notifications->sendRemoteShare((string) $attendeeId, $token, $addingUserId, $room->getToken(), $addedBy->getDisplayName(), $addedBy->getCloudId(), $addedBy->getDisplayName(), $addedBy->getCloudId(), 'user', $room->getName(), (string) $room->getType());
$this->notifications->sendRemoteShare((string) $attendeeId, $token, $addingUserId, $addedBy->getDisplayName(), $addedBy->getCloudId(), $addedBy->getDisplayName(), $addedBy->getCloudId(), 'user', $room);
}

/**
Expand Down
79 changes: 73 additions & 6 deletions tests/php/Federation/FederationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
use OCA\Talk\Federation\FederationManager;
use OCA\Talk\Federation\Notifications;
use OCA\Talk\Manager;
use OCA\Talk\MatterbridgeManager;
use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\AttendeeMapper;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
use OCP\BackgroundJob\IJobList;
Expand Down Expand Up @@ -69,22 +72,30 @@ class FederationTest extends TestCase {
/** @var INotificationManager */
protected $notificationManager;

/** @var AttendeeMapper */
protected $attendeeMapper;

public function setUp(): void {
parent::setUp();

$this->cloudFederationProviderManager = $this->createMock(ICloudFederationProviderManager::class);
$this->cloudFederationFactory = $this->createMock(ICloudFederationFactory::class);
$this->addressHandler = $this->createMock(AddressHandler::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->attendeeMapper = $this->createMock(AttendeeMapper::class);

$this->notifications = new Notifications(
$this->cloudFederationFactory,
$this->addressHandler,
$this->createMock(LoggerInterface::class),
$this->cloudFederationProviderManager,
$this->createMock(IJobList::class)
$this->createMock(IJobList::class),
$this->userManager,
$this->attendeeMapper,
$this->createMock(MatterbridgeManager::class),
);

$this->federationManager = $this->createMock(FederationManager::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->notificationManager = $this->createMock(INotificationManager::class);

$this->cloudFederationProvider = new CloudFederationProviderTalk(
Expand All @@ -94,26 +105,82 @@ public function setUp(): void {
$this->notificationManager,
$this->createMock(IURLGenerator::class),
$this->createMock(ParticipantService::class),
$this->createMock(AttendeeMapper::class),
$this->attendeeMapper,
$this->createMock(Manager::class)
);
}

public function testSendRemoteShare() {
public function testSendRemoteShareWithOwner() {
$cloudShare = $this->createMock(ICloudFederationShare::class);

$providerId = '3';
$roomId = 5;
$token = 'abcdefghijklmno';
$shareWith = '[email protected]';
$name = 'abcdefgh';
$owner = 'Owner\'s name';
$ownerFederatedId = '[email protected]';
$ownerId = 'owner';
$ownerFederatedId = $ownerId . '@test.local';
$sharedBy = 'Owner\'s name';
$sharedByFederatedId = '[email protected]';
$shareType = 'user';
$roomType = Room::TYPE_GROUP;
$roomName = 'Room name';

$room = $this->createMock(Room::class);
$attendee = $this->createMock(Attendee::class);
$ownerUser = $this->createMock(IUser::class);

$room->expects($this->once())
->method('getName')
->with()
->willReturn($roomName);

$room->expects($this->once())
->method('getType')
->with()
->willReturn($roomType);

$room->expects($this->once())
->method('getToken')
->with()
->willReturn($name);

$room->expects($this->once())
->method('getId')
->with()
->willReturn($roomId);

$attendee->expects($this->once())
->method('getActorType')
->with()
->willReturn(Attendee::ACTOR_USERS);

$attendee->expects($this->once())
->method('getActorId')
->with()
->willReturn($ownerId);

$this->attendeeMapper->expects($this->once())
->method('getActorsByParticipantTypes')
->with($roomId, [Participant::OWNER])
->willReturn([$attendee]);

$this->userManager->expects($this->once())
->method('get')
->with($ownerId)
->willReturn($ownerUser);

$ownerUser->expects($this->once())
->method('getCloudId')
->with()
->willReturn($ownerFederatedId);

$ownerUser->expects($this->once())
->method('getDisplayName')
->with()
->willReturn($owner);

$this->cloudFederationFactory->expects($this->once())
->method('getCloudFederationShare')
->with(
Expand All @@ -140,7 +207,7 @@ public function testSendRemoteShare() {
->with($shareWith)
->willReturn(['test', 'remote.test.local']);

$this->notifications->sendRemoteShare($providerId, $token, $shareWith, $name, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId, $shareType, $roomName, (string) $roomType);
$this->notifications->sendRemoteShare($providerId, $token, $shareWith, $sharedBy, $sharedByFederatedId, $shareType, $room);
}

public function testReceiveRemoteShare() {
Expand Down

0 comments on commit 4987824

Please sign in to comment.