Changeset View
Changeset View
Standalone View
Standalone View
src/app/OpenVidu/Room.php
Show All 12 Lines | |||||
* @property string $name Room name | * @property string $name Room name | ||||
* @property int $user_id Room owner | * @property int $user_id Room owner | ||||
* @property ?string $session_id OpenVidu session identifier | * @property ?string $session_id OpenVidu session identifier | ||||
*/ | */ | ||||
class Room extends Model | class Room extends Model | ||||
{ | { | ||||
use SettingsTrait; | use SettingsTrait; | ||||
public const ROLE_MODERATOR = 'MODERATOR'; | public const ROLE_SUBSCRIBER = 1 << 0; | ||||
public const ROLE_PUBLISHER = 'PUBLISHER'; | public const ROLE_PUBLISHER = 1 << 1; | ||||
public const ROLE_SUBSCRIBER = 'SUBSCRIBER'; | public const ROLE_MODERATOR = 1 << 2; | ||||
public const ROLE_SCREEN = 1 << 3; | |||||
public const ROLE_OWNER = 1 << 4; | |||||
public const REQUEST_ACCEPTED = 'accepted'; | public const REQUEST_ACCEPTED = 'accepted'; | ||||
public const REQUEST_DENIED = 'denied'; | public const REQUEST_DENIED = 'denied'; | ||||
private const OV_ROLE_MODERATOR = 'MODERATOR'; | |||||
private const OV_ROLE_PUBLISHER = 'PUBLISHER'; | |||||
private const OV_ROLE_SUBSCRIBER = 'SUBSCRIBER'; | |||||
protected $fillable = [ | protected $fillable = [ | ||||
'user_id', | 'user_id', | ||||
'name' | 'name' | ||||
]; | ]; | ||||
protected $table = 'openvidu_rooms'; | protected $table = 'openvidu_rooms'; | ||||
/** @var \GuzzleHttp\Client|null HTTP client instance */ | /** @var \GuzzleHttp\Client|null HTTP client instance */ | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | public function deleteSession(): bool | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Create a OpenVidu session (connection) token | * Create a OpenVidu session (connection) token | ||||
* | * | ||||
* @param string $role User role | * @param int $role User role (see self::ROLE_* constants) | ||||
* @param array $data User data to attach to the connection. | |||||
* It will be available client-side for everybody. | |||||
* | * | ||||
* @return array|null Token data on success, NULL otherwise | * @return array|null Token data on success, NULL otherwise | ||||
* @throws \Exception if session does not exist | * @throws \Exception if session does not exist | ||||
*/ | */ | ||||
public function getSessionToken($role = self::ROLE_PUBLISHER, $data = []): ?array | public function getSessionToken($role = self::ROLE_SUBSCRIBER): ?array | ||||
{ | { | ||||
if (!$this->session_id) { | if (!$this->session_id) { | ||||
throw new \Exception("The room session does not exist"); | throw new \Exception("The room session does not exist"); | ||||
} | } | ||||
// FIXME: Looks like passing the role in 'data' param is the only way | // FIXME: Looks like passing the role in 'data' param is the only way | ||||
// to make it visible for everyone in a room. So, for example we can | // to make it visible for everyone in a room. So, for example we can | ||||
// handle/style subscribers/publishers/moderators differently on the | // handle/style subscribers/publishers/moderators differently on the | ||||
// client-side. Is this a security issue? | // client-side. Is this a security issue? | ||||
if (!empty($data)) { | |||||
$data += ['role' => $role]; | |||||
} else { | |||||
$data = ['role' => $role]; | $data = ['role' => $role]; | ||||
} | |||||
$url = 'sessions/' . $this->session_id . '/connection'; | $url = 'sessions/' . $this->session_id . '/connection'; | ||||
$post = [ | $post = [ | ||||
'json' => [ | 'json' => [ | ||||
'role' => $role, | 'role' => self::OV_ROLE_PUBLISHER, | ||||
'data' => json_encode($data) | 'data' => json_encode($data) | ||||
] | ] | ||||
]; | ]; | ||||
$response = $this->client()->request('POST', $url, $post); | $response = $this->client()->request('POST', $url, $post); | ||||
if ($response->getStatusCode() == 200) { | if ($response->getStatusCode() == 200) { | ||||
$json = json_decode($response->getBody(), true); | $json = json_decode($response->getBody(), true); | ||||
// Extract the 'token' part of the token, it will be used to authenticate the connection. | |||||
// It will be needed in next iterations e.g. to authenticate moderators that aren't | |||||
// Kolab4 users (or are just not logged in to Kolab4). | |||||
// FIXME: we could as well generate our own token for auth purposes | |||||
parse_str(parse_url($json['token'], PHP_URL_QUERY), $url); | |||||
// Create the connection reference in our database | |||||
$conn = new Connection(); | |||||
$conn->id = $json['id']; | |||||
$conn->session_id = $this->session_id; | |||||
$conn->room_id = $this->id; | |||||
$conn->role = $role; | |||||
$conn->metadata = ['token' => $url['token']]; | |||||
$conn->save(); | |||||
return [ | return [ | ||||
'session' => $this->session_id, | 'session' => $this->session_id, | ||||
'token' => $json['token'], | 'token' => $json['token'], | ||||
'role' => $json['role'], | |||||
'connectionId' => $json['id'], | 'connectionId' => $json['id'], | ||||
'role' => $role, | |||||
]; | ]; | ||||
} | } | ||||
return null; | return null; | ||||
} | } | ||||
/** | /** | ||||
* Check if the room has an active session | * Check if the room has an active session | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | class Room extends Model | ||||
public function settings() | public function settings() | ||||
{ | { | ||||
return $this->hasMany('App\OpenVidu\RoomSetting', 'room_id'); | return $this->hasMany('App\OpenVidu\RoomSetting', 'room_id'); | ||||
} | } | ||||
/** | /** | ||||
* Send a OpenVidu signal to the session participants (connections) | * Send a OpenVidu signal to the session participants (connections) | ||||
* | * | ||||
* @param string $name Signal name (type) | * @param string $name Signal name (type) | ||||
* @param array $data Signal data array | * @param array $data Signal data array | ||||
* @param array|string $target List of target connections, Null for all connections. | * @param null|int|string[] $target List of target connections, Null for all connections. | ||||
* It can be also a participant role. | * It can be also a participant role. | ||||
* | * | ||||
* @return bool True on success, False on failure | * @return bool True on success, False on failure | ||||
* @throws \Exception if session does not exist | * @throws \Exception if session does not exist | ||||
*/ | */ | ||||
public function signal(string $name, array $data = [], $target = null): bool | public function signal(string $name, array $data = [], $target = null): bool | ||||
{ | { | ||||
if (!$this->session_id) { | if (!$this->session_id) { | ||||
throw new \Exception("The room session does not exist"); | throw new \Exception("The room session does not exist"); | ||||
} | } | ||||
$post = [ | $post = [ | ||||
'session' => $this->session_id, | 'session' => $this->session_id, | ||||
'type' => $name, | 'type' => $name, | ||||
'data' => $data ? json_encode($data) : '', | 'data' => $data ? json_encode($data) : '', | ||||
]; | ]; | ||||
// Get connection IDs by participant role | // Get connection IDs by participant role | ||||
if (is_string($target)) { | if (is_int($target)) { | ||||
// TODO: We should probably store this in our database/redis. I foresee a use-case | $connections = Connection::where('session_id', $this->session_id) | ||||
// for such a connections store on our side, e.g. keeping participant | ->whereRaw("(role & $target)") | ||||
// metadata, e.g. selected language, extra roles like a "language interpreter", etc. | ->pluck('id') | ||||
->all(); | |||||
$response = $this->client()->request('GET', 'sessions/' . $this->session_id); | |||||
if ($response->getStatusCode() !== 200) { | |||||
return false; | |||||
} | |||||
$json = json_decode($response->getBody(), true); | |||||
$connections = []; | |||||
foreach ($json['connections']['content'] as $connection) { | |||||
if ($connection['role'] === $target) { | |||||
$connections[] = $connection['id']; | |||||
break; | |||||
} | |||||
} | |||||
if (empty($connections)) { | if (empty($connections)) { | ||||
return false; | return false; | ||||
} | } | ||||
$target = $connections; | $target = $connections; | ||||
} | } | ||||
Show All 9 Lines |