зеркало из https://github.com/nextcloud/spreed.git
Merge pull request #5775 from nextcloud/enh/5723/add-database
Implement Recieving Room Shares
This commit is contained in:
Коммит
56e1d3db96
|
@ -16,7 +16,7 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m
|
|||
|
||||
]]></description>
|
||||
|
||||
<version>13.0.0-dev</version>
|
||||
<version>13.0.0-dev.1</version>
|
||||
<licence>agpl</licence>
|
||||
|
||||
<author>Daniel Calviño Sánchez</author>
|
||||
|
|
|
@ -523,6 +523,27 @@ return [
|
|||
],
|
||||
],
|
||||
|
||||
/**
|
||||
* Federation
|
||||
*/
|
||||
|
||||
[
|
||||
'name' => 'Federation#acceptShare',
|
||||
'url' => 'api/{apiVersion}/federation/invitation/{id}',
|
||||
'verb' => 'POST',
|
||||
'requirements' => [
|
||||
'apiVersion' => 'v1',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'Federation#rejectShare',
|
||||
'url' => 'api/{apiVersion}/federation/invitation/{id}',
|
||||
'verb' => 'DELETE',
|
||||
'requirements' => [
|
||||
'apiVersion' => 'v1',
|
||||
],
|
||||
],
|
||||
|
||||
/**
|
||||
* PublicShareAuth
|
||||
*/
|
||||
|
|
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\Talk\BackgroundJob;
|
||||
|
||||
use OCA\Talk\Federation\FederationManager;
|
||||
use OCA\Talk\Service\ParticipantService;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\TimedJob;
|
||||
|
@ -46,6 +47,9 @@ class RemoveEmptyRooms extends TimedJob {
|
|||
/** @var LoggerInterface */
|
||||
protected $logger;
|
||||
|
||||
/** @var FederationManager */
|
||||
protected $federationManager;
|
||||
|
||||
protected $numDeletedRooms = 0;
|
||||
|
||||
public function __construct(ITimeFactory $timeFactory,
|
||||
|
@ -77,7 +81,7 @@ class RemoveEmptyRooms extends TimedJob {
|
|||
return;
|
||||
}
|
||||
|
||||
if ($this->participantService->getNumberOfActors($room) === 0 && $room->getObjectType() !== 'file') {
|
||||
if ($this->participantService->getNumberOfActors($room) === 0 && $room->getObjectType() !== 'file' && $this->federationManager->getNumberOfInvitations($room) === 0) {
|
||||
$room->deleteRoom();
|
||||
$this->numDeletedRooms++;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
<?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\Controller;
|
||||
|
||||
use OCA\Talk\AppInfo\Application;
|
||||
use OCA\Talk\Exceptions\UnauthorizedException;
|
||||
use OCA\Talk\Federation\FederationManager;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\DB\Exception as DBException;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
|
||||
class FederationController extends OCSController {
|
||||
/** @var FederationManager */
|
||||
private $federationManager;
|
||||
|
||||
/** @var IUserSession */
|
||||
private $userSession;
|
||||
|
||||
public function __construct(IRequest $request, FederationManager $federationManager, IUserSession $userSession) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
$this->federationManager = $federationManager;
|
||||
$this->userSession = $userSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
* @param int $id
|
||||
* @return DataResponse
|
||||
* @throws UnauthorizedException
|
||||
* @throws DBException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function acceptShare(int $id): DataResponse {
|
||||
$user = $this->userSession->getUser();
|
||||
if (!$user instanceof IUser) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
$this->federationManager->acceptRemoteRoomShare($user, $id);
|
||||
return new DataResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
* @param int $id
|
||||
* @return DataResponse
|
||||
* @throws UnauthorizedException
|
||||
* @throws DBException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function rejectShare(int $id): DataResponse {
|
||||
$user = $this->userSession->getUser();
|
||||
if (!$user instanceof IUser) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
$this->federationManager->rejectRemoteRoomShare($user, $id);
|
||||
return new DataResponse();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
<?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 Exception;
|
||||
use OCA\FederatedFileSharing\AddressHandler;
|
||||
use OCA\Talk\AppInfo\Application;
|
||||
use OCA\Talk\Manager;
|
||||
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\AppFramework\Http;
|
||||
use OCP\DB\Exception as DBException;
|
||||
use OCP\Federation\Exceptions\ActionNotSupportedException;
|
||||
use OCP\Federation\Exceptions\AuthenticationFailedException;
|
||||
use OCP\Federation\Exceptions\BadRequestException;
|
||||
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
|
||||
use OCP\Federation\ICloudFederationProvider;
|
||||
use OCP\Federation\ICloudFederationShare;
|
||||
use OCP\HintException;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Notification\IManager as INotificationManager;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
|
||||
class CloudFederationProviderTalk implements ICloudFederationProvider {
|
||||
|
||||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
|
||||
/** @var AddressHandler */
|
||||
private $addressHandler;
|
||||
|
||||
/** @var FederationManager */
|
||||
private $federationManager;
|
||||
|
||||
/** @var INotificationManager */
|
||||
private $notificationManager;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
|
||||
/** @var ParticipantService */
|
||||
private $participantService;
|
||||
|
||||
/** @var AttendeeMapper */
|
||||
private $attendeeMapper;
|
||||
|
||||
/** @var Manager */
|
||||
private $manager;
|
||||
|
||||
public function __construct(
|
||||
IUserManager $userManager,
|
||||
AddressHandler $addressHandler,
|
||||
FederationManager $federationManager,
|
||||
INotificationManager $notificationManager,
|
||||
IURLGenerator $urlGenerator,
|
||||
ParticipantService $participantService,
|
||||
AttendeeMapper $attendeeMapper,
|
||||
Manager $manager
|
||||
) {
|
||||
$this->userManager = $userManager;
|
||||
$this->addressHandler = $addressHandler;
|
||||
$this->federationManager = $federationManager;
|
||||
$this->notificationManager = $notificationManager;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->participantService = $participantService;
|
||||
$this->attendeeMapper = $attendeeMapper;
|
||||
$this->manager = $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getShareType(): string {
|
||||
return 'talk-room';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws HintException
|
||||
* @throws DBException
|
||||
*/
|
||||
public function shareReceived(ICloudFederationShare $share): string {
|
||||
if (!$this->federationManager->isEnabled()) {
|
||||
throw new ProviderCouldNotAddShareException('Server does not support talk federation', '', Http::STATUS_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
if (!in_array($share->getShareType(), $this->getSupportedShareTypes(), true)) {
|
||||
throw new ProviderCouldNotAddShareException('Support for sharing with non-users not implemented yet', '', Http::STATUS_NOT_IMPLEMENTED);
|
||||
// TODO: Implement group shares
|
||||
}
|
||||
|
||||
if (!is_numeric($share->getShareType())) {
|
||||
throw new ProviderCouldNotAddShareException('shareType is not a number', '', Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$shareSecret = $share->getShareSecret();
|
||||
$shareWith = $share->getShareWith();
|
||||
$remoteId = $share->getProviderId();
|
||||
$roomToken = $share->getResourceName();
|
||||
$roomName = $share->getProtocol()['roomName'];
|
||||
$roomType = (int) $share->getShareType();
|
||||
$sharedBy = $share->getSharedByDisplayName();
|
||||
$sharedByFederatedId = $share->getSharedBy();
|
||||
$owner = $share->getOwnerDisplayName();
|
||||
$ownerFederatedId = $share->getOwner();
|
||||
[, $remote] = $this->addressHandler->splitUserRemote($ownerFederatedId);
|
||||
|
||||
// if no explicit information about the person who created the share was send
|
||||
// we assume that the share comes from the owner
|
||||
if ($sharedByFederatedId === null) {
|
||||
$sharedBy = $owner;
|
||||
$sharedByFederatedId = $ownerFederatedId;
|
||||
}
|
||||
|
||||
if ($remote && $shareSecret && $shareWith && $roomToken && $remoteId && is_string($roomName) && $roomName && $owner) {
|
||||
$shareWith = $this->userManager->get($shareWith);
|
||||
if ($shareWith === null) {
|
||||
throw new ProviderCouldNotAddShareException('User does not exist', '',Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$shareId = (string) $this->federationManager->addRemoteRoom($shareWith, $remoteId, $roomType, $roomName, $roomToken, $remote, $shareSecret);
|
||||
|
||||
$this->notifyAboutNewShare($shareWith, $shareId, $sharedByFederatedId, $sharedBy, $roomName, $roomToken, $remote);
|
||||
return $shareId;
|
||||
}
|
||||
throw new ProviderCouldNotAddShareException('required request data not found', '', Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function notificationReceived($notificationType, $providerId, array $notification): array {
|
||||
if (!is_numeric($providerId)) {
|
||||
throw new BadRequestException(['providerId']);
|
||||
}
|
||||
switch ($notificationType) {
|
||||
case 'SHARE_ACCEPTED':
|
||||
return $this->shareAccepted((int) $providerId, $notification);
|
||||
case 'SHARE_DECLINED':
|
||||
return $this->shareDeclined((int) $providerId, $notification);
|
||||
case 'SHARE_UNSHARED':
|
||||
return []; // TODO: Implement
|
||||
case 'REQUEST_RESHARE':
|
||||
return []; // TODO: Implement
|
||||
case 'RESHARE_UNDO':
|
||||
return []; // TODO: Implement
|
||||
case 'RESHARE_CHANGE_PERMISSION':
|
||||
return []; // TODO: Implement
|
||||
}
|
||||
return [];
|
||||
// TODO: Implement notificationReceived() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ActionNotSupportedException
|
||||
* @throws ShareNotFound
|
||||
* @throws AuthenticationFailedException
|
||||
*/
|
||||
private function shareAccepted(int $id, array $notification): array {
|
||||
$attendee = $this->getAttendeeAndValidate($id, $notification['sharedSecret']);
|
||||
|
||||
// TODO: Add activity for share accepted
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ActionNotSupportedException
|
||||
* @throws ShareNotFound
|
||||
* @throws AuthenticationFailedException
|
||||
*/
|
||||
private function shareDeclined(int $id, array $notification): array {
|
||||
$attendee = $this->getAttendeeAndValidate($id, $notification['sharedSecret']);
|
||||
|
||||
$room = $this->manager->getRoomById($attendee->getRoomId());
|
||||
$participant = new Participant($room, $attendee, null);
|
||||
$this->participantService->removeAttendee($room, $participant, Room::PARTICIPANT_LEFT);
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws AuthenticationFailedException
|
||||
* @throws ActionNotSupportedException
|
||||
* @throws ShareNotFound
|
||||
*/
|
||||
private function getAttendeeAndValidate(int $id, string $sharedSecret): Attendee {
|
||||
if (!$this->federationManager->isEnabled()) {
|
||||
throw new ActionNotSupportedException('Server does not support Talk federation');
|
||||
}
|
||||
|
||||
try {
|
||||
$attendee = $this->attendeeMapper->getById($id);
|
||||
} catch (Exception $ex) {
|
||||
throw new ShareNotFound();
|
||||
}
|
||||
if ($attendee->getActorType() !== Attendee::ACTOR_FEDERATED_USERS) {
|
||||
throw new ShareNotFound();
|
||||
}
|
||||
if ($attendee->getAccessToken() !== $sharedSecret) {
|
||||
throw new AuthenticationFailedException();
|
||||
}
|
||||
return $attendee;
|
||||
}
|
||||
|
||||
private function notifyAboutNewShare(IUser $shareWith, string $shareId, string $sharedByFederatedId, string $sharedByName, string $roomName, string $roomToken, string $serverUrl) {
|
||||
$notification = $this->notificationManager->createNotification();
|
||||
$notification->setApp(Application::APP_ID)
|
||||
->setUser($shareWith->getUID())
|
||||
->setDateTime(new \DateTime())
|
||||
->setObject('remote_talk_share', $shareId)
|
||||
->setSubject('remote_talk_share', [
|
||||
'sharedByDisplayName' => $sharedByName,
|
||||
'sharedByFederatedId' => $sharedByFederatedId,
|
||||
'roomName' => $roomName,
|
||||
'serverUrl' => $serverUrl,
|
||||
'roomToken' => $roomToken,
|
||||
]);
|
||||
|
||||
$declineAction = $notification->createAction();
|
||||
$declineAction->setLabel('decline')
|
||||
->setLink($this->urlGenerator->linkToOCSRouteAbsolute('spreed.Federation.rejectShare', ['id' => $shareId]), 'DELETE');
|
||||
$notification->addAction($declineAction);
|
||||
|
||||
$acceptAction = $notification->createAction();
|
||||
$acceptAction->setLabel('accept')
|
||||
->setLink($this->urlGenerator->linkToOCSRouteAbsolute('spreed.Federation.acceptShare', ['id' => $shareId]), 'POST');
|
||||
$notification->addAction($acceptAction);
|
||||
|
||||
$this->notificationManager->notify($notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getSupportedShareTypes() {
|
||||
return ['user'];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
<?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\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\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 {
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
/** @var Manager */
|
||||
private $manager;
|
||||
|
||||
/** @var ParticipantService */
|
||||
private $participantService;
|
||||
|
||||
/** @var InvitationMapper */
|
||||
private $invitationMapper;
|
||||
|
||||
public function __construct(
|
||||
IConfig $config,
|
||||
Manager $manager,
|
||||
ParticipantService $participantService,
|
||||
InvitationMapper $invitationMapper
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->manager = $manager;
|
||||
$this->participantService = $participantService;
|
||||
$this->invitationMapper = $invitationMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if Talk federation is enabled on this instance
|
||||
* @return bool
|
||||
*/
|
||||
public function isEnabled(): bool {
|
||||
// TODO: Set to default true once implementation is complete
|
||||
return $this->config->getAppValue(Application::APP_ID, 'federation_enabled', "false") === "true";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
* @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
|
||||
*/
|
||||
public function acceptRemoteRoomShare(IUser $user, int $shareId) {
|
||||
$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());
|
||||
$participant = [
|
||||
[
|
||||
'actorType' => Attendee::ACTOR_USERS,
|
||||
'actorId' => $user->getUID(),
|
||||
'displayName' => $user->getDisplayName(),
|
||||
'accessToken' => $invitation->getAccessToken(),
|
||||
'remoteId' => $invitation->getRemoteId(),
|
||||
]
|
||||
];
|
||||
$this->participantService->addUsers($room, $participant);
|
||||
|
||||
$this->invitationMapper->delete($invitation);
|
||||
|
||||
// TODO: Send SHARE_ACCEPTED notification
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DBException
|
||||
* @throws UnauthorizedException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function rejectRemoteRoomShare(IUser $user, int $shareId) {
|
||||
$invitation = $this->invitationMapper->getInvitationById($shareId);
|
||||
if ($invitation->getUserId() !== $user->getUID()) {
|
||||
throw new UnauthorizedException('invitation is for a different user');
|
||||
}
|
||||
$this->invitationMapper->delete($invitation);
|
||||
|
||||
// TODO: Send SHARE_DECLINED notification
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DBException
|
||||
*/
|
||||
public function getNumberOfInvitations(Room $room): int {
|
||||
return $this->invitationMapper->countInvitationsForRoom($room);
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ use OCP\AppFramework\Utility\ITimeFactory;
|
|||
use OCP\Comments\IComment;
|
||||
use OCP\Comments\ICommentsManager;
|
||||
use OCP\Comments\NotFoundException;
|
||||
use OCP\DB\Exception as DBException;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\ICache;
|
||||
|
@ -185,6 +186,7 @@ class Manager {
|
|||
(string) $row['name'],
|
||||
(string) $row['description'],
|
||||
(string) $row['password'],
|
||||
(string) $row['server_url'],
|
||||
(int) $row['active_guests'],
|
||||
(int) $row['call_flag'],
|
||||
$activeSince,
|
||||
|
@ -628,7 +630,7 @@ class Manager {
|
|||
* @return Room
|
||||
* @throws RoomNotFoundException
|
||||
*/
|
||||
public function getRoomByActor(string $token, string $actorType, string $actorId, ?string $sessionId = null): Room {
|
||||
public function getRoomByActor(string $token, string $actorType, string $actorId, ?string $sessionId = null, ?string $serverUrl = null): Room {
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$helper = new SelectHelper();
|
||||
$helper->selectRoomsTable($query);
|
||||
|
@ -641,6 +643,12 @@ class Manager {
|
|||
))
|
||||
->where($query->expr()->eq('r.token', $query->createNamedParameter($token)));
|
||||
|
||||
if ($serverUrl === null) {
|
||||
$query->andWhere($query->expr()->isNull('r.server_url'));
|
||||
} else {
|
||||
$query->andWhere($query->expr()->eq('r.server_url', $query->createNamedParameter($serverUrl)));
|
||||
}
|
||||
|
||||
if ($sessionId !== null) {
|
||||
$helper->selectSessionsTable($query);
|
||||
$query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX(
|
||||
|
@ -676,10 +684,10 @@ class Manager {
|
|||
* @return Room
|
||||
* @throws RoomNotFoundException
|
||||
*/
|
||||
public function getRoomByToken(string $token, ?string $preloadUserId = null): Room {
|
||||
public function getRoomByToken(string $token, ?string $preloadUserId = null, ?string $serverUrl = null): Room {
|
||||
$preloadUserId = $preloadUserId === '' ? null : $preloadUserId;
|
||||
if ($preloadUserId !== null) {
|
||||
return $this->getRoomByActor($token, Attendee::ACTOR_USERS, $preloadUserId);
|
||||
return $this->getRoomByActor($token, Attendee::ACTOR_USERS, $preloadUserId, null, $serverUrl);
|
||||
}
|
||||
|
||||
$query = $this->db->getQueryBuilder();
|
||||
|
@ -688,6 +696,13 @@ class Manager {
|
|||
$query->from('talk_rooms', 'r')
|
||||
->where($query->expr()->eq('r.token', $query->createNamedParameter($token)));
|
||||
|
||||
if ($serverUrl === null) {
|
||||
$query->andWhere($query->expr()->isNull('r.server_url'));
|
||||
} else {
|
||||
$query->andWhere($query->expr()->eq('r.server_url', $query->createNamedParameter($serverUrl)));
|
||||
}
|
||||
|
||||
|
||||
$result = $query->execute();
|
||||
$row = $result->fetch();
|
||||
$result->closeCursor();
|
||||
|
@ -908,6 +923,29 @@ class Manager {
|
|||
return $room;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
* @param string $name
|
||||
* @return Room
|
||||
* @throws DBException
|
||||
*/
|
||||
public function createRemoteRoom(int $type, string $name, string $token, string $serverUrl): Room {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
|
||||
$qb->insert('talk_rooms')
|
||||
->values([
|
||||
'name' => $qb->createNamedParameter($name),
|
||||
'type' => $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT),
|
||||
'token' => $qb->createNamedParameter($token),
|
||||
'server_url' => $qb->createNamedParameter($serverUrl),
|
||||
]);
|
||||
|
||||
$qb->executeStatement();
|
||||
$roomId = $qb->getLastInsertId();
|
||||
|
||||
return $this->getRoomById($roomId);
|
||||
}
|
||||
|
||||
public function resolveRoomDisplayName(Room $room, string $userId): string {
|
||||
if ($room->getObjectType() === 'share:password') {
|
||||
return $this->l->t('Password request: %s', [$room->getName()]);
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
<?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\Migration;
|
||||
|
||||
use Closure;
|
||||
use Doctrine\DBAL\Schema\SchemaException;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
class Version13000Date20210625232111 extends SimpleMigrationStep {
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
* @throws SchemaException
|
||||
*/
|
||||
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
$table = $schema->getTable('talk_attendees');
|
||||
if (!$table->hasColumn('access_token')) {
|
||||
$table->addColumn('access_token', Types::STRING, [
|
||||
'notnull' => false,
|
||||
'default' => null,
|
||||
'length' => 64
|
||||
]);
|
||||
}
|
||||
if (!$table->hasColumn('remote_id')) {
|
||||
$table->addColumn('remote_id', Types::STRING, [
|
||||
'notnull' => false,
|
||||
'default' => null,
|
||||
'length' => 255,
|
||||
]);
|
||||
}
|
||||
|
||||
$table = $schema->getTable('talk_rooms');
|
||||
if (!$table->hasColumn('server_url')) {
|
||||
$table->addColumn('server_url', Types::STRING, [
|
||||
'notnull' => false,
|
||||
'default' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$schema->hasTable('talk_invitations')) {
|
||||
$table = $schema->createTable('talk_invitations');
|
||||
$table->addColumn('id', Types::BIGINT, [
|
||||
'autoincrement' => true,
|
||||
'notnull' => true,
|
||||
]);
|
||||
$table->addColumn('room_id', Types::BIGINT, [
|
||||
'notnull' => true,
|
||||
'unsigned' => true,
|
||||
]);
|
||||
$table->addColumn('user_id', Types::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 255,
|
||||
]);
|
||||
$table->addColumn('access_token', Types::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('remote_id', Types::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 255,
|
||||
]);
|
||||
|
||||
$table->setPrimaryKey(['id']);
|
||||
|
||||
$table->addIndex(['room_id']);
|
||||
}
|
||||
|
||||
|
||||
return $schema;
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ use OCP\AppFramework\Db\Entity;
|
|||
|
||||
/**
|
||||
* @method void setRoomId(int $roomId)
|
||||
* @method string getRoomId()
|
||||
* @method int getRoomId()
|
||||
* @method void setActorType(string $actorType)
|
||||
* @method string getActorType()
|
||||
* @method void setActorId(string $actorId)
|
||||
|
@ -51,6 +51,10 @@ use OCP\AppFramework\Db\Entity;
|
|||
* @method int getReadPrivacy()
|
||||
* @method void setPublishingPermissions(int $publishingPermissions)
|
||||
* @method int getPublishingPermissions()
|
||||
* @method void setAccessToken(string $accessToken)
|
||||
* @method null|string getAccessToken()
|
||||
* @method void setRemoteId(string $remoteId)
|
||||
* @method string getRemoteId()
|
||||
*/
|
||||
class Attendee extends Entity {
|
||||
public const ACTOR_USERS = 'users';
|
||||
|
@ -59,6 +63,7 @@ class Attendee extends Entity {
|
|||
public const ACTOR_EMAILS = 'emails';
|
||||
public const ACTOR_CIRCLES = 'circles';
|
||||
public const ACTOR_BRIDGED = 'bridged';
|
||||
public const ACTOR_FEDERATED_USERS = 'federated_users';
|
||||
|
||||
public const PUBLISHING_PERMISSIONS_NONE = 0;
|
||||
public const PUBLISHING_PERMISSIONS_AUDIO = 1;
|
||||
|
@ -105,6 +110,12 @@ class Attendee extends Entity {
|
|||
/** @var int */
|
||||
protected $publishingPermissions;
|
||||
|
||||
/** @var string */
|
||||
protected $accessToken;
|
||||
|
||||
/** @var string */
|
||||
protected $remoteId;
|
||||
|
||||
public function __construct() {
|
||||
$this->addType('roomId', 'int');
|
||||
$this->addType('actorType', 'string');
|
||||
|
@ -119,6 +130,8 @@ class Attendee extends Entity {
|
|||
$this->addType('lastMentionMessage', 'int');
|
||||
$this->addType('readPrivacy', 'int');
|
||||
$this->addType('publishingPermissions', 'int');
|
||||
$this->addType('accessToken', 'string');
|
||||
$this->addType('remote_id', 'string');
|
||||
}
|
||||
|
||||
public function getDisplayName(): string {
|
||||
|
@ -144,6 +157,8 @@ class Attendee extends Entity {
|
|||
'last_mention_message' => $this->getLastMentionMessage(),
|
||||
'read_privacy' => $this->getReadPrivacy(),
|
||||
'publishing_permissions' => $this->getPublishingPermissions(),
|
||||
'access_token' => $this->getAccessToken(),
|
||||
'remote_id' => $this->getRemoteId(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,17 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\Talk\Model;
|
||||
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\AppFramework\Db\QBMapper;
|
||||
use OCP\DB\Exception as DBException;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
/**
|
||||
* @method Attendee mapRowToEntity(array $row)
|
||||
* @method Attendee findEntity(IQueryBuilder $query)
|
||||
* @method Attendee[] findEntities(IQueryBuilder $query)
|
||||
*/
|
||||
class AttendeeMapper extends QBMapper {
|
||||
|
||||
|
@ -44,7 +49,7 @@ class AttendeeMapper extends QBMapper {
|
|||
* @param string $actorType
|
||||
* @param string $actorId
|
||||
* @return Attendee
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws DoesNotExistException
|
||||
*/
|
||||
public function findByActor(int $roomId, string $actorType, string $actorId): Attendee {
|
||||
$query = $this->db->getQueryBuilder();
|
||||
|
@ -57,6 +62,22 @@ class AttendeeMapper extends QBMapper {
|
|||
return $this->findEntity($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return Attendee
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws DBException
|
||||
*/
|
||||
public function getById(int $id): Attendee {
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$query->select('*')
|
||||
->from($this->getTableName())
|
||||
->where($query->expr()->eq('id', $query->createNamedParameter($id)));
|
||||
|
||||
return $this->findEntity($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $roomId
|
||||
* @param string $actorType
|
||||
|
@ -153,6 +174,8 @@ class AttendeeMapper extends QBMapper {
|
|||
'last_mention_message' => (int) $row['last_mention_message'],
|
||||
'read_privacy' => (int) $row['read_privacy'],
|
||||
'publishing_permissions' => (int) $row['publishing_permissions'],
|
||||
'access_token' => (string) $row['access_token'],
|
||||
'remote_id' => (string) $row['remote_id'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
<?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\Model;
|
||||
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
|
||||
/**
|
||||
* Class Invitation
|
||||
*
|
||||
* @package OCA\Talk\Model
|
||||
*
|
||||
* @method void setRoomId(int $roomId)
|
||||
* @method int getRoomId()
|
||||
* @method void setUserId(string $userId)
|
||||
* @method string getUserId()
|
||||
* @method void setAccessToken(string $accessToken)
|
||||
* @method string getAccessToken()
|
||||
* @method void setRemoteId(string $remoteId)
|
||||
* @method string getRemoteId()
|
||||
*/
|
||||
class Invitation extends Entity {
|
||||
/** @var int */
|
||||
protected $roomId;
|
||||
|
||||
/** @var string */
|
||||
protected $userId;
|
||||
|
||||
/** @var string */
|
||||
protected $accessToken;
|
||||
|
||||
/** @var string */
|
||||
protected $remoteId;
|
||||
|
||||
public function __construct() {
|
||||
$this->addType('roomId', 'int');
|
||||
$this->addType('userId', 'string');
|
||||
$this->addType('accessToken', 'string');
|
||||
$this->addType('remoteId', 'string');
|
||||
}
|
||||
|
||||
public function asArray(): array {
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'room_id' => $this->getRoomId(),
|
||||
'user_id' => $this->getUserId(),
|
||||
'access_token' => $this->getAccessToken(),
|
||||
'remote_id' => $this->getRemoteId(),
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
<?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\Model;
|
||||
|
||||
use OCA\Talk\Room;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\AppFramework\Db\QBMapper;
|
||||
use OCP\DB\Exception as DBException;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
/**
|
||||
* Class InvitationMapper
|
||||
*
|
||||
* @package OCA\Talk\Model
|
||||
*
|
||||
* @method Invitation mapRowToEntity(array $row)
|
||||
* @method Invitation findEntity(IQueryBuilder $query)
|
||||
* @method Invitation[] findEntities(IQueryBuilder $query)
|
||||
*/
|
||||
class InvitationMapper extends QBMapper {
|
||||
public function __construct(IDBConnection $db) {
|
||||
parent::__construct($db, 'talk_invitations', Invitation::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DBException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws DoesNotExistException
|
||||
*/
|
||||
public function getInvitationById(int $id): Invitation {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
|
||||
|
||||
return $this->findEntity($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Room $room
|
||||
* @return Invitation[]
|
||||
* @throws DBException
|
||||
*/
|
||||
public function getInvitationsForRoom(Room $room): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->where($qb->expr()->eq('room_id', $qb->createNamedParameter($room->getId())));
|
||||
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DBException
|
||||
*/
|
||||
public function countInvitationsForRoom(Room $room): int {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
|
||||
$qb->select($qb->func()->count('*', 'num_invitations'))
|
||||
->from($this->getTableName())
|
||||
->where($qb->expr()->eq('room_id', $qb->createNamedParameter($room->getId())));
|
||||
|
||||
$result = $qb->executeQuery();
|
||||
$row = $result->fetch();
|
||||
$result->closeCursor();
|
||||
|
||||
return (int) ($row['num_invitations' ?? 0]);
|
||||
}
|
||||
|
||||
public function createInvitationFromRow(array $row): Invitation {
|
||||
return $this->mapRowToEntity([
|
||||
'id' => $row['id'],
|
||||
'room_id' => (int) $row['room_id'],
|
||||
'user_id' => (string) $row['user_id'],
|
||||
'access_token' => (string) $row['access_token'],
|
||||
'remote_id' => (string) $row['remote_id'],
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -49,6 +49,7 @@ class SelectHelper {
|
|||
->addSelect($alias . 'object_type')
|
||||
->addSelect($alias . 'object_id')
|
||||
->addSelect($alias . 'listable')
|
||||
->addSelect($alias . 'server_url')
|
||||
->selectAlias($alias . 'id', 'r_id');
|
||||
}
|
||||
|
||||
|
@ -70,6 +71,8 @@ class SelectHelper {
|
|||
->addSelect($alias . 'last_mention_message')
|
||||
->addSelect($alias . 'read_privacy')
|
||||
->addSelect($alias . 'publishing_permissions')
|
||||
->addSelect($alias . 'access_token')
|
||||
->addSelect($alias . 'remote_id')
|
||||
->selectAlias($alias . 'id', 'a_id');
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\Talk\Notification;
|
||||
|
||||
use OCA\FederatedFileSharing\AddressHandler;
|
||||
use OCA\Talk\Chat\CommentsManager;
|
||||
use OCA\Talk\Chat\MessageParser;
|
||||
use OCA\Talk\Config;
|
||||
|
@ -36,6 +37,7 @@ use OCA\Talk\Room;
|
|||
use OCA\Talk\Service\ParticipantService;
|
||||
use OCP\Comments\ICommentsManager;
|
||||
use OCP\Comments\NotFoundException;
|
||||
use OCP\HintException;
|
||||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
|
@ -77,6 +79,8 @@ class Notifier implements INotifier {
|
|||
protected $messageParser;
|
||||
/** @var Definitions */
|
||||
protected $definitions;
|
||||
/** @var AddressHandler */
|
||||
protected $addressHandler;
|
||||
|
||||
/** @var Room[] */
|
||||
protected $rooms = [];
|
||||
|
@ -94,7 +98,8 @@ class Notifier implements INotifier {
|
|||
INotificationManager $notificationManager,
|
||||
CommentsManager $commentManager,
|
||||
MessageParser $messageParser,
|
||||
Definitions $definitions) {
|
||||
Definitions $definitions,
|
||||
AddressHandler $addressHandler) {
|
||||
$this->lFactory = $lFactory;
|
||||
$this->url = $url;
|
||||
$this->config = $config;
|
||||
|
@ -107,6 +112,7 @@ class Notifier implements INotifier {
|
|||
$this->commentManager = $commentManager;
|
||||
$this->messageParser = $messageParser;
|
||||
$this->definitions = $definitions;
|
||||
$this->addressHandler = $addressHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,6 +264,10 @@ class Notifier implements INotifier {
|
|||
return $this->parseChatMessage($notification, $room, $participant, $l);
|
||||
}
|
||||
|
||||
if ($subject === 'remote_talk_share') {
|
||||
return $this->parseRemoteInvitationMessage($notification, $l);
|
||||
}
|
||||
|
||||
$this->notificationManager->markProcessed($notification);
|
||||
throw new \InvalidArgumentException('Unknown subject');
|
||||
}
|
||||
|
@ -270,6 +280,47 @@ class Notifier implements INotifier {
|
|||
return $temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws HintException
|
||||
*/
|
||||
protected function parseRemoteInvitationMessage(INotification $notification, IL10N $l): INotification {
|
||||
$subjectParameters = $notification->getSubjectParameters();
|
||||
|
||||
[$sharedById, $sharedByServer] = $this->addressHandler->splitUserRemote($subjectParameters['sharedByFederatedId']);
|
||||
|
||||
$message = $l->t('{user1} shared room {roomName} on {remoteServer} with you');
|
||||
|
||||
$rosParameters = [
|
||||
'user1' => [
|
||||
'type' => 'user',
|
||||
'id' => $sharedById,
|
||||
'name' => $subjectParameters['sharedByDisplayName'],
|
||||
'server' => $sharedByServer,
|
||||
],
|
||||
'roomName' => [
|
||||
'type' => 'highlight',
|
||||
'id' => $subjectParameters['serverUrl'] . '::' . $subjectParameters['roomToken'],
|
||||
'name' => $subjectParameters['roomName'],
|
||||
],
|
||||
'remoteServer' => [
|
||||
'type' => 'highlight',
|
||||
'id' => $subjectParameters['serverUrl'],
|
||||
'name' => $subjectParameters['serverUrl'],
|
||||
]
|
||||
];
|
||||
|
||||
$placeholders = $replacements = [];
|
||||
foreach ($rosParameters as $placeholder => $parameter) {
|
||||
$placeholders[] = '{' . $placeholder .'}';
|
||||
$replacements[] = $parameter['name'];
|
||||
}
|
||||
|
||||
$notification->setParsedMessage(str_replace($placeholders, $replacements, $message));
|
||||
$notification->setRichMessage($message, $rosParameters);
|
||||
|
||||
return $notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param INotification $notification
|
||||
* @param Room $room
|
||||
|
|
12
lib/Room.php
12
lib/Room.php
|
@ -180,6 +180,8 @@ class Room {
|
|||
private $description;
|
||||
/** @var string */
|
||||
private $password;
|
||||
/** @var string */
|
||||
private $serverUrl;
|
||||
/** @var int */
|
||||
private $activeGuests;
|
||||
/** @var int */
|
||||
|
@ -218,6 +220,7 @@ class Room {
|
|||
string $name,
|
||||
string $description,
|
||||
string $password,
|
||||
string $serverUrl,
|
||||
int $activeGuests,
|
||||
int $callFlag,
|
||||
?\DateTime $activeSince,
|
||||
|
@ -243,6 +246,7 @@ class Room {
|
|||
$this->name = $name;
|
||||
$this->description = $description;
|
||||
$this->password = $password;
|
||||
$this->serverUrl = $serverUrl;
|
||||
$this->activeGuests = $activeGuests;
|
||||
$this->callFlag = $callFlag;
|
||||
$this->activeSince = $activeSince;
|
||||
|
@ -377,6 +381,14 @@ class Room {
|
|||
return $this->password;
|
||||
}
|
||||
|
||||
public function getServerUrl(): string {
|
||||
return $this->serverUrl;
|
||||
}
|
||||
|
||||
public function isFederatedRemoteRoom(): bool {
|
||||
return $this->serverUrl !== '';
|
||||
}
|
||||
|
||||
public function setParticipant(?string $userId, Participant $participant): void {
|
||||
$this->currentUser = $userId;
|
||||
$this->participant = $participant;
|
||||
|
|
|
@ -326,6 +326,12 @@ class ParticipantService {
|
|||
if (isset($participant['displayName'])) {
|
||||
$attendee->setDisplayName($participant['displayName']);
|
||||
}
|
||||
if (isset($participant['accessToken'])) {
|
||||
$attendee->setAccessToken($participant['accessToken']);
|
||||
}
|
||||
if (isset($participant['remoteId'])) {
|
||||
$attendee->setRemoteId($participant['remoteId']);
|
||||
}
|
||||
$attendee->setParticipantType($participant['participantType'] ?? Participant::USER);
|
||||
$attendee->setLastReadMessage($lastMessage);
|
||||
$attendee->setReadPrivacy($readPrivacy);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
<referencedClass name="OCA\Circles\Model\Circle" />
|
||||
<referencedClass name="OCA\Circles\Model\Member" />
|
||||
<referencedClass name="OCA\DAV\CardDAV\PhotoCache" />
|
||||
<referencedClass name="OCA\FederatedFileSharing\AddressHandler" />
|
||||
<referencedClass name="OCA\Files_Sharing\SharedStorage" />
|
||||
</errorLevel>
|
||||
</UndefinedClass>
|
||||
|
@ -43,6 +44,7 @@
|
|||
<referencedClass name="OC\DB\ConnectionAdapter" />
|
||||
<referencedClass name="OCA\Circles\Model\Member" />
|
||||
<referencedClass name="OCA\DAV\CardDAV\PhotoCache" />
|
||||
<referencedClass name="OCA\FederatedFileSharing\AddressHandler" />
|
||||
</errorLevel>
|
||||
</UndefinedDocblockClass>
|
||||
<UndefinedInterfaceMethod>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
namespace OCA\Talk\Tests\php\Notifications;
|
||||
|
||||
use OCA\FederatedFileSharing\AddressHandler;
|
||||
use OCA\Talk\Chat\CommentsManager;
|
||||
use OCA\Talk\Chat\MessageParser;
|
||||
use OCA\Talk\Config;
|
||||
|
@ -75,6 +76,8 @@ class NotifierTest extends \Test\TestCase {
|
|||
protected $definitions;
|
||||
/** @var Notifier */
|
||||
protected $notifier;
|
||||
/** @var AddressHandler|MockObject */
|
||||
protected $addressHandler;
|
||||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
|
@ -91,6 +94,7 @@ class NotifierTest extends \Test\TestCase {
|
|||
$this->commentsManager = $this->createMock(CommentsManager::class);
|
||||
$this->messageParser = $this->createMock(MessageParser::class);
|
||||
$this->definitions = $this->createMock(Definitions::class);
|
||||
$this->addressHandler = $this->createMock(AddressHandler::class);
|
||||
|
||||
$this->notifier = new Notifier(
|
||||
$this->lFactory,
|
||||
|
@ -104,7 +108,8 @@ class NotifierTest extends \Test\TestCase {
|
|||
$this->notificationManager,
|
||||
$this->commentsManager,
|
||||
$this->messageParser,
|
||||
$this->definitions
|
||||
$this->definitions,
|
||||
$this->addressHandler
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ class RoomTest extends TestCase {
|
|||
'Test',
|
||||
'description',
|
||||
'passy',
|
||||
'',
|
||||
0,
|
||||
Participant::FLAG_DISCONNECTED,
|
||||
null,
|
||||
|
|
Загрузка…
Ссылка в новой задаче