mirror of https://github.com/sualko/cloud_bbb
parent
68e3bb561d
commit
60d43ae478
|
@ -211,4 +211,12 @@ class API {
|
||||||
|
|
||||||
return $server->getApiVersion()->getVersion();
|
return $server->getApiVersion()->getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isRunning(Room $room): bool {
|
||||||
|
$isMeetingRunningParams = new IsMeetingRunningParameters($room->getUid());
|
||||||
|
|
||||||
|
$response = $this->getServer()->isMeetingRunning($isMeetingRunningParams);
|
||||||
|
|
||||||
|
return $response->success() && $response->isRunning();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,13 @@ class JoinController extends Controller {
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($room->requireModerator && ($userId === null || !$this->permission->isModerator($room, $userId)) && !$this->api->isRunning($room)) {
|
||||||
|
return new TemplateResponse($this->appName, 'waiting', [
|
||||||
|
'room' => $room->name,
|
||||||
|
'name' => $displayname,
|
||||||
|
], 'guest');
|
||||||
|
}
|
||||||
|
|
||||||
$creationDate = $this->api->createMeeting($room, $presentation);
|
$creationDate = $this->api->createMeeting($room, $presentation);
|
||||||
$joinUrl = $this->api->createJoinUrl($room, $creationDate, $displayname, $userId);
|
$joinUrl = $this->api->createJoinUrl($room, $creationDate, $displayname, $userId);
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,8 @@ class RoomController extends Controller {
|
||||||
int $maxParticipants,
|
int $maxParticipants,
|
||||||
bool $record,
|
bool $record,
|
||||||
string $access,
|
string $access,
|
||||||
bool $everyoneIsModerator
|
bool $everyoneIsModerator,
|
||||||
|
bool $requireModerator
|
||||||
): DataResponse {
|
): DataResponse {
|
||||||
$room = $this->service->find($id);
|
$room = $this->service->find($id);
|
||||||
|
|
||||||
|
@ -136,8 +137,8 @@ class RoomController extends Controller {
|
||||||
return new DataResponse('Access type not allowed.', Http::STATUS_BAD_REQUEST);
|
return new DataResponse('Access type not allowed.', Http::STATUS_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->handleNotFound(function () use ($id, $name, $welcome, $maxParticipants, $record, $everyoneIsModerator, $access) {
|
return $this->handleNotFound(function () use ($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator) {
|
||||||
return $this->service->update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator);
|
return $this->service->update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ use OCP\AppFramework\Db\Entity;
|
||||||
* @method string getAccess()
|
* @method string getAccess()
|
||||||
* @method string getPassword()
|
* @method string getPassword()
|
||||||
* @method bool getEveryoneIsModerator()
|
* @method bool getEveryoneIsModerator()
|
||||||
|
* @method bool getRequireModerator()
|
||||||
|
* @method bool getEveryoneIsModerator()
|
||||||
* @method void setUid(string $uid)
|
* @method void setUid(string $uid)
|
||||||
* @method void setName(string $name)
|
* @method void setName(string $name)
|
||||||
* @method void setAttendeePassword(string $pw)
|
* @method void setAttendeePassword(string $pw)
|
||||||
|
@ -29,6 +31,7 @@ use OCP\AppFramework\Db\Entity;
|
||||||
* @method void setAccess(string $access)
|
* @method void setAccess(string $access)
|
||||||
* @method void setPassword(string $pw)
|
* @method void setPassword(string $pw)
|
||||||
* @method void setEveryoneIsModerator(bool $everyone)
|
* @method void setEveryoneIsModerator(bool $everyone)
|
||||||
|
* @method void setRequireModerator(bool $require)
|
||||||
*/
|
*/
|
||||||
class Room extends Entity implements JsonSerializable {
|
class Room extends Entity implements JsonSerializable {
|
||||||
public const ACCESS_PUBLIC = 'public';
|
public const ACCESS_PUBLIC = 'public';
|
||||||
|
@ -50,11 +53,13 @@ class Room extends Entity implements JsonSerializable {
|
||||||
public $access = self::ACCESS_PUBLIC;
|
public $access = self::ACCESS_PUBLIC;
|
||||||
public $password;
|
public $password;
|
||||||
public $everyoneIsModerator;
|
public $everyoneIsModerator;
|
||||||
|
public $requireModerator = false;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->addType('maxParticipants', 'integer');
|
$this->addType('maxParticipants', 'integer');
|
||||||
$this->addType('record', 'boolean');
|
$this->addType('record', 'boolean');
|
||||||
$this->addType('everyoneIsModerator', 'boolean');
|
$this->addType('everyoneIsModerator', 'boolean');
|
||||||
|
$this->addType('requireModerator', 'boolean');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function jsonSerialize(): array {
|
public function jsonSerialize(): array {
|
||||||
|
@ -69,6 +74,7 @@ class Room extends Entity implements JsonSerializable {
|
||||||
'access' => $this->access,
|
'access' => $this->access,
|
||||||
'password' => $this->password,
|
'password' => $this->password,
|
||||||
'everyoneIsModerator' => boolval($this->everyoneIsModerator),
|
'everyoneIsModerator' => boolval($this->everyoneIsModerator),
|
||||||
|
'requireModerator' => boolval($this->requireModerator),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace OCA\BigBlueButton\Migration;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use OCP\DB\ISchemaWrapper;
|
||||||
|
use OCP\Migration\IOutput;
|
||||||
|
use OCP\Migration\SimpleMigrationStep;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated migration step: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
class Version000000Date20200829112301 extends SimpleMigrationStep {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param IOutput $output
|
||||||
|
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||||
|
* @param array $options
|
||||||
|
* @return null|ISchemaWrapper
|
||||||
|
*/
|
||||||
|
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
|
||||||
|
$schema = $schemaClosure();
|
||||||
|
|
||||||
|
if ($schema->hasTable('bbb_rooms')) {
|
||||||
|
$table = $schema->getTable('bbb_rooms');
|
||||||
|
|
||||||
|
if (!$table->hasColumn('require_moderator')) {
|
||||||
|
$table->addColumn('require_moderator', 'boolean', [
|
||||||
|
'notnull' => true,
|
||||||
|
'default' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,7 +73,7 @@ class RoomService {
|
||||||
return $this->mapper->insert($room);
|
return $this->mapper->insert($room);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator) {
|
public function update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $requireModerator) {
|
||||||
try {
|
try {
|
||||||
$room = $this->mapper->find($id);
|
$room = $this->mapper->find($id);
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ class RoomService {
|
||||||
$room->setRecord($record);
|
$room->setRecord($record);
|
||||||
$room->setAccess($access);
|
$room->setAccess($access);
|
||||||
$room->setEveryoneIsModerator($everyoneIsModerator);
|
$room->setEveryoneIsModerator($everyoneIsModerator);
|
||||||
|
$room->setRequireModerator($requireModerator);
|
||||||
|
|
||||||
return $this->mapper->update($room);
|
return $this->mapper->update($room);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
/** @var $_ array */
|
||||||
|
/** @var $l \OCP\IL10N */
|
||||||
|
style('core', 'guest');
|
||||||
|
script('bbb', 'waiting');
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="update bbb">
|
||||||
|
<h2><?php p($_['room']); ?></h2>
|
||||||
|
<h3><?php p($l->t('Hello %s', $_['name'])); ?></h3>
|
||||||
|
|
||||||
|
<p id="bbb-waiting-text"></p>
|
||||||
|
</div>
|
|
@ -36,6 +36,7 @@ export interface Room {
|
||||||
access: Access;
|
access: Access;
|
||||||
password?: string;
|
password?: string;
|
||||||
everyoneIsModerator: boolean;
|
everyoneIsModerator: boolean;
|
||||||
|
requireModerator: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RoomShare {
|
export interface RoomShare {
|
||||||
|
|
|
@ -77,6 +77,10 @@
|
||||||
margin: 3em;
|
margin: 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
@ -12,6 +12,7 @@ const descriptions: { [key: string]: string } = {
|
||||||
recording: t('bbb', 'If enabled, the moderator is able to start the recording.'),
|
recording: t('bbb', 'If enabled, the moderator is able to start the recording.'),
|
||||||
access: t('bbb', 'Public: Everyone knowing the link is able to join. Password: Guests have to provide a password. Waiting room: A moderator has to accept every guest before they can join. Internal: Only Nextcloud users can join.'),
|
access: t('bbb', 'Public: Everyone knowing the link is able to join. Password: Guests have to provide a password. Waiting room: A moderator has to accept every guest before they can join. Internal: Only Nextcloud users can join.'),
|
||||||
moderator: t('bbb', 'A moderator is able to manage all participants in a meeting including kicking, muting or selecting a presenter. Users with the role moderator are also able to close a meeting or change the default settings.'),
|
moderator: t('bbb', 'A moderator is able to manage all participants in a meeting including kicking, muting or selecting a presenter. Users with the role moderator are also able to close a meeting or change the default settings.'),
|
||||||
|
requireModerator: t('bbb', 'If enabled, normal users have to wait until a moderator is in the room.'),
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -127,7 +128,18 @@ const EditRoomDialog: React.FC<Props> = ({ room, restriction, updateProperty, op
|
||||||
onChange={(event) => updateProperty('record', event.target.checked)} />
|
onChange={(event) => updateProperty('record', event.target.checked)} />
|
||||||
<label htmlFor={`bbb-record-${room.id}`}>{t('bbb', 'Recording')}</label>
|
<label htmlFor={`bbb-record-${room.id}`}>{t('bbb', 'Recording')}</label>
|
||||||
</div>
|
</div>
|
||||||
<em>{descriptions.recording}</em>
|
<p><em>{descriptions.recording}</em></p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<input id={`bbb-requireModerator-${room.id}`}
|
||||||
|
type="checkbox"
|
||||||
|
className="checkbox"
|
||||||
|
checked={room.requireModerator}
|
||||||
|
onChange={(event) => updateProperty('requireModerator', event.target.checked)} />
|
||||||
|
<label htmlFor={`bbb-requireModerator-${room.id}`}>{t('bbb', 'Require moderator to start room')}</label>
|
||||||
|
</div>
|
||||||
|
<p><em>{descriptions.requireModerator}</em></p>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
.bbb {
|
||||||
|
h2 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import './waiting.scss';
|
||||||
|
|
||||||
|
$(() => {
|
||||||
|
let countdown = 30;
|
||||||
|
|
||||||
|
const interval = window.setInterval(() => {
|
||||||
|
$('#bbb-waiting-text').text(t('bbb', 'This room is not open yet. We will try it again in {sec} seconds. Please wait.', {sec: (--countdown).toString()}));
|
||||||
|
|
||||||
|
if (countdown === 0) {
|
||||||
|
window.location.reload();
|
||||||
|
window.clearInterval(interval);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
});
|
|
@ -16,6 +16,9 @@ module.exports = {
|
||||||
],
|
],
|
||||||
join: [
|
join: [
|
||||||
path.join(__dirname, 'ts', 'join.ts'),
|
path.join(__dirname, 'ts', 'join.ts'),
|
||||||
|
],
|
||||||
|
waiting: [
|
||||||
|
path.join(__dirname, 'ts', 'waiting.ts'),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
|
Loading…
Reference in New Issue