diff --git a/lib/BigBlueButton/API.php b/lib/BigBlueButton/API.php index 2176ca3..90e1f69 100644 --- a/lib/BigBlueButton/API.php +++ b/lib/BigBlueButton/API.php @@ -206,7 +206,7 @@ class API { if ($presentation !== null && $presentation->isValid()) { /** @psalm-suppress InvalidArgument */ - $createMeetingParams->addPresentation($presentation->getUrl(), null, $presentation->getFilename()); + $createMeetingParams->addPresentation($presentation->generateUrl(), null, $presentation->getFilename()); } if ($room->access === Room::ACCESS_WAITING_ROOM || $room->access === Room::ACCESS_WAITING_ROOM_ALL) { diff --git a/lib/BigBlueButton/Presentation.php b/lib/BigBlueButton/Presentation.php index 39e629b..b473def 100644 --- a/lib/BigBlueButton/Presentation.php +++ b/lib/BigBlueButton/Presentation.php @@ -2,14 +2,26 @@ namespace OCA\BigBlueButton\BigBlueButton; +use OCP\Files\Storage\IStorage; + class Presentation { private $url; private $filename; - public function __construct(string $url, string $filename) { - $this->url = $url; - $this->filename = preg_replace('/[^\x20-\x7E]+/','#', $filename); + private $path; + + /** @var IStorage */ + private $storage; + + public function __construct(string $path, IStorage $storage) { + $this->storage = $storage; + $this->path = preg_replace('/^\//', '', $path); + $this->filename = preg_replace('/[^\x20-\x7E]+/','#', $path); + } + + public function generateUrl(): string { + return $this->storage->getDirectDownload($this->path); } public function getUrl(): string { @@ -21,6 +33,6 @@ class Presentation { } public function isValid(): bool { - return !empty($this->url) && !empty($this->filename); + return !empty($this->filename); } } diff --git a/lib/Controller/JoinController.php b/lib/Controller/JoinController.php index 1a56a89..4e5387d 100644 --- a/lib/Controller/JoinController.php +++ b/lib/Controller/JoinController.php @@ -14,11 +14,13 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\BackgroundJob\IJobList; +use OCP\Files\Storage\IStorage; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUserSession; -class JoinController extends Controller { +class JoinController extends Controller +{ /** @var string */ protected $token; @@ -43,6 +45,9 @@ class JoinController extends Controller { /** @var IJobList */ private $jobList; + /** @var IStorage */ + private $storage; + public function __construct( string $appName, IRequest $request, @@ -51,7 +56,8 @@ class JoinController extends Controller { IUserSession $userSession, API $api, Permission $permission, - IJobList $jobList + IJobList $jobList, + IStorage $storage ) { parent::__construct($appName, $request); @@ -61,14 +67,17 @@ class JoinController extends Controller { $this->api = $api; $this->permission = $permission; $this->jobList = $jobList; + $this->storage = $storage; } - public function setToken(string $token): void { + public function setToken(string $token): void + { $this->token = $token; $this->room = null; } - public function isValidToken(): bool { + public function isValidToken(): bool + { $room = $this->getRoom(); return $room !== null; @@ -81,7 +90,8 @@ class JoinController extends Controller { * * @return RedirectResponse|TemplateResponse */ - public function index($displayname, $u = '', $filename = '', $password = '') { + public function index($displayname, $u = '', $filename = '', $password = '') + { $room = $this->getRoom(); if ($room === null) { @@ -108,7 +118,11 @@ class JoinController extends Controller { } if ($this->permission->isAdmin($room, $userId)) { - $presentation = new Presentation($u, $filename); + $presentation = new Presentation($filename, $this->storage); + } + + if (!$room->running && $presentation === null) { + $presentation = new Presentation($room->presentationPath, $this->storage); } } elseif ($room->access === Room::ACCESS_INTERNAL || $room->access === Room::ACCESS_INTERNAL_RESTRICTED) { return new RedirectResponse($this->getLoginUrl()); @@ -138,7 +152,7 @@ class JoinController extends Controller { $this->markAsRunning($room); - \OCP\Util::addHeader('meta', ['http-equiv' => 'refresh', 'content' => '3;url='.$joinUrl]); + \OCP\Util::addHeader('meta', ['http-equiv' => 'refresh', 'content' => '3;url=' . $joinUrl]); return new TemplateResponse($this->appName, 'forward', [ 'room' => $room->name, @@ -146,7 +160,8 @@ class JoinController extends Controller { ], 'guest'); } - private function getRoom(): ?Room { + private function getRoom(): ?Room + { if ($this->room === null) { $this->room = $this->service->findByUid($this->token); } @@ -154,7 +169,8 @@ class JoinController extends Controller { return $this->room; } - private function getLoginUrl(): string { + private function getLoginUrl(): string + { return $this->urlGenerator->linkToRoute('core.login.showLoginForm', [ 'redirect_url' => $this->urlGenerator->linkToRoute( 'bbb.join.index', @@ -163,7 +179,8 @@ class JoinController extends Controller { ]); } - private function markAsRunning(Room $room) { + private function markAsRunning(Room $room) + { if (!$room->running) { $this->service->updateRunning($room->getId(), true); } diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index a5252c5..37497fc 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -13,7 +13,8 @@ use OCP\IGroupManager; use OCP\IRequest; use OCP\IUserManager; -class RoomController extends Controller { +class RoomController extends Controller +{ /** @var RoomService */ private $service; @@ -56,7 +57,8 @@ class RoomController extends Controller { /** * @NoAdminRequired */ - public function index(): DataResponse { + public function index(): DataResponse + { $user = $this->userManager->get($this->userId); $groupIds = $this->groupManager->getUserGroupIds($user); $circleIds = $this->circleHelper->getCircleIds($this->userId); @@ -119,7 +121,9 @@ class RoomController extends Controller { bool $listenOnly, bool $mediaCheck, bool $cleanLayout, - bool $joinMuted + bool $joinMuted, + string $presentationUserId, + string $presentationPath ): DataResponse { $room = $this->service->find($id); @@ -142,15 +146,28 @@ class RoomController extends Controller { return new DataResponse(['message' => 'Access type not allowed.'], Http::STATUS_BAD_REQUEST); } - return $this->handleNotFound(function () use ($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator, $moderatorToken, $listenOnly, $mediaCheck, $cleanLayout, $joinMuted) { - return $this->service->update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator, $moderatorToken, $listenOnly, $mediaCheck, $cleanLayout, $joinMuted); + if ($presentationUserId != '' && $presentationUserId != $room->getPresentationUserId()) { + return new DataResponse(['message' => 'Not allowed to change to another user.'], Http::STATUS_BAD_REQUEST); + } + + if ($presentationUserId === '') { + $presentationUserId = $this->userId; + } + + if ($presentationUserId != $this->userId && $presentationPath != $room->getPresentationPath()) { + return new DataResponse(['message' => 'Not allowed to choose path of another user.'], Http::STATUS_BAD_REQUEST); + } + + return $this->handleNotFound(function () use ($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator, $moderatorToken, $listenOnly, $mediaCheck, $cleanLayout, $joinMuted, $presentationUserId, $presentationPath) { + return $this->service->update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator, $moderatorToken, $listenOnly, $mediaCheck, $cleanLayout, $joinMuted, $presentationUserId, $presentationPath); }); } /** * @NoAdminRequired */ - public function destroy(int $id): DataResponse { + public function destroy(int $id): DataResponse + { $room = $this->service->find($id); if (!$this->permission->isAdmin($room, $this->userId)) { diff --git a/lib/Db/Room.php b/lib/Db/Room.php index 7fb2816..b59ec1a 100644 --- a/lib/Db/Room.php +++ b/lib/Db/Room.php @@ -74,6 +74,8 @@ class Room extends Entity implements JsonSerializable { public $cleanLayout; public $joinMuted; public $running; + public $presentationUserId; + public $presentationPath; public function __construct() { $this->addType('maxParticipants', 'integer'); @@ -108,6 +110,8 @@ class Room extends Entity implements JsonSerializable { 'cleanLayout' => boolval($this->cleanLayout), 'joinMuted' => boolval($this->joinMuted), 'running' => boolval($this->running), + 'presentationUserId' => $this->presentationUserId, + 'presentationPath' => $this->presentationPath, ]; } } diff --git a/lib/Service/RoomService.php b/lib/Service/RoomService.php index d8e42b6..6117f7f 100644 --- a/lib/Service/RoomService.php +++ b/lib/Service/RoomService.php @@ -103,6 +103,8 @@ class RoomService { $room->setMediaCheck($mediaCheck); $room->setCleanLayout(false); $room->setJoinMuted(false); + $room->setPresentationUserId(''); + $room->setPresentationPath(''); if ($access === Room::ACCESS_PASSWORD) { $room->setPassword($this->humanReadableRandom(8)); @@ -133,7 +135,9 @@ class RoomService { bool $listenOnly, bool $mediaCheck, bool $cleanLayout, - bool $joinMuted) { + bool $joinMuted, + string $presentationUserId, + string $presentationPath) { try { $room = $this->mapper->find($id); @@ -156,6 +160,8 @@ class RoomService { $room->setMediaCheck($mediaCheck); $room->setCleanLayout($cleanLayout); $room->setJoinMuted($joinMuted); + $room->setPresentationUserId($presentationUserId); + $room->setPresentationPath($presentationPath); return $this->mapper->update($room); } catch (Exception $e) {