You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
5.7 KiB
187 lines
5.7 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
/**
|
|
* @copyright Copyright (c) 2021 Gary Kim <gary@garykim.dev>
|
|
*
|
|
* @author Gary Kim <gary@garykim.dev>
|
|
*
|
|
* @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\Federation;
|
|
|
|
use OCA\Talk\AppInfo\Application;
|
|
use OCA\Talk\Exceptions\CannotReachRemoteException;
|
|
use OCA\Talk\Exceptions\RoomNotFoundException;
|
|
use OCA\Talk\Exceptions\UnauthorizedException;
|
|
use OCA\Talk\Manager;
|
|
use OCA\Talk\Model\Attendee;
|
|
use OCA\Talk\Model\Invitation;
|
|
use OCA\Talk\Model\InvitationMapper;
|
|
use OCA\Talk\Room;
|
|
use OCA\Talk\Service\ParticipantService;
|
|
use OCP\AppFramework\Db\DoesNotExistException;
|
|
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
|
use OCP\DB\Exception as DBException;
|
|
use OCP\IConfig;
|
|
use OCP\IUser;
|
|
|
|
/**
|
|
* Class FederationManager
|
|
*
|
|
* @package OCA\Talk\Federation
|
|
*
|
|
* FederationManager handles incoming federated rooms
|
|
*/
|
|
class FederationManager {
|
|
public const TALK_ROOM_RESOURCE = 'talk-room';
|
|
public const TALK_PROTOCOL_NAME = 'nctalk';
|
|
public const TOKEN_LENGTH = 15;
|
|
|
|
private IConfig $config;
|
|
|
|
private Manager $manager;
|
|
|
|
private ParticipantService $participantService;
|
|
|
|
private InvitationMapper $invitationMapper;
|
|
|
|
private Notifications $notifications;
|
|
|
|
public function __construct(
|
|
IConfig $config,
|
|
Manager $manager,
|
|
ParticipantService $participantService,
|
|
InvitationMapper $invitationMapper,
|
|
Notifications $notifications,
|
|
) {
|
|
$this->config = $config;
|
|
$this->manager = $manager;
|
|
$this->participantService = $participantService;
|
|
$this->invitationMapper = $invitationMapper;
|
|
$this->notifications = $notifications;
|
|
}
|
|
|
|
/**
|
|
* Determine if Talk federation is enabled on this instance
|
|
* @return bool
|
|
* @deprecated use \OCA\Talk\Config::isFederationEnabled()
|
|
*/
|
|
public function isEnabled(): bool {
|
|
// TODO: Set to default true once implementation is complete
|
|
return $this->config->getAppValue(Application::APP_ID, 'federation_enabled', 'no') === 'yes';
|
|
}
|
|
|
|
/**
|
|
* @param IUser $user
|
|
* @param string $remoteId
|
|
* @param int $roomType
|
|
* @param string $roomName
|
|
* @param string $roomToken
|
|
* @param string $remoteUrl
|
|
* @param string $sharedSecret
|
|
* @return int share id for this specific remote room share
|
|
* @throws DBException
|
|
*/
|
|
public function addRemoteRoom(IUser $user, string $remoteId, int $roomType, string $roomName, string $roomToken, string $remoteUrl, string $sharedSecret): int {
|
|
try {
|
|
$room = $this->manager->getRoomByToken($roomToken, null, $remoteUrl);
|
|
} catch (RoomNotFoundException $ex) {
|
|
$room = $this->manager->createRemoteRoom($roomType, $roomName, $roomToken, $remoteUrl);
|
|
}
|
|
$invitation = new Invitation();
|
|
$invitation->setUserId($user->getUID());
|
|
$invitation->setRoomId($room->getId());
|
|
$invitation->setAccessToken($sharedSecret);
|
|
$invitation->setRemoteId($remoteId);
|
|
$invitation = $this->invitationMapper->insert($invitation);
|
|
|
|
return $invitation->getId();
|
|
}
|
|
|
|
/**
|
|
* @throws DBException
|
|
* @throws UnauthorizedException
|
|
* @throws MultipleObjectsReturnedException
|
|
* @throws DoesNotExistException
|
|
* @throws CannotReachRemoteException
|
|
*/
|
|
public function acceptRemoteRoomShare(IUser $user, int $shareId): void {
|
|
$invitation = $this->invitationMapper->getInvitationById($shareId);
|
|
if ($invitation->getUserId() !== $user->getUID()) {
|
|
throw new UnauthorizedException('invitation is for a different user');
|
|
}
|
|
|
|
// Add user to the room
|
|
$room = $this->manager->getRoomById($invitation->getRoomId());
|
|
if (
|
|
!$this->notifications->sendShareAccepted($room->getRemoteServer(), $invitation->getRemoteId(), $invitation->getAccessToken())
|
|
) {
|
|
throw new CannotReachRemoteException();
|
|
}
|
|
|
|
|
|
$participant = [
|
|
[
|
|
'actorType' => Attendee::ACTOR_USERS,
|
|
'actorId' => $user->getUID(),
|
|
'displayName' => $user->getDisplayName(),
|
|
'accessToken' => $invitation->getAccessToken(),
|
|
'remoteId' => $invitation->getRemoteId(), // FIXME this seems unnecessary
|
|
]
|
|
];
|
|
$this->participantService->addUsers($room, $participant, $user);
|
|
|
|
$this->invitationMapper->delete($invitation);
|
|
}
|
|
|
|
/**
|
|
* @throws DBException
|
|
* @throws UnauthorizedException
|
|
* @throws MultipleObjectsReturnedException
|
|
* @throws DoesNotExistException
|
|
*/
|
|
public function rejectRemoteRoomShare(IUser $user, int $shareId): void {
|
|
$invitation = $this->invitationMapper->getInvitationById($shareId);
|
|
if ($invitation->getUserId() !== $user->getUID()) {
|
|
throw new UnauthorizedException('invitation is for a different user');
|
|
}
|
|
|
|
$room = $this->manager->getRoomById($invitation->getRoomId());
|
|
|
|
$this->invitationMapper->delete($invitation);
|
|
|
|
$this->notifications->sendShareDeclined($room->getRemoteServer(), $invitation->getRemoteId(), $invitation->getAccessToken());
|
|
}
|
|
|
|
/**
|
|
* @param IUser $user
|
|
* @return Invitation[]
|
|
* @throws DBException
|
|
*/
|
|
public function getRemoteRoomShares(IUser $user): array {
|
|
return $this->invitationMapper->getInvitationsForUser($user);
|
|
}
|
|
|
|
/**
|
|
* @throws DBException
|
|
*/
|
|
public function getNumberOfInvitations(Room $room): int {
|
|
return $this->invitationMapper->countInvitationsForRoom($room);
|
|
}
|
|
}
|