зеркало из https://github.com/nextcloud/spreed.git
Split joining a room and joining a call API wise
Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Родитель
d83c3d250e
Коммит
eae71a3977
|
@ -38,7 +38,7 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m
|
|||
<bugs>https://github.com/nextcloud/spreed/issues</bugs>
|
||||
<repository type="git">https://github.com/nextcloud/spreed.git</repository>
|
||||
|
||||
<version>2.1.9</version>
|
||||
<version>2.1.10</version>
|
||||
|
||||
<dependencies>
|
||||
<nextcloud min-version="13" max-version="13" />
|
||||
|
|
|
@ -221,6 +221,24 @@ return [
|
|||
'token' => '^[a-z0-9]{4,30}$',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'Room#joinRoom',
|
||||
'url' => '/api/{apiVersion}/room/{token}/participants/active',
|
||||
'verb' => 'POST',
|
||||
'requirements' => [
|
||||
'apiVersion' => 'v1',
|
||||
'token' => '^[a-z0-9]{4,30}$',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'Room#exitRoom',
|
||||
'url' => '/api/{apiVersion}/room/{token}/participants/active',
|
||||
'verb' => 'DELETE',
|
||||
'requirements' => [
|
||||
'apiVersion' => 'v1',
|
||||
'token' => '^[a-z0-9]{4,30}$',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'Room#promoteModerator',
|
||||
'url' => '/api/{apiVersion}/room/{token}/moderators',
|
||||
|
|
|
@ -278,6 +278,38 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
|
|||
* Method: `DELETE`
|
||||
* Endpoint: `/room/{token}/participants/self`
|
||||
|
||||
* Response:
|
||||
- Header:
|
||||
+ `200 OK`
|
||||
+ `404 Not Found` When the room could not be found for the participant
|
||||
|
||||
### Join a room (available for call and chat)
|
||||
|
||||
* Method: `POST`
|
||||
* Endpoint: `/room/{token}/participants/active`
|
||||
* Data:
|
||||
|
||||
field | type | Description
|
||||
------|------|------------
|
||||
`password` | string | Optional: Password is only required for users which are of type `4` or `5` and only when the room has `hasPassword` set to true.
|
||||
|
||||
* Response:
|
||||
- Header:
|
||||
+ `200 OK`
|
||||
+ `403 Forbidden` When the password is required and didn't match
|
||||
+ `404 Not Found` When the room could not be found for the participant
|
||||
|
||||
- Data:
|
||||
|
||||
field | type | Description
|
||||
------|------|------------
|
||||
`sessionId` | string | 512 character long string
|
||||
|
||||
### Leave a room (not available for call and chat anymore)
|
||||
|
||||
* Method: `DELETE`
|
||||
* Endpoint: `/room/{token}/participants/active`
|
||||
|
||||
* Response:
|
||||
- Header:
|
||||
+ `200 OK`
|
||||
|
@ -347,24 +379,12 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
|
|||
|
||||
* Method: `POST`
|
||||
* Endpoint: `/call/{token}`
|
||||
* Data:
|
||||
|
||||
field | type | Description
|
||||
------|------|------------
|
||||
`password` | string | Optional: Password is only required for users which are of type `4` or `5` and only when the room has `hasPassword` set to true.
|
||||
|
||||
* Response:
|
||||
- Header:
|
||||
+ `200 OK`
|
||||
+ `403 Forbidden` When the password is required and didn't match
|
||||
+ `404 Not Found` When the room could not be found for the participant
|
||||
|
||||
- Data:
|
||||
|
||||
field | type | Description
|
||||
------|------|------------
|
||||
`sessionId` | string | 512 character long string
|
||||
|
||||
### Send ping to keep the call alive
|
||||
|
||||
* Method: `POST`
|
||||
|
@ -375,7 +395,7 @@ Base endpoint is: `/ocs/v2.php/apps/spreed/api/v1`
|
|||
+ `200 OK`
|
||||
+ `404 Not Found` When the room could not be found for the participant
|
||||
|
||||
### Leave a call (but staying in the room for future calls)
|
||||
### Leave a call (but staying in the room for future calls and chat)
|
||||
|
||||
* Method: `DELETE`
|
||||
* Endpoint: `/call/{token}`
|
||||
|
|
|
@ -87,6 +87,8 @@ class Application extends App {
|
|||
$dispatcher->addListener(Room::class . '::postRemoveUser', $listener);
|
||||
$dispatcher->addListener(Room::class . '::postRemoveBySession', $listener);
|
||||
$dispatcher->addListener(Room::class . '::postUserDisconnectRoom', $listener);
|
||||
$dispatcher->addListener(Room::class . '::postSessionJoinCall', $listener);
|
||||
$dispatcher->addListener(Room::class . '::postSessionLeaveCall', $listener);
|
||||
|
||||
$dispatcher->addListener(Room::class . '::postAddUsers', function(GenericEvent $event) {
|
||||
/** @var BackendNotifier $notifier */
|
||||
|
|
|
@ -106,8 +106,8 @@ class CallController extends OCSController {
|
|||
$participants = $room->getParticipants(time() - 30);
|
||||
$result = [];
|
||||
foreach ($participants['users'] as $participant => $data) {
|
||||
if ($data['sessionId'] === '0') {
|
||||
// User left the room
|
||||
if ($data['sessionId'] === '0' || !$data['inCall']) {
|
||||
// User is not active in call
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -136,38 +136,36 @@ class CallController extends OCSController {
|
|||
* @UseSession
|
||||
*
|
||||
* @param string $token
|
||||
* @param string $password
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function joinCall($token, $password) {
|
||||
public function joinCall($token) {
|
||||
try {
|
||||
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
|
||||
} catch (RoomNotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->userId !== null) {
|
||||
$sessionIds = $this->manager->getSessionIdsForUser($this->userId);
|
||||
$newSessionId = $room->enterRoomAsUser($this->userId, $password, $this->session->get('spreed-password') === $room->getToken());
|
||||
|
||||
if (!empty($sessionIds)) {
|
||||
$this->messages->deleteMessages($sessionIds);
|
||||
}
|
||||
} else {
|
||||
$newSessionId = $room->enterRoomAsGuest($password, $this->session->get('spreed-password') === $room->getToken());
|
||||
if ($this->userId !== null) {
|
||||
if (!$this->session->exists('spreed-session')) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
$sessionId = $this->session->get('spreed-session');
|
||||
} else {
|
||||
try {
|
||||
$participant = $room->getParticipant($this->userId);
|
||||
} catch (ParticipantNotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
$sessionId = $participant->getSessionId();
|
||||
if ($sessionId === '0') {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
} catch (InvalidPasswordException $e) {
|
||||
return new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
|
||||
$this->session->remove('spreed-password');
|
||||
$this->session->set('spreed-session', $newSessionId);
|
||||
$room->ping($this->userId, $newSessionId, time());
|
||||
$room->changeInCall($sessionId, true);
|
||||
|
||||
return new DataResponse([
|
||||
'sessionId' => $newSessionId,
|
||||
]);
|
||||
return new DataResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,23 +199,32 @@ class CallController extends OCSController {
|
|||
* @return DataResponse
|
||||
*/
|
||||
public function leaveCall($token) {
|
||||
$sessionId = $this->session->get('spreed-session');
|
||||
$this->session->remove('spreed-session');
|
||||
|
||||
try {
|
||||
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
|
||||
|
||||
if ($this->userId === null) {
|
||||
$participant = $room->getParticipantBySession($sessionId);
|
||||
$room->removeParticipantBySession($participant);
|
||||
} else {
|
||||
$participant = $room->getParticipant($this->userId);
|
||||
$room->disconnectUserFromAllRooms($participant->getUser());
|
||||
}
|
||||
} catch (RoomNotFoundException $e) {
|
||||
} catch (ParticipantNotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($this->userId !== null) {
|
||||
if (!$this->session->exists('spreed-session')) {
|
||||
return new DataResponse();
|
||||
}
|
||||
$sessionId = $this->session->get('spreed-session');
|
||||
} else {
|
||||
try {
|
||||
$participant = $room->getParticipant($this->userId);
|
||||
} catch (ParticipantNotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
$sessionId = $participant->getSessionId();
|
||||
if ($sessionId === '0') {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
$room->changeInCall($sessionId, false);
|
||||
|
||||
return new DataResponse();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,11 +25,13 @@
|
|||
|
||||
namespace OCA\Spreed\Controller;
|
||||
|
||||
use OCA\Spreed\Exceptions\InvalidPasswordException;
|
||||
use OCA\Spreed\Exceptions\ParticipantNotFoundException;
|
||||
use OCA\Spreed\Exceptions\RoomNotFoundException;
|
||||
use OCA\Spreed\Manager;
|
||||
use OCA\Spreed\Participant;
|
||||
use OCA\Spreed\Room;
|
||||
use OCA\Spreed\Signaling\Messages;
|
||||
use OCP\Activity\IManager as IActivityManager;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
|
@ -57,6 +59,8 @@ class RoomController extends OCSController {
|
|||
private $logger;
|
||||
/** @var Manager */
|
||||
private $manager;
|
||||
/** @var Messages */
|
||||
private $messages;
|
||||
/** @var INotificationManager */
|
||||
private $notificationManager;
|
||||
/** @var IActivityManager */
|
||||
|
@ -73,6 +77,7 @@ class RoomController extends OCSController {
|
|||
* @param IGroupManager $groupManager
|
||||
* @param ILogger $logger
|
||||
* @param Manager $manager
|
||||
* @param Messages $messages
|
||||
* @param INotificationManager $notificationManager
|
||||
* @param IActivityManager $activityManager
|
||||
* @param IL10N $l10n
|
||||
|
@ -85,6 +90,7 @@ class RoomController extends OCSController {
|
|||
IGroupManager $groupManager,
|
||||
ILogger $logger,
|
||||
Manager $manager,
|
||||
Messages $messages,
|
||||
INotificationManager $notificationManager,
|
||||
IActivityManager $activityManager,
|
||||
IL10N $l10n) {
|
||||
|
@ -95,6 +101,7 @@ class RoomController extends OCSController {
|
|||
$this->groupManager = $groupManager;
|
||||
$this->logger = $logger;
|
||||
$this->manager = $manager;
|
||||
$this->messages = $messages;
|
||||
$this->notificationManager = $notificationManager;
|
||||
$this->activityManager = $activityManager;
|
||||
$this->l10n = $l10n;
|
||||
|
@ -158,8 +165,10 @@ class RoomController extends OCSController {
|
|||
|
||||
if ($participant instanceof Participant) {
|
||||
$participantType = $participant->getParticipantType();
|
||||
$participantInCall = $participant->isInCall();
|
||||
} else {
|
||||
$participantType = Participant::GUEST;
|
||||
$participantInCall = false;
|
||||
}
|
||||
|
||||
$roomData = [
|
||||
|
@ -169,6 +178,7 @@ class RoomController extends OCSController {
|
|||
'name' => $room->getName(),
|
||||
'displayName' => $room->getName(),
|
||||
'participantType' => $participantType,
|
||||
'participantInCall' => $participantInCall,
|
||||
'count' => $room->getNumberOfParticipants(time() - 30),
|
||||
'hasPassword' => $room->hasPassword(),
|
||||
];
|
||||
|
@ -766,6 +776,73 @@ class RoomController extends OCSController {
|
|||
return new DataResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @PublicPage
|
||||
* @UseSession
|
||||
*
|
||||
* @param string $token
|
||||
* @param string $password
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function joinRoom($token, $password) {
|
||||
try {
|
||||
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
|
||||
} catch (RoomNotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->userId !== null) {
|
||||
$sessionIds = $this->manager->getSessionIdsForUser($this->userId);
|
||||
$newSessionId = $room->enterRoomAsUser($this->userId, $password, $this->session->get('spreed-password') === $room->getToken());
|
||||
|
||||
if (!empty($sessionIds)) {
|
||||
$this->messages->deleteMessages($sessionIds);
|
||||
}
|
||||
} else {
|
||||
$newSessionId = $room->enterRoomAsGuest($password, $this->session->get('spreed-password') === $room->getToken());
|
||||
}
|
||||
} catch (InvalidPasswordException $e) {
|
||||
return new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
|
||||
$this->session->remove('spreed-password');
|
||||
$this->session->set('spreed-session', $newSessionId);
|
||||
$room->ping($this->userId, $newSessionId, time());
|
||||
|
||||
return new DataResponse([
|
||||
'sessionId' => $newSessionId,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @PublicPage
|
||||
* @UseSession
|
||||
*
|
||||
* @param string $token
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function exitRoom($token) {
|
||||
$sessionId = $this->session->get('spreed-session');
|
||||
$this->session->remove('spreed-session');
|
||||
|
||||
try {
|
||||
$room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
|
||||
|
||||
if ($this->userId === null) {
|
||||
$participant = $room->getParticipantBySession($sessionId);
|
||||
$room->removeParticipantBySession($participant);
|
||||
} else {
|
||||
$participant = $room->getParticipant($this->userId);
|
||||
$room->disconnectUserFromAllRooms($participant->getUser());
|
||||
}
|
||||
} catch (RoomNotFoundException $e) {
|
||||
} catch (ParticipantNotFoundException $e) {
|
||||
}
|
||||
|
||||
return new DataResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
|
|
|
@ -191,7 +191,7 @@ class SignalingController extends OCSController {
|
|||
|
||||
foreach ($participants['users'] as $participant => $data) {
|
||||
if ($data['sessionId'] === '0') {
|
||||
// Use left the room
|
||||
// User is not active
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -200,6 +200,7 @@ class SignalingController extends OCSController {
|
|||
'roomId' => $room->getId(),
|
||||
'lastPing' => $data['lastPing'],
|
||||
'sessionId' => $data['sessionId'],
|
||||
'inCall' => $data['inCall'],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -209,6 +210,7 @@ class SignalingController extends OCSController {
|
|||
'roomId' => $room->getId(),
|
||||
'lastPing' => $data['lastPing'],
|
||||
'sessionId' => $data['sessionId'],
|
||||
'inCall' => $data['inCall'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ class Manager {
|
|||
* @return Participant
|
||||
*/
|
||||
protected function createParticipantObject(Room $room, array $row) {
|
||||
return new Participant($this->db, $room, $row['userId'], (int) $row['participantType'], (int) $row['lastPing'], $row['sessionId']);
|
||||
return new Participant($this->db, $room, $row['userId'], (int) $row['participantType'], (int) $row['lastPing'], $row['sessionId'], (bool) $row['inCall']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
namespace OCA\Spreed\Migration;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
use OCP\Migration\IOutput;
|
||||
|
||||
/**
|
||||
* Auto-generated migration step: Please modify to your needs!
|
||||
*/
|
||||
class Version2001Date20171031102049 extends SimpleMigrationStep {
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `Schema`
|
||||
* @param array $options
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `Schema`
|
||||
* @param array $options
|
||||
* @return null|Schema
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var Schema $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
|
||||
$table = $schema->getTable('talk_participants');
|
||||
$table->addColumn('inCall', Type::BOOLEAN, [
|
||||
'default' => 0,
|
||||
]);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `Schema`
|
||||
* @param array $options
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
}
|
||||
}
|
|
@ -44,6 +44,8 @@ class Participant {
|
|||
protected $lastPing;
|
||||
/** @var string */
|
||||
protected $sessionId;
|
||||
/** @var bool */
|
||||
protected $inCall;
|
||||
|
||||
/**
|
||||
* @param IDBConnection $db
|
||||
|
@ -52,14 +54,16 @@ class Participant {
|
|||
* @param int $participantType
|
||||
* @param int $lastPing
|
||||
* @param string $sessionId
|
||||
* @param bool $inCall
|
||||
*/
|
||||
public function __construct(IDBConnection $db, Room $room, $user, $participantType, $lastPing, $sessionId) {
|
||||
public function __construct(IDBConnection $db, Room $room, $user, $participantType, $lastPing, $sessionId, $inCall) {
|
||||
$this->db = $db;
|
||||
$this->room = $room;
|
||||
$this->user = $user;
|
||||
$this->participantType = $participantType;
|
||||
$this->lastPing = $lastPing;
|
||||
$this->sessionId = $sessionId;
|
||||
$this->inCall = $inCall;
|
||||
}
|
||||
|
||||
public function getUser() {
|
||||
|
@ -77,4 +81,8 @@ class Participant {
|
|||
public function getSessionId() {
|
||||
return $this->sessionId;
|
||||
}
|
||||
|
||||
public function isInCall() {
|
||||
return $this->inCall;
|
||||
}
|
||||
}
|
||||
|
|
36
lib/Room.php
36
lib/Room.php
|
@ -547,6 +547,7 @@ class Room {
|
|||
$query = $this->db->getQueryBuilder();
|
||||
$query->update('talk_participants')
|
||||
->set('sessionId', $query->createNamedParameter('0'))
|
||||
->set('inCall', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT))
|
||||
->where($query->expr()->eq('userId', $query->createNamedParameter($userId)))
|
||||
->andWhere($query->expr()->neq('participantType', $query->createNamedParameter(Participant::USER_SELF_JOINED, IQueryBuilder::PARAM_INT)));
|
||||
$query->execute();
|
||||
|
@ -590,6 +591,39 @@ class Room {
|
|||
return $sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sessionId
|
||||
* @param bool $active
|
||||
*/
|
||||
public function changeInCall($sessionId, $active) {
|
||||
if ($active) {
|
||||
$this->dispatcher->dispatch(self::class . '::preSessionJoinCall', new GenericEvent($this, [
|
||||
'sessionId' => $sessionId,
|
||||
]));
|
||||
} else {
|
||||
$this->dispatcher->dispatch(self::class . '::preSessionLeaveCall', new GenericEvent($this, [
|
||||
'sessionId' => $sessionId,
|
||||
]));
|
||||
}
|
||||
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$query->update('talk_participants')
|
||||
->set('inCall', $query->createNamedParameter((int) $active, IQueryBuilder::PARAM_INT))
|
||||
->where($query->expr()->eq('sessionId', $query->createNamedParameter($sessionId)))
|
||||
->andWhere($query->expr()->eq('roomId', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)));
|
||||
$query->execute();
|
||||
|
||||
if ($active) {
|
||||
$this->dispatcher->dispatch(self::class . '::postSessionJoinCall', new GenericEvent($this, [
|
||||
'sessionId' => $sessionId,
|
||||
]));
|
||||
} else {
|
||||
$this->dispatcher->dispatch(self::class . '::postSessionLeaveCall', new GenericEvent($this, [
|
||||
'sessionId' => $sessionId,
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $password
|
||||
* @return bool
|
||||
|
@ -647,12 +681,14 @@ class Room {
|
|||
while ($row = $result->fetch()) {
|
||||
if ($row['userId'] !== '' && $row['userId'] !== null) {
|
||||
$users[$row['userId']] = [
|
||||
'inCall' => (bool) $row['inCall'],
|
||||
'lastPing' => (int) $row['lastPing'],
|
||||
'sessionId' => $row['sessionId'],
|
||||
'participantType' => (int) $row['participantType'],
|
||||
];
|
||||
} else {
|
||||
$guests[] = [
|
||||
'inCall' => (bool) $row['inCall'],
|
||||
'lastPing' => (int) $row['lastPing'],
|
||||
'sessionId' => $row['sessionId'],
|
||||
];
|
||||
|
|
Загрузка…
Ссылка в новой задаче