Skip to content

Commit 2c5ff0d

Browse files
authored
Merge pull request #67 from sualko/feat-restrictions
feat: add admin setting to restrict rooms
2 parents ab0c32a + f13f28a commit 2c5ff0d

37 files changed

Lines changed: 1189 additions & 159 deletions

appinfo/routes.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
'resources' => [
55
'room' => ['url' => '/rooms'],
66
'roomShare' => ['url' => '/roomShares'],
7+
'restriction' => ['url' => '/restrictions'],
78
],
89
'routes' => [
910
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
@@ -12,5 +13,6 @@
1213
['name' => 'server#version', 'url' => '/server/version', 'verb' => 'GET'],
1314
['name' => 'server#delete_record', 'url' => '/server/record/{recordId}', 'verb' => 'DELETE'],
1415
['name' => 'join#index', 'url' => '/b/{token}', 'verb' => 'GET'],
16+
['name' => 'restriction#user', 'url' => '/restrictions/user', 'verb' => 'GET'],
1517
]
1618
];

lib/Controller/JoinController.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,9 @@ public function index($displayname, $u = '', $filename = '', $password = '') {
120120
\OCP\Util::addHeader('meta', ['http-equiv' => 'refresh', 'content' => '3;url='.$joinUrl]);
121121

122122
return new TemplateResponse($this->appName, 'forward', [
123-
'room' => $room->name,
124-
'url' => $joinUrl,
123+
'room' => $room->name,
124+
'url' => $joinUrl,
125125
], 'guest');
126-
;
127126
}
128127

129128
private function getRoom(): ?Room {
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
namespace OCA\BigBlueButton\Controller;
4+
5+
use OCA\BigBlueButton\Db\Restriction;
6+
use OCP\IRequest;
7+
use OCP\IGroupManager;
8+
use OCP\IUserManager;
9+
use OCP\AppFramework\Http;
10+
use OCP\AppFramework\Http\DataResponse;
11+
use OCP\AppFramework\Controller;
12+
13+
use OCA\BigBlueButton\Service\RestrictionService;
14+
15+
class RestrictionController extends Controller {
16+
/** @var RestrictionService */
17+
private $service;
18+
19+
/** @var string */
20+
private $userId;
21+
22+
/** @var IUserManager */
23+
private $userManager;
24+
25+
/** @var IGroupManager */
26+
private $groupManager;
27+
28+
use Errors;
29+
30+
public function __construct(
31+
$appName,
32+
IRequest $request,
33+
RestrictionService $service,
34+
IUserManager $userManager,
35+
IGroupManager $groupManager,
36+
$userId
37+
) {
38+
parent::__construct($appName, $request);
39+
$this->service = $service;
40+
$this->userManager = $userManager;
41+
$this->groupManager = $groupManager;
42+
$this->userId = $userId;
43+
}
44+
45+
/**
46+
* @NoAdminRequired
47+
*/
48+
public function user(): DataResponse {
49+
$user = $this->userManager->get($this->userId);
50+
$groupIds = $this->groupManager->getUserGroupIds($user);
51+
52+
return new DataResponse($this->service->findByGroupIds($groupIds));
53+
}
54+
55+
public function index(): DataResponse {
56+
$restrictions = $this->service->findAll();
57+
58+
if (!$this->service->existsByGroupId(Restriction::ALL_ID)) {
59+
$defaultRestriction = new Restriction();
60+
$defaultRestriction->setGroupId('');
61+
62+
$restrictions[] = $defaultRestriction;
63+
}
64+
65+
return new DataResponse($restrictions);
66+
}
67+
68+
public function create(
69+
string $groupId
70+
): DataResponse {
71+
if ($this->service->existsByGroupId($groupId)) {
72+
return new DataResponse(null, Http::STATUS_CONFLICT);
73+
}
74+
75+
return new DataResponse($this->service->create(
76+
$groupId
77+
));
78+
}
79+
80+
public function update(
81+
int $id,
82+
string $groupId,
83+
int $maxRooms,
84+
array $roomTypes,
85+
int $maxParticipants,
86+
bool $allowRecording
87+
): DataResponse {
88+
return $this->handleNotFound(function () use (
89+
$id,
90+
$groupId,
91+
$maxRooms,
92+
$roomTypes,
93+
$maxParticipants,
94+
$allowRecording) {
95+
return $this->service->update(
96+
$id,
97+
$groupId,
98+
$maxRooms,
99+
$roomTypes,
100+
$maxParticipants,
101+
$allowRecording
102+
);
103+
});
104+
}
105+
106+
public function destroy(int $id): DataResponse {
107+
return $this->handleNotFound(function () use ($id) {
108+
$roomShare = $this->service->find($id);
109+
110+
return $this->service->delete($id);
111+
});
112+
}
113+
}

lib/Controller/RoomController.php

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use OCA\BigBlueButton\Service\RoomService;
66
use OCA\BigBlueButton\Permission;
7+
use OCA\BigBlueButton\Db\Room;
78
use OCP\IRequest;
89
use OCP\AppFramework\Http;
910
use OCP\AppFramework\Http\DataResponse;
@@ -63,13 +64,34 @@ public function create(
6364
string $name,
6465
string $welcome,
6566
int $maxParticipants,
66-
bool $record
67+
bool $record,
68+
string $access
6769
): DataResponse {
70+
if (!$this->permission->isAllowedToCreateRoom($this->userId)) {
71+
return new DataResponse(null, Http::STATUS_FORBIDDEN);
72+
}
73+
74+
$restriction = $this->permission->getRestriction($this->userId);
75+
76+
if ($restriction->getMaxParticipants() > -1 && ($maxParticipants > $restriction->getMaxParticipants() || $maxParticipants <= 0)) {
77+
return new DataResponse('Max participants limit exceeded.', Http::STATUS_BAD_REQUEST);
78+
}
79+
80+
if (!$restriction->getAllowRecording() && $record) {
81+
return new DataResponse('Not allowed to enable recordings.', Http::STATUS_BAD_REQUEST);
82+
}
83+
84+
$disabledRoomTypes = \json_decode($restriction->getRoomTypes());
85+
if (in_array($access, $disabledRoomTypes) || !in_array($access, Room::ACCESS)) {
86+
return new DataResponse('Access type not allowed.', Http::STATUS_BAD_REQUEST);
87+
}
88+
6889
return new DataResponse($this->service->create(
6990
$name,
7091
$welcome,
7192
$maxParticipants,
7293
$record,
94+
$access,
7395
$this->userId
7496
));
7597
}
@@ -92,6 +114,21 @@ public function update(
92114
return new DataResponse(null, Http::STATUS_FORBIDDEN);
93115
}
94116

117+
$restriction = $this->permission->getRestriction($this->userId);
118+
119+
if ($restriction->getMaxParticipants() > -1 && $maxParticipants !== $room->getMaxParticipants() && ($maxParticipants > $restriction->getMaxParticipants() || $maxParticipants <= 0)) {
120+
return new DataResponse('Max participants limit exceeded.', Http::STATUS_BAD_REQUEST);
121+
}
122+
123+
if (!$restriction->getAllowRecording() && $record !== $room->getRecord()) {
124+
return new DataResponse('Not allowed to enable recordings.', Http::STATUS_BAD_REQUEST);
125+
}
126+
127+
$disabledRoomTypes = \json_decode($restriction->getRoomTypes());
128+
if ((in_array($access, $disabledRoomTypes) && $access !== $room->getAccess()) || !in_array($access, Room::ACCESS)) {
129+
return new DataResponse('Access type not allowed.', Http::STATUS_BAD_REQUEST);
130+
}
131+
95132
return $this->handleNotFound(function () use ($id, $name, $welcome, $maxParticipants, $record, $everyoneIsModerator, $access) {
96133
return $this->service->update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator);
97134
});

lib/Db/Restriction.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace OCA\BigBlueButton\Db;
4+
5+
use JsonSerializable;
6+
7+
use OCP\AppFramework\Db\Entity;
8+
9+
/**
10+
* @method int getRoomId()
11+
* @method int getMaxRooms()
12+
* @method string getRoomTypes()
13+
* @method int getMaxParticipants()
14+
* @method bool getAllowRecording()
15+
* @method void setRoomId(string $id)
16+
* @method void setMaxRooms(int $number)
17+
* @method void setMaxParticipants(int $number)
18+
* @method void setAllowRecording(bool $allow)
19+
*/
20+
class Restriction extends Entity implements JsonSerializable {
21+
public const ALL_ID = '';
22+
23+
protected $groupId;
24+
protected $maxRooms = -1;
25+
protected $roomTypes = '[]';
26+
protected $maxParticipants = -1;
27+
protected $allowRecording = true;
28+
29+
public function __construct() {
30+
$this->addType('max_rooms', 'integer');
31+
$this->addType('max_participants', 'integer');
32+
$this->addType('allow_recording', 'boolean');
33+
}
34+
35+
public function jsonSerialize(): array {
36+
return [
37+
'id' => $this->id,
38+
'groupId' => $this->groupId,
39+
'maxRooms' => (int) $this->maxRooms,
40+
'roomTypes' => \json_decode($this->roomTypes),
41+
'maxParticipants' => (int) $this->maxParticipants,
42+
'allowRecording' => boolval($this->allowRecording),
43+
];
44+
}
45+
}

lib/Db/RestrictionMapper.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace OCA\BigBlueButton\Db;
4+
5+
use OCP\AppFramework\Db\DoesNotExistException;
6+
use OCP\AppFramework\Db\QBMapper;
7+
use OCP\DB\QueryBuilder\IQueryBuilder;
8+
use OCP\IDBConnection;
9+
10+
class RestrictionMapper extends QBMapper {
11+
public function __construct(IDBConnection $db) {
12+
parent::__construct($db, 'bbb_restrictions', Restriction::class);
13+
}
14+
15+
/**
16+
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
17+
* @throws DoesNotExistException
18+
*/
19+
public function find(int $id): Restriction {
20+
/* @var $qb IQueryBuilder */
21+
$qb = $this->db->getQueryBuilder();
22+
$qb->select('*')
23+
->from($this->tableName)
24+
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
25+
26+
return $this->findEntity($qb);
27+
}
28+
29+
/**
30+
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
31+
* @throws DoesNotExistException
32+
*/
33+
public function findByGroupId(string $groupId): Restriction {
34+
/* @var $qb IQueryBuilder */
35+
$qb = $this->db->getQueryBuilder();
36+
$qb->select('*')
37+
->from($this->tableName)
38+
->where($qb->expr()->eq('group_id', $qb->createNamedParameter($groupId)));
39+
40+
return $this->findEntity($qb);
41+
}
42+
43+
/**
44+
* @return array<Restriction>
45+
*/
46+
public function findByGroupIds(array $groupIds): array {
47+
/* @var $qb IQueryBuilder */
48+
$qb = $this->db->getQueryBuilder();
49+
$qb->select('*')
50+
->from($this->tableName)
51+
->where($qb->expr()->in('group_id', $qb->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)));
52+
53+
/** @var array<Restriction> */
54+
return $this->findEntities($qb);
55+
}
56+
57+
/**
58+
* @return array<Restriction>
59+
*/
60+
public function findAll(): array {
61+
/* @var $qb IQueryBuilder */
62+
$qb = $this->db->getQueryBuilder();
63+
$qb->select('*')
64+
->from($this->tableName);
65+
66+
/** @var array<Restriction> */
67+
return $this->findEntities($qb);
68+
}
69+
}

lib/Db/Room.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class Room extends Entity implements JsonSerializable {
3737
public const ACCESS_INTERNAL = 'internal';
3838
public const ACCESS_INTERNAL_RESTRICTED = 'internal_restricted';
3939

40+
public const ACCESS = [self::ACCESS_PUBLIC, self::ACCESS_PASSWORD, self::ACCESS_WAITING_ROOM, self::ACCESS_INTERNAL, self::ACCESS_INTERNAL_RESTRICTED];
41+
4042
public $uid;
4143
public $name;
4244
public $attendeePassword;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OCA\BigBlueButton\Migration;
6+
7+
use Closure;
8+
use OCP\DB\ISchemaWrapper;
9+
use OCP\Migration\IOutput;
10+
use OCP\Migration\SimpleMigrationStep;
11+
12+
/**
13+
* Auto-generated migration step: Please modify to your needs!
14+
*/
15+
class Version000000Date20200826100844 extends SimpleMigrationStep {
16+
17+
/**
18+
* @param IOutput $output
19+
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
20+
* @param array $options
21+
* @return null|ISchemaWrapper
22+
*/
23+
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
24+
/** @var ISchemaWrapper $schema */
25+
$schema = $schemaClosure();
26+
27+
if (!$schema->hasTable('bbb_restrictions')) {
28+
$table = $schema->createTable('bbb_restrictions');
29+
$table->addColumn('id', 'integer', [
30+
'autoincrement' => true,
31+
'notnull' => true,
32+
]);
33+
$table->addColumn('group_id', 'string', [
34+
'unique' => true,
35+
'notnull' => true,
36+
'length' => 200,
37+
]);
38+
$table->addColumn('max_rooms', 'integer', [
39+
'notnull' => false,
40+
'default' => -1,
41+
]);
42+
$table->addColumn('room_types', 'string', [
43+
'notnull' => true,
44+
'default' => '[]',
45+
]);
46+
$table->addColumn('max_participants', 'integer', [
47+
'notnull' => false,
48+
'default' => -1,
49+
]);
50+
$table->addColumn('allow_recording', 'boolean', [
51+
'notnull' => true,
52+
'default' => true,
53+
]);
54+
55+
$table->setPrimaryKey(['id']);
56+
$table->addIndex(['group_id'], 'restrictions_group_id_index');
57+
}
58+
59+
return $schema;
60+
}
61+
}

0 commit comments

Comments
 (0)