diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php index f4ef947bcd4..6e5021bb21a 100644 --- a/lib/Controller/CallController.php +++ b/lib/Controller/CallController.php @@ -162,7 +162,7 @@ public function joinCall(?int $flags = null, ?int $forcePermissions = null, bool * Ring an attendee * * @param int $attendeeId ID of the attendee to ring - * @return DataResponse, array{}> + * @return DataResponse, array{}>|DataResponse * * 200: Attendee rang successfully * 400: Ringing attendee is not possible @@ -183,8 +183,8 @@ public function ringAttendee(int $attendeeId): DataResponse { try { $this->participantService->sendCallNotificationForAttendee($this->room, $this->participant, $attendeeId); - } catch (\InvalidArgumentException) { - return new DataResponse([], Http::STATUS_BAD_REQUEST); + } catch (\InvalidArgumentException $e) { + return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST); } catch (DoesNotExistException) { return new DataResponse([], Http::STATUS_NOT_FOUND); } diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 8c881033455..41079d67428 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -71,6 +71,8 @@ use OCP\IUserManager; use OCP\Security\ISecureRandom; use OCP\Server; +use OCP\UserStatus\IManager as IUserStatusManager; +use OCP\UserStatus\IUserStatus; class ParticipantService { @@ -95,6 +97,7 @@ public function __construct( private BackendNotifier $backendNotifier, private ITimeFactory $timeFactory, private ICacheFactory $cacheFactory, + private IUserStatusManager $userStatusManager, ) { } @@ -1181,6 +1184,11 @@ public function sendCallNotificationForAttendee(Room $room, Participant $current throw new DoesNotExistException('Room mismatch'); } + $userStatus = $this->userStatusManager->getUserStatuses([$attendee->getActorId()]); + if (isset($userStatus[$attendee->getActorId()]) && $userStatus[$attendee->getActorId()]->getStatus() === IUserStatus::DND) { + throw new \InvalidArgumentException('status'); + } + $sessions = $this->sessionMapper->findByAttendeeId($targetAttendeeId); foreach ($sessions as $session) { if ($session->getInCall() !== Participant::FLAG_DISCONNECTED) { diff --git a/openapi-full.json b/openapi-full.json index 8aec51d898f..f1a25c4f448 100644 --- a/openapi-full.json +++ b/openapi-full.json @@ -4045,8 +4045,8 @@ } } }, - "400": { - "description": "Ringing attendee is not possible", + "404": { + "description": "Attendee could not be found", "content": { "application/json": { "schema": { @@ -4073,8 +4073,8 @@ } } }, - "404": { - "description": "Attendee could not be found", + "400": { + "description": "Ringing attendee is not possible", "content": { "application/json": { "schema": { @@ -4093,7 +4093,17 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": {} + "data": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } } } } diff --git a/openapi.json b/openapi.json index a0d74b9d13c..61cf9f21f50 100644 --- a/openapi.json +++ b/openapi.json @@ -3932,8 +3932,8 @@ } } }, - "400": { - "description": "Ringing attendee is not possible", + "404": { + "description": "Attendee could not be found", "content": { "application/json": { "schema": { @@ -3960,8 +3960,8 @@ } } }, - "404": { - "description": "Attendee could not be found", + "400": { + "description": "Ringing attendee is not possible", "content": { "application/json": { "schema": { @@ -3980,7 +3980,17 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": {} + "data": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } } } } diff --git a/src/types/openapi/openapi-full.ts b/src/types/openapi/openapi-full.ts index 66bd34df612..ddf13c64a98 100644 --- a/src/types/openapi/openapi-full.ts +++ b/src/types/openapi/openapi-full.ts @@ -1796,7 +1796,9 @@ export type operations = { "application/json": { ocs: { meta: components["schemas"]["OCSMeta"]; - data: unknown; + data: { + error: string; + }; }; }; }; diff --git a/src/types/openapi/openapi.ts b/src/types/openapi/openapi.ts index 86e715f60d2..8370ecec756 100644 --- a/src/types/openapi/openapi.ts +++ b/src/types/openapi/openapi.ts @@ -1619,7 +1619,9 @@ export type operations = { "application/json": { ocs: { meta: components["schemas"]["OCSMeta"]; - data: unknown; + data: { + error: string; + }; }; }; }; diff --git a/tests/integration/features/callapi/notifications.feature b/tests/integration/features/callapi/notifications.feature index 47fa7d56408..27bb24069bc 100644 --- a/tests/integration/features/callapi/notifications.feature +++ b/tests/integration/features/callapi/notifications.feature @@ -76,6 +76,24 @@ Feature: callapi/notifications Then user "participant2" has the following notifications | app | object_type | object_id | subject | | spreed | call | room | A group call has started in room | + + Scenario: Calling an attendee that is in DND throws an error 'status' message with 400 + When user "participant1" creates room "room" (v4) + | roomType | 2 | + | roomName | room | + And user "participant1" adds user "participant2" to room "room" with 200 (v4) + Given user "participant1" joins room "room" with 200 (v4) + Given user "participant2" joins room "room" with 200 (v4) + Given user "participant1" loads attendees attendee ids in room "room" (v4) + And user "participant2" sets status to "dnd" with 200 (v4) + Given user "participant1" joins call "room" with 200 (v4) + | silent | true | + Then user "participant2" has the following notifications + | app | object_type | object_id | subject | + Given user "participant1" pings user "participant2" to join call "room" with 400 (v4) + Then the request is rejected with the following error message + | status | message | + | 400 | status | Scenario: Lobby: No call notification sent for users that are blocked by the lobby Given user "participant1" creates room "room" (v4) diff --git a/tests/php/Service/ParticipantServiceTest.php b/tests/php/Service/ParticipantServiceTest.php index ca75f26b7b5..9a68aae11f1 100644 --- a/tests/php/Service/ParticipantServiceTest.php +++ b/tests/php/Service/ParticipantServiceTest.php @@ -29,6 +29,7 @@ use OCP\IGroupManager; use OCP\IUserManager; use OCP\Security\ISecureRandom; +use OCP\UserStatus\IManager; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; @@ -50,6 +51,7 @@ class ParticipantServiceTest extends TestCase { protected BackendNotifier&MockObject $federationBackendNotifier; protected ITimeFactory&MockObject $time; protected ICacheFactory&MockObject $cacheFactory; + protected IManager&MockObject $userStatusManager; private ?ParticipantService $service = null; @@ -70,6 +72,7 @@ public function setUp(): void { $this->federationBackendNotifier = $this->createMock(BackendNotifier::class); $this->time = $this->createMock(ITimeFactory::class); $this->cacheFactory = $this->createMock(ICacheFactory::class); + $this->userStatusManager = $this->createMock(IManager::class); $this->service = new ParticipantService( $this->serverConfig, $this->talkConfig, @@ -85,7 +88,8 @@ public function setUp(): void { $this->membershipService, $this->federationBackendNotifier, $this->time, - $this->cacheFactory + $this->cacheFactory, + $this->userStatusManager, ); }