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.
 
 
 
 
 

275 lines
9.2 KiB

<?php
declare(strict_types=1);
/**
*
* @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.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\Controller;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Files\Util;
use OCA\Talk\Manager;
use OCA\Talk\Room;
use OCA\Talk\Service\RoomService;
use OCA\Talk\TalkSession;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\AppFramework\OCSController;
use OCP\Files\FileInfo;
use OCP\Files\NotFoundException;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager as IShareManager;
use OCP\Share\IShare;
class FilesIntegrationController extends OCSController {
/** @var Manager */
private $manager;
/** @var RoomService */
private $roomService;
/** @var IShareManager */
private $shareManager;
/** @var ISession */
private $session;
/** @var IUserSession */
private $userSession;
/** @var TalkSession */
private $talkSession;
/** @var Util */
private $util;
/** @var IConfig */
private $config;
/** @var IL10N */
private $l;
public function __construct(
string $appName,
IRequest $request,
Manager $manager,
RoomService $roomService,
IShareManager $shareManager,
ISession $session,
IUserSession $userSession,
TalkSession $talkSession,
Util $util,
IConfig $config,
IL10N $l10n
) {
parent::__construct($appName, $request);
$this->manager = $manager;
$this->roomService = $roomService;
$this->shareManager = $shareManager;
$this->session = $session;
$this->userSession = $userSession;
$this->talkSession = $talkSession;
$this->util = $util;
$this->config = $config;
$this->l = $l10n;
}
/**
* @NoAdminRequired
*
* Returns the token of the room associated to the given file id.
*
* This is the counterpart of self::getRoomByShareToken() for file ids
* instead of share tokens, although both return the same room token if the
* given file id and share token refer to the same file.
*
* If there is no room associated to the given file id a new room is
* created; the new room is a public room associated with a "file" object
* with the given file id. Unlike normal rooms in which the owner is the
* user that created the room these are special rooms without owner
* (although self joined users with direct access to the file become
* persistent participants automatically when they join until they
* explicitly leave or no longer have access to the file).
*
* In any case, to create or even get the token of the room, the file must
* be shared and the user must be the owner of a public share of the file
* (like a link share, for example) or have direct access to that file; an
* error is returned otherwise. A user has direct access to a file if she
* has access to it (or to an ancestor) through a user, group, circle or
* room share (but not through a link share, for example), or if she is the
* owner of such a file.
*
* @param string $fileId
* @return DataResponse the status code is "200 OK" if a room is returned,
* or "404 Not found" if the given file id was invalid.
* @throws OCSNotFoundException
*/
public function getRoomByFileId(string $fileId): DataResponse {
if ($this->config->getAppValue('spreed', 'conversations_files', '1') !== '1') {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
$currentUser = $this->userSession->getUser();
if (!$currentUser instanceof IUser) {
throw new OCSException($this->l->t('File is not shared, or shared but not with the user'), Http::STATUS_UNAUTHORIZED);
}
$share = $this->util->getAnyPublicShareOfFileOwnedByUserOrAnyDirectShareOfFileAccessibleByUser($fileId, $currentUser->getUID());
$groupFolder = null;
if (!$share) {
$groupFolder = $this->util->getGroupFolderNode($fileId, $currentUser->getUID());
if (!$groupFolder) {
throw new OCSNotFoundException($this->l->t('File is not shared, or shared but not with the user'));
}
}
try {
$room = $this->manager->getRoomByObject('file', $fileId);
} catch (RoomNotFoundException $e) {
if ($share) {
try {
$name = $this->getFileName($share, $fileId);
} catch (NotFoundException $e) {
throw new OCSNotFoundException($this->l->t('File is not shared, or shared but not with the user'));
}
} else {
$name = $groupFolder->getName();
}
$name = $this->roomService->prepareConversationName($name);
$room = $this->roomService->createConversation(Room::PUBLIC_CALL, $name, null, 'file', $fileId);
}
return new DataResponse([
'token' => $room->getToken()
]);
}
/**
* @PublicPage
* @UseSession
*
* Returns the token of the room associated to the file id of the given
* share token.
*
* This is the counterpart of self::getRoomByFileId() for share tokens
* instead of file ids, although both return the same room token if the
* given file id and share token refer to the same file.
*
* If there is no room associated to the file id of the given share token a
* new room is created; the new room is a public room associated with a
* "file" object with the file id of the given share token. Unlike normal
* rooms in which the owner is the user that created the room these are
* special rooms without owner (although self joined users with direct
* access to the file become persistent participants automatically when they
* join until they explicitly leave or no longer have access to the file).
*
* In any case, to create or even get the token of the room, the file must
* be publicly shared (like a link share, for example); an error is returned
* otherwise.
*
* Besides the token of the room this also returns the current user ID and
* display name, if any; this is needed by the Talk sidebar to know the
* actual current user, as the public share page uses the incognito mode and
* thus logged in users as seen as guests.
*
* @param string $shareToken
* @return DataResponse the status code is "200 OK" if a room is returned,
* or "404 Not found" if the given share token was invalid.
*/
public function getRoomByShareToken(string $shareToken): DataResponse {
if ($this->config->getAppValue('spreed', 'conversations_files', '1') !== '1' ||
$this->config->getAppValue('spreed', 'conversations_files_public_shares', '1') !== '1') {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
try {
$share = $this->shareManager->getShareByToken($shareToken);
if ($share->getPassword() !== null) {
$shareId = $this->session->get('public_link_authenticated');
if ($share->getId() !== $shareId) {
throw new ShareNotFound();
}
}
} catch (ShareNotFound $e) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}
try {
if ($share->getNodeType() !== FileInfo::TYPE_FILE) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}
$fileId = (string)$share->getNodeId();
try {
$room = $this->manager->getRoomByObject('file', $fileId);
} catch (RoomNotFoundException $e) {
$name = $share->getNode()->getName();
$name = $this->roomService->prepareConversationName($name);
$room = $this->roomService->createConversation(Room::PUBLIC_CALL, $name, null, 'file', $fileId);
}
} catch (NotFoundException $e) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
}
$this->talkSession->setFileShareTokenForRoom($room->getToken(), $shareToken);
$currentUser = $this->userSession->getUser();
$currentUserId = $currentUser instanceof IUser ? $currentUser->getUID() : '';
$currentUserDisplayName = $currentUser instanceof IUser ? $currentUser->getDisplayName() : '';
return new DataResponse([
'token' => $room->getToken(),
'userId' => $currentUserId,
'userDisplayName' => $currentUserDisplayName,
]);
}
/**
* Returns the name of the file in the share.
*
* If the given share itself is a file its name is returned; otherwise the
* file is looked for in the given shared folder and its name is returned.
*
* @param IShare $share
* @param string $fileId
* @return string
* @throws NotFoundException
*/
private function getFileName(IShare $share, string $fileId): string {
$node = $share->getNode();
if ($node->getType() === FileInfo::TYPE_FILE) {
return $node->getName();
}
$fileById = $node->getById($fileId);
if (empty($fileById)) {
throw new NotFoundException('File not found in share');
}
$file = array_shift($fileById);
return $file->getName();
}
}