Files
f7_talk/tests/php/Recording/BackendNotifierTest.php
T
glb_adm 01acfa3b40
Type checking / changes (push) Has been cancelled
Type checking / test (push) Has been cancelled
Type checking / typescript-summary (push) Has been cancelled
Node tests / changes (push) Has been cancelled
Node tests / test (push) Has been cancelled
Node tests / test-summary (push) Has been cancelled
UPSTREAM BASELINE: nextcloud/spreed v22.0.12 (без изменений)
Источник: https://github.com/nextcloud/spreed/archive/refs/tags/v22.0.12.tar.gz
С этого коммита ветка официального Nextcloud Talk отрезана (решение владельца 2026-07-06).
Все дальнейшие изменения — только наши; версии релизов: 22.0.12-f7.N.
2026-07-06 14:07:50 +00:00

253 lines
7.3 KiB
PHP

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Talk\Tests\php\Recording;
use OCA\Talk\Chat\CommentsManager;
use OCA\Talk\Config;
use OCA\Talk\Federation\Authenticator;
use OCA\Talk\Manager;
use OCA\Talk\Model\AttendeeMapper;
use OCA\Talk\Model\SessionMapper;
use OCA\Talk\Recording\BackendNotifier;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
use OCA\Talk\Service\RoomService;
use OCA\Talk\TalkSession;
use OCP\App\IAppManager;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Config\IUserConfig;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Security\IHasher;
use OCP\Security\ISecureRandom;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
class CustomBackendNotifier extends BackendNotifier {
private array $requests = [];
public function getRequests(): array {
return $this->requests;
}
public function clearRequests() {
$this->requests = [];
}
protected function doRequest(string $url, array $params, int $retries = 3): void {
$this->requests[] = [
'url' => $url,
'params' => $params,
];
}
}
#[Group('DB')]
class BackendNotifierTest extends TestCase {
protected IURLGenerator&MockObject $urlGenerator;
protected ParticipantService $participantService;
protected ?CustomBackendNotifier $backendNotifier = null;
protected ?Config $config = null;
protected ?ISecureRandom $secureRandom = null;
protected ?Manager $manager = null;
protected ?string $recordingSecret = null;
protected ?string $baseUrl = null;
public function setUp(): void {
parent::setUp();
$config = \OCP\Server::get(IConfig::class);
$this->recordingSecret = 'the-recording-secret';
$this->baseUrl = 'https://localhost/recording';
$config->setAppValue('spreed', 'recording_servers', json_encode([
'secret' => $this->recordingSecret,
'servers' => [
[
'server' => $this->baseUrl,
],
],
]));
$this->secureRandom = \OCP\Server::get(ISecureRandom::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$appConfig = $this->createMock(IAppConfig::class);
$groupManager = $this->createMock(IGroupManager::class);
$userManager = $this->createMock(IUserManager::class);
$timeFactory = $this->createMock(ITimeFactory::class);
$dispatcher = \OCP\Server::get(IEventDispatcher::class);
$this->config = new Config($config, $appConfig, $this->createMock(IUserConfig::class), $this->secureRandom, $groupManager, $userManager, $this->urlGenerator, $timeFactory, $dispatcher);
$this->recreateBackendNotifier();
$this->participantService = \OCP\Server::get(ParticipantService::class);
$dbConnection = \OCP\Server::get(IDBConnection::class);
$this->manager = new Manager(
$dbConnection,
$config,
$this->config,
\OCP\Server::get(IAppManager::class),
\OCP\Server::get(AttendeeMapper::class),
\OCP\Server::get(SessionMapper::class),
$this->participantService,
$this->secureRandom,
$this->createMock(IUserManager::class),
$groupManager,
$this->createMock(CommentsManager::class),
$this->createMock(TalkSession::class),
$dispatcher,
$timeFactory,
$this->createMock(IHasher::class),
$this->createMock(IL10N::class),
$this->createMock(Authenticator::class),
);
}
public function tearDown(): void {
$config = \OCP\Server::get(IConfig::class);
$config->deleteAppValue('spreed', 'recording_servers');
parent::tearDown();
}
private function recreateBackendNotifier() {
$this->backendNotifier = new CustomBackendNotifier(
$this->config,
$this->createMock(LoggerInterface::class),
$this->createMock(IClientService::class),
$this->secureRandom,
$this->urlGenerator,
);
}
private function calculateBackendChecksum($data, $random) {
if (empty($random) || strlen($random) < 32) {
return false;
}
return hash_hmac('sha256', $random . $data, $this->recordingSecret);
}
private function validateBackendRequest($expectedUrl, $request) {
$this->assertTrue(isset($request));
$this->assertEquals($expectedUrl, $request['url']);
$headers = $request['params']['headers'];
$this->assertEquals('application/json', $headers['Content-Type']);
$random = $headers['Talk-Recording-Random'];
$checksum = $headers['Talk-Recording-Checksum'];
$body = $request['params']['body'];
$this->assertEquals($this->calculateBackendChecksum($body, $random), $checksum);
return $body;
}
private function assertMessageWasSent(Room $room, array $message): void {
$expectedUrl = $this->baseUrl . '/api/v1/room/' . $room->getToken();
$requests = $this->backendNotifier->getRequests();
$requests = array_filter($requests, function ($request) use ($expectedUrl) {
return $request['url'] === $expectedUrl;
});
$bodies = array_map(function ($request) use ($expectedUrl) {
return json_decode($this->validateBackendRequest($expectedUrl, $request), true);
}, $requests);
$bodies = array_filter($bodies, function (array $body) use ($message) {
return $body['type'] === $message['type'];
});
$this->assertContainsEquals($message, $bodies, json_encode($bodies, JSON_PRETTY_PRINT));
}
public function testStart(): void {
$userId = 'testUser';
/** @var IUser&MockObject $testUser */
$testUser = $this->createMock(IUser::class);
$testUser->expects($this->any())
->method('getUID')
->willReturn($userId);
$roomService = $this->createMock(RoomService::class);
$roomService->method('verifyPassword')
->willReturn(['result' => true, 'url' => '']);
$room = $this->manager->createRoom(Room::TYPE_PUBLIC);
$this->participantService->addUsers($room, [[
'actorType' => 'users',
'actorId' => $userId,
]]);
$participant = $this->participantService->joinRoom($roomService, $room, $testUser, '');
$this->backendNotifier->start($room, Room::RECORDING_VIDEO, 'participant1', $participant);
$this->assertMessageWasSent($room, [
'type' => 'start',
'start' => [
'status' => Room::RECORDING_VIDEO,
'owner' => 'participant1',
'actor' => [
'type' => 'users',
'id' => $userId,
],
],
]);
}
public function testStop(): void {
$userId = 'testUser';
/** @var IUser&MockObject $testUser */
$testUser = $this->createMock(IUser::class);
$testUser->expects($this->any())
->method('getUID')
->willReturn($userId);
$roomService = $this->createMock(RoomService::class);
$roomService->method('verifyPassword')
->willReturn(['result' => true, 'url' => '']);
$room = $this->manager->createRoom(Room::TYPE_PUBLIC);
$this->participantService->addUsers($room, [[
'actorType' => 'users',
'actorId' => $userId,
]]);
$participant = $this->participantService->joinRoom($roomService, $room, $testUser, '');
$this->backendNotifier->stop($room, $participant);
$this->assertMessageWasSent($room, [
'type' => 'stop',
'stop' => [
'actor' => [
'type' => 'users',
'id' => $userId,
],
],
]);
$this->backendNotifier->stop($room);
$this->assertMessageWasSent($room, [
'type' => 'stop',
'stop' => [
],
]);
}
}