diff options
author | Vitor Mattos <vitor@php.rio> | 2022-12-07 22:45:57 -0300 |
---|---|---|
committer | Vitor Mattos <vitor@php.rio> | 2022-12-09 17:02:08 -0300 |
commit | db88acf9beb04ab6bf1b7d423bcad0c5ad21c542 (patch) | |
tree | 37f1ed6fe23081b7132d51f03e1fab4431dac33f | |
parent | edb7df03562c93fdfe65fe66b921498fb1b59968 (diff) |
Toggle call recording status
Signed-off-by: Vitor Mattos <vitor@php.rio>
-rw-r--r-- | appinfo/routes/routesCallController.php | 4 | ||||
-rw-r--r-- | docs/call.md | 28 | ||||
-rw-r--r-- | lib/Controller/CallController.php | 26 | ||||
-rw-r--r-- | lib/Manager.php | 3 | ||||
-rw-r--r-- | lib/Middleware/InjectionMiddleware.php | 14 | ||||
-rw-r--r-- | lib/Migration/Version16000Date20221208013745.php | 55 | ||||
-rw-r--r-- | lib/Model/SelectHelper.php | 1 | ||||
-rw-r--r-- | lib/Room.php | 15 | ||||
-rw-r--r-- | lib/Service/RoomService.php | 36 | ||||
-rw-r--r-- | tests/php/Service/RoomServiceTest.php | 1 |
10 files changed, 181 insertions, 2 deletions
diff --git a/appinfo/routes/routesCallController.php b/appinfo/routes/routesCallController.php index 83632bc9d..11a3f6d62 100644 --- a/appinfo/routes/routesCallController.php +++ b/appinfo/routes/routesCallController.php @@ -40,5 +40,9 @@ return [ ['name' => 'Call#updateCallFlags', 'url' => '/api/{apiVersion}/call/{token}', 'verb' => 'PUT', 'requirements' => $requirements], /** @see \OCA\Talk\Controller\CallController::leaveCall() */ ['name' => 'Call#leaveCall', 'url' => '/api/{apiVersion}/call/{token}', 'verb' => 'DELETE', 'requirements' => $requirements], + /** @see \OCA\Talk\Controller\CallController::startRecording() */ + ['name' => 'Call#startRecording', 'url' => '/api/{apiVersion}/call/{token}/recording', 'verb' => 'POST', 'requirements' => $requirementsWithToken], + /** @see \OCA\Talk\Controller\CallController::stopRecording() */ + ['name' => 'Call#stopRecording', 'url' => '/api/{apiVersion}/call/{token}/recording', 'verb' => 'DELETE', 'requirements' => $requirementsWithToken], ], ]; diff --git a/docs/call.md b/docs/call.md index f0a76c8a8..60781f11e 100644 --- a/docs/call.md +++ b/docs/call.md @@ -102,3 +102,31 @@ + `404 Not Found` When the conversation could not be found for the participant + `404 Not Found` When the user did not join the conversation before + `412 Precondition Failed` When the lobby is active and the user is not a moderator + +## Start call recording + +* Method: `POST` +* Endpoint: `/call/{token}/recording` +* Data: + +| Field | Type | Description | +| ------ | ---- | ----------------------------------------------------- | +| status | int | Type of call recording when 1 is video and 2 is audio | + +* Response: + - Status code: + + `200 OK` + + `400 Bad Request` When the status to start is invalid + + `400 Bad Request` The haven't the capability `recording-v1` + + `412 Precondition Failed` When the lobby is active and the user is not a moderator + +## Stop call recording + +* Method: `DELETE` +* Endpoint: `/call/{token}/recording` + +* Response: + - Status code: + + `200 OK` + + `400 Bad Request` The haven't the capability `recording-v1` + + `412 Precondition Failed` When the lobby is active and the user is not a moderator diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php index 5be4ae148..4cff9abe3 100644 --- a/lib/Controller/CallController.php +++ b/lib/Controller/CallController.php @@ -200,4 +200,30 @@ class CallController extends AEnvironmentAwareController { return new DataResponse(); } + + /** + * @PublicPage + * @RequireCallEnabled + * @RequireParticipant + * @RequireModeratorOrNoLobby + * @RequireCallRecording + */ + public function startRecording(int $status): DataResponse { + if (!$this->roomService->startRecording($this->room, $status)) { + return new DataResponse([], Http::STATUS_BAD_REQUEST); + } + return new DataResponse(); + } + + /** + * @PublicPage + * @RequireCallEnabled + * @RequireParticipant + * @RequireModeratorOrNoLobby + * @RequireCallRecording + */ + public function stopRecording(): DataResponse { + $this->roomService->stopRecording($this->room); + return new DataResponse(); + } } diff --git a/lib/Manager.php b/lib/Manager.php index e038b4485..90f2ce8aa 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -187,7 +187,8 @@ class Manager { (string) $row['object_type'], (string) $row['object_id'], (int) $row['breakout_room_mode'], - (int) $row['breakout_room_status'] + (int) $row['breakout_room_status'], + (int) $row['call_recording'] ); } diff --git a/lib/Middleware/InjectionMiddleware.php b/lib/Middleware/InjectionMiddleware.php index fc8e4bcad..cc73c66c2 100644 --- a/lib/Middleware/InjectionMiddleware.php +++ b/lib/Middleware/InjectionMiddleware.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace OCA\Talk\Middleware; +use OCA\Talk\Config; use OCA\Talk\Controller\AEnvironmentAwareController; use OCA\Talk\Exceptions\ParticipantNotFoundException; use OCA\Talk\Exceptions\PermissionsException; @@ -55,6 +56,7 @@ class InjectionMiddleware extends Middleware { protected TalkSession $talkSession; protected Manager $manager; protected IThrottler $throttler; + protected Config $config; protected ?string $userId; public function __construct(IRequest $request, @@ -63,6 +65,7 @@ class InjectionMiddleware extends Middleware { TalkSession $talkSession, Manager $manager, IThrottler $throttler, + Config $config, ?string $userId) { $this->request = $request; $this->reflector = $reflector; @@ -70,6 +73,7 @@ class InjectionMiddleware extends Middleware { $this->talkSession = $talkSession; $this->manager = $manager; $this->throttler = $throttler; + $this->config = $config; $this->userId = $userId; } @@ -118,6 +122,10 @@ class InjectionMiddleware extends Middleware { $this->checkLobbyState($controller); } + if ($this->reflector->hasAnnotation('RequireCallRecording')) { + $this->checkCallRecording($controller); + } + $requiredPermissions = $this->reflector->getAnnotationParameter('RequirePermissions', 'permissions'); if ($requiredPermissions) { $this->checkPermissions($controller, $requiredPermissions); @@ -247,6 +255,12 @@ class InjectionMiddleware extends Middleware { } } + protected function checkCallRecording(AEnvironmentAwareController $controller): void { + if (!$this->config->isCallRecordingEnabled()) { + throw new ReadOnlyException(); + } + } + /** * @param Controller $controller * @param string $methodName diff --git a/lib/Migration/Version16000Date20221208013745.php b/lib/Migration/Version16000Date20221208013745.php new file mode 100644 index 000000000..45a9ccfc4 --- /dev/null +++ b/lib/Migration/Version16000Date20221208013745.php @@ -0,0 +1,55 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2022 Vitor Mattos <vitor@php.rio> + * + * @author Vitor Mattos <vitor@php.rio> + * + * @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 OCP\DB\ISchemaWrapper; +use OCP\DB\Types; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +class Version16000Date20221208013745 extends SimpleMigrationStep { + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $table = $schema->getTable('talk_rooms'); + if (!$table->hasColumn('call_recording')) { + $table->addColumn('call_recording', Types::INTEGER, [ + 'default' => 0, + ]); + return $schema; + } + return null; + } +} diff --git a/lib/Model/SelectHelper.php b/lib/Model/SelectHelper.php index 755432367..611d86753 100644 --- a/lib/Model/SelectHelper.php +++ b/lib/Model/SelectHelper.php @@ -57,6 +57,7 @@ class SelectHelper { ->addSelect($alias . 'remote_token') ->addSelect($alias . 'breakout_room_mode') ->addSelect($alias . 'breakout_room_status') + ->addSelect($alias . 'call_recording') ->selectAlias($alias . 'id', 'r_id'); } diff --git a/lib/Room.php b/lib/Room.php index df5d88143..7725c4c0b 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -147,6 +147,8 @@ class Room { public const EVENT_AFTER_SET_BREAKOUT_ROOM_MODE = self::class . '::afterSetBreakoutRoomMode'; public const EVENT_BEFORE_SET_BREAKOUT_ROOM_STATUS = self::class . '::beforeSetBreakoutRoomStatus'; public const EVENT_AFTER_SET_BREAKOUT_ROOM_STATUS = self::class . '::afterSetBreakoutRoomStatus'; + public const EVENT_BEFORE_SET_CALL_RECORDING = self::class . '::beforeSetCallRecording'; + public const EVENT_AFTER_SET_CALL_RECORDING = self::class . '::afterSetCallRecording'; public const EVENT_BEFORE_AVATAR_SET = self::class . '::preSetAvatar'; public const EVENT_AFTER_AVATAR_SET = self::class . '::postSetAvatar'; @@ -185,6 +187,7 @@ class Room { private string $objectId; private int $breakoutRoomMode; private int $breakoutRoomStatus; + private int $callRecording; protected ?string $currentUser = null; protected ?Participant $participant = null; @@ -220,7 +223,8 @@ class Room { string $objectType, string $objectId, int $breakoutRoomMode, - int $breakoutRoomStatus) { + int $breakoutRoomStatus, + int $callRecording) { $this->manager = $manager; $this->db = $db; $this->dispatcher = $dispatcher; @@ -253,6 +257,7 @@ class Room { $this->objectId = $objectId; $this->breakoutRoomMode = $breakoutRoomMode; $this->breakoutRoomStatus = $breakoutRoomStatus; + $this->callRecording = $callRecording; } public function getId(): int { @@ -632,4 +637,12 @@ class Room { public function setBreakoutRoomStatus(int $status): void { $this->breakoutRoomStatus = $status; } + + public function getCallRecording(): int { + return $this->breakoutRoomStatus; + } + + public function setCallRecording(int $status): void { + $this->callRecording = $status; + } } diff --git a/lib/Service/RoomService.php b/lib/Service/RoomService.php index 08cb8ef2f..26b8eb185 100644 --- a/lib/Service/RoomService.php +++ b/lib/Service/RoomService.php @@ -362,6 +362,42 @@ class RoomService { return true; } + public function startRecording(Room $room, $status): bool { + if (!in_array($status, [1, 2])) { + return false; + } + return $this->setCallRecording($room, $status); + } + + public function stopRecording(Room $room): bool { + return $this->setCallRecording($room); + } + + /** + * Undocumented function + * + * @param Room $room + * @param integer $status 0 none|1 video|2 audio + */ + public function setCallRecording(Room $room, int $status = 0): bool { + if (!in_array($status, [0, 1, 2])) { + return false; + } + + $oldStatus = $room->getCallRecording(); + $event = new ModifyRoomEvent($room, 'callRecording', $status, $oldStatus); + $this->dispatcher->dispatch(Room::EVENT_BEFORE_SET_CALL_RECORDING, $event); + + $update = $this->db->getQueryBuilder(); + $update->update('talk_rooms') + ->set('call_recording', $update->createNamedParameter($status, IQueryBuilder::PARAM_INT)) + ->where($update->expr()->eq('id', $update->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))); + $update->executeStatement(); + + $this->dispatcher->dispatch(Room::EVENT_AFTER_SET_CALL_RECORDING, $event); + return true; + } + /** * @param Room $room * @param int $newType Currently it is only allowed to change between `Room::TYPE_GROUP` and `Room::TYPE_PUBLIC` diff --git a/tests/php/Service/RoomServiceTest.php b/tests/php/Service/RoomServiceTest.php index d71502929..61798485f 100644 --- a/tests/php/Service/RoomServiceTest.php +++ b/tests/php/Service/RoomServiceTest.php @@ -386,6 +386,7 @@ class RoomServiceTest extends TestCase { '', '', 0, + 0, 0 ); |