mirror of https://github.com/sualko/cloud_bbb
feat: videos for all users and moderators
Admin may change the "published" status of a video. users/moderators may only see the published ones.pull/281/head
parent
9fed698723
commit
ac2626bc2c
|
@ -14,6 +14,7 @@ return [
|
||||||
['name' => 'server#check', 'url' => '/server/check', 'verb' => 'POST'],
|
['name' => 'server#check', 'url' => '/server/check', 'verb' => 'POST'],
|
||||||
['name' => 'server#version', 'url' => '/server/version', 'verb' => 'GET'],
|
['name' => 'server#version', 'url' => '/server/version', 'verb' => 'GET'],
|
||||||
['name' => 'server#delete_record', 'url' => '/server/record/{recordId}', 'verb' => 'DELETE'],
|
['name' => 'server#delete_record', 'url' => '/server/record/{recordId}', 'verb' => 'DELETE'],
|
||||||
|
['name' => 'server#publish_record', 'url' => '/server/record/{recordId}/publish', 'verb' => 'POST'],
|
||||||
['name' => 'join#index', 'url' => '/b/{token}/{moderatorToken}', 'verb' => 'GET', 'defaults' => ['moderatorToken' => '']],
|
['name' => 'join#index', 'url' => '/b/{token}/{moderatorToken}', 'verb' => 'GET', 'defaults' => ['moderatorToken' => '']],
|
||||||
['name' => 'restriction#user', 'url' => '/restrictions/user', 'verb' => 'GET'],
|
['name' => 'restriction#user', 'url' => '/restrictions/user', 'verb' => 'GET'],
|
||||||
['name' => 'hook#meetingEnded', 'url' => '/hook/ended/{token}/{mac}', 'verb' => 'GET'],
|
['name' => 'hook#meetingEnded', 'url' => '/hook/ended/{token}/{mac}', 'verb' => 'GET'],
|
||||||
|
|
|
@ -10,6 +10,7 @@ use BigBlueButton\Parameters\GetRecordingsParameters;
|
||||||
use BigBlueButton\Parameters\InsertDocumentParameters;
|
use BigBlueButton\Parameters\InsertDocumentParameters;
|
||||||
use BigBlueButton\Parameters\IsMeetingRunningParameters;
|
use BigBlueButton\Parameters\IsMeetingRunningParameters;
|
||||||
use BigBlueButton\Parameters\JoinMeetingParameters;
|
use BigBlueButton\Parameters\JoinMeetingParameters;
|
||||||
|
use BigBlueButton\Parameters\PublishRecordingsParameters;
|
||||||
use OCA\BigBlueButton\AppInfo\Application;
|
use OCA\BigBlueButton\AppInfo\Application;
|
||||||
use OCA\BigBlueButton\AvatarRepository;
|
use OCA\BigBlueButton\AvatarRepository;
|
||||||
use OCA\BigBlueButton\Crypto;
|
use OCA\BigBlueButton\Crypto;
|
||||||
|
@ -262,6 +263,14 @@ class API {
|
||||||
return $response->isDeleted();
|
return $response->isDeleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function publishRecording(string $recordingId, bool $published): bool {
|
||||||
|
$publishParams = new PublishRecordingsParameters($recordingId, $published);
|
||||||
|
|
||||||
|
$response = $this->getServer()->publishRecordings($publishParams);
|
||||||
|
|
||||||
|
return $response->isPublished();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return (array|bool|int|string)[]
|
* @return (array|bool|int|string)[]
|
||||||
*
|
*
|
||||||
|
|
|
@ -95,9 +95,9 @@ class ServerController extends Controller {
|
||||||
$recordings = $this->server->getRecordings($room);
|
$recordings = $this->server->getRecordings($room);
|
||||||
|
|
||||||
if (!$this->permission->isAdmin($room, $this->userId)) {
|
if (!$this->permission->isAdmin($room, $this->userId)) {
|
||||||
$recordings = array_filter($recordings, function ($recording) {
|
$recordings = array_values(array_filter($recordings, function ($recording) {
|
||||||
return $recording['published'];
|
return $recording['published'];
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DataResponse($recordings);
|
return new DataResponse($recordings);
|
||||||
|
@ -124,6 +124,27 @@ class ServerController extends Controller {
|
||||||
return new DataResponse($success);
|
return new DataResponse($success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoAdminRequired
|
||||||
|
*/
|
||||||
|
public function publishRecord(string $recordId, bool $published): DataResponse {
|
||||||
|
$record = $this->server->getRecording($recordId);
|
||||||
|
|
||||||
|
$room = $this->service->findByUid($record['meetingId']);
|
||||||
|
|
||||||
|
if ($room === null) {
|
||||||
|
return new DataResponse(false, Http::STATUS_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->permission->isAdmin($room, $this->userId)) {
|
||||||
|
return new DataResponse(false, Http::STATUS_FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
$success = $this->server->publishRecording($recordId, $published);
|
||||||
|
|
||||||
|
return new DataResponse($success);
|
||||||
|
}
|
||||||
|
|
||||||
public function check(?string $url, ?string $secret): DataResponse {
|
public function check(?string $url, ?string $secret): DataResponse {
|
||||||
if ($url === null || empty($url) || $secret === null || empty($secret)) {
|
if ($url === null || empty($url) || $secret === null || empty($secret)) {
|
||||||
return new DataResponse(false);
|
return new DataResponse(false);
|
||||||
|
|
|
@ -201,6 +201,14 @@ class Api {
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async publishRecording(id: string, publish: boolean,) {
|
||||||
|
const response = await axios.post(this.getUrl(`server/record/${id}/publish`), {
|
||||||
|
published: publish,
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
public async storeRecording(recording: Recording, path: string) {
|
public async storeRecording(recording: Recording, path: string) {
|
||||||
const startDate = new Date(recording.startTime);
|
const startDate = new Date(recording.startTime);
|
||||||
const filename = `${encodeURIComponent(recording.name + ' ' + startDate.toISOString())}.url`;
|
const filename = `${encodeURIComponent(recording.name + ' ' + startDate.toISOString())}.url`;
|
||||||
|
|
|
@ -4,11 +4,29 @@ import { Recording } from '../Common/Api';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
recording: Recording;
|
recording: Recording;
|
||||||
|
isAdmin : boolean;
|
||||||
deleteRecording: (recording: Recording) => void;
|
deleteRecording: (recording: Recording) => void;
|
||||||
storeRecording: (recording: Recording) => void;
|
storeRecording: (recording: Recording) => void;
|
||||||
|
publishRecording: (recording: Recording, publish: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RecordingRow: React.FC<Props> = ({recording, deleteRecording, storeRecording}) => {
|
const RecordingRow: React.FC<Props> = ({recording, isAdmin, deleteRecording, storeRecording, publishRecording}) => {
|
||||||
|
|
||||||
|
|
||||||
|
function checkPublished(recording: Recording, onChange: (value: boolean) => void) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<input id={`bbb-record-state-${recording.id}`}
|
||||||
|
type="checkbox"
|
||||||
|
className="checkbox"
|
||||||
|
checked={recording.state === 'published'}
|
||||||
|
onChange={(event) => onChange(event.target.checked)} />
|
||||||
|
<label htmlFor={`bbb-record-state-${recording.id}`}>{t('bbb', 'Published')}</label>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={recording.id}>
|
<tr key={recording.id}>
|
||||||
<td className="start icon-col">
|
<td className="start icon-col">
|
||||||
|
@ -40,10 +58,17 @@ const RecordingRow: React.FC<Props> = ({recording, deleteRecording, storeRecordi
|
||||||
<td>
|
<td>
|
||||||
{recording.type}
|
{recording.type}
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{isAdmin && checkPublished(recording, (checked) => {
|
||||||
|
publishRecording(recording, checked);
|
||||||
|
})}
|
||||||
|
</td>
|
||||||
<td className="remove icon-col">
|
<td className="remove icon-col">
|
||||||
|
{isAdmin &&
|
||||||
<button className="action-item" onClick={() => deleteRecording(recording)} title={t('bbb', 'Delete')}>
|
<button className="action-item" onClick={() => deleteRecording(recording)} title={t('bbb', 'Delete')}>
|
||||||
<span className="icon icon-delete icon-visible"></span>
|
<span className="icon icon-delete icon-visible"></span>
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|
|
@ -261,7 +261,7 @@ const RoomRow: React.FC<Props> = (props) => {
|
||||||
</td>
|
</td>
|
||||||
}
|
}
|
||||||
<td className="bbb-shrink">
|
<td className="bbb-shrink">
|
||||||
{(adminRoom || true ) &&
|
{
|
||||||
<RecordingsNumber recordings={recordings} showRecordings={showRecordings} setShowRecordings={setShowRecordings} />
|
<RecordingsNumber recordings={recordings} showRecordings={showRecordings} setShowRecordings={setShowRecordings} />
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
|
|
Loading…
Reference in New Issue