Skip to content

Commit 29aa147

Browse files
authored
Merge pull request #281 from arawa/feature/share_moderators_and_users
Feature/share moderators and users
2 parents a203c53 + 95e4e4f commit 29aa147

File tree

14 files changed

+228
-61
lines changed

14 files changed

+228
-61
lines changed

appinfo/routes.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
['name' => 'server#check', 'url' => '/server/check', 'verb' => 'POST'],
1515
['name' => 'server#version', 'url' => '/server/version', 'verb' => 'GET'],
1616
['name' => 'server#delete_record', 'url' => '/server/record/{recordId}', 'verb' => 'DELETE'],
17+
['name' => 'server#publish_record', 'url' => '/server/record/{recordId}/publish', 'verb' => 'POST'],
1718
['name' => 'join#index', 'url' => '/b/{token}/{moderatorToken}', 'verb' => 'GET', 'defaults' => ['moderatorToken' => '']],
1819
['name' => 'restriction#user', 'url' => '/restrictions/user', 'verb' => 'GET'],
1920
['name' => 'hook#meetingEnded', 'url' => '/hook/ended/{token}/{mac}', 'verb' => 'GET'],

lib/BigBlueButton/API.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use BigBlueButton\Parameters\InsertDocumentParameters;
1111
use BigBlueButton\Parameters\IsMeetingRunningParameters;
1212
use BigBlueButton\Parameters\JoinMeetingParameters;
13+
use BigBlueButton\Parameters\PublishRecordingsParameters;
1314
use OCA\BigBlueButton\AppInfo\Application;
1415
use OCA\BigBlueButton\AvatarRepository;
1516
use OCA\BigBlueButton\Crypto;
@@ -262,6 +263,14 @@ public function deleteRecording(string $recordingId): bool {
262263
return $response->isDeleted();
263264
}
264265

266+
public function publishRecording(string $recordingId, bool $published): bool {
267+
$publishParams = new PublishRecordingsParameters($recordingId, $published);
268+
269+
$response = $this->getServer()->publishRecordings($publishParams);
270+
271+
return $response->isPublished();
272+
}
273+
265274
/**
266275
* @return (array|bool|int|string)[]
267276
*

lib/Controller/RoomShareController.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use OCP\AppFramework\Http;
1212
use OCP\AppFramework\Http\DataResponse;
1313

14+
use OCP\IGroupManager;
1415
use OCP\IRequest;
1516
use OCP\IUserManager;
1617

@@ -24,6 +25,9 @@ class RoomShareController extends Controller {
2425
/** @var IUserManager */
2526
private $userManager;
2627

28+
/** @var IGroupManager */
29+
private $groupManager;
30+
2731
/** @var RoomService */
2832
private $roomService;
2933

@@ -37,13 +41,15 @@ public function __construct(
3741
IRequest $request,
3842
RoomShareService $service,
3943
IUserManager $userManager,
44+
IGroupManager $groupManager,
4045
RoomService $roomService,
4146
CircleHelper $circleHelper,
4247
$userId
4348
) {
4449
parent::__construct($appName, $request);
4550
$this->service = $service;
4651
$this->userManager = $userManager;
52+
$this->groupManager = $groupManager;
4753
$this->roomService = $roomService;
4854
$this->circleHelper = $circleHelper;
4955
$this->userId = $userId;
@@ -90,6 +96,14 @@ public function index(): DataResponse {
9096
}
9197

9298
$roomShare->setShareWithDisplayName($circle->getName());
99+
} elseif ($roomShare->getShareType() === RoomShare::SHARE_TYPE_GROUP) {
100+
$shareWithGroup = $this->groupManager->get($roomShare->getShareWith());
101+
102+
if ($shareWithGroup === null) {
103+
continue;
104+
}
105+
106+
$roomShare->setShareWithDisplayName($shareWithGroup->getDisplayName());
93107
}
94108

95109
$shares[] = $roomShare;

lib/Controller/ServerController.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,18 @@ public function records(string $roomUid): DataResponse {
8888
return new DataResponse([], Http::STATUS_NOT_FOUND);
8989
}
9090

91-
if (!$this->permission->isAdmin($room, $this->userId)) {
91+
if (!$this->permission->isUser($room, $this->userId)) {
9292
return new DataResponse([], Http::STATUS_FORBIDDEN);
9393
}
9494

9595
$recordings = $this->server->getRecordings($room);
9696

97+
if (!$this->permission->isAdmin($room, $this->userId)) {
98+
$recordings = array_values(array_filter($recordings, function ($recording) {
99+
return $recording['published'];
100+
}));
101+
}
102+
97103
return new DataResponse($recordings);
98104
}
99105

@@ -118,6 +124,27 @@ public function deleteRecord(string $recordId): DataResponse {
118124
return new DataResponse($success);
119125
}
120126

127+
/**
128+
* @NoAdminRequired
129+
*/
130+
public function publishRecord(string $recordId, bool $published): DataResponse {
131+
$record = $this->server->getRecording($recordId);
132+
133+
$room = $this->service->findByUid($record['meetingId']);
134+
135+
if ($room === null) {
136+
return new DataResponse(false, Http::STATUS_NOT_FOUND);
137+
}
138+
139+
if (!$this->permission->isAdmin($room, $this->userId)) {
140+
return new DataResponse(false, Http::STATUS_FORBIDDEN);
141+
}
142+
143+
$success = $this->server->publishRecording($recordId, $published);
144+
145+
return new DataResponse($success);
146+
}
147+
121148
public function check(?string $url, ?string $secret): DataResponse {
122149
if ($url === null || empty($url) || $secret === null || empty($secret)) {
123150
return new DataResponse(false);

lib/Db/Room.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class Room extends Entity implements JsonSerializable {
7474
public $cleanLayout;
7575
public $joinMuted;
7676
public $running;
77+
public $permission;
7778

7879
public function __construct() {
7980
$this->addType('maxParticipants', 'integer');
@@ -86,6 +87,7 @@ public function __construct() {
8687
$this->addType('cleanLayout', 'boolean');
8788
$this->addType('joinMuted', 'boolean');
8889
$this->addType('running', 'boolean');
90+
$this->addType('permission', 'integer');
8991
}
9092

9193
public function jsonSerialize(): array {
@@ -102,6 +104,7 @@ public function jsonSerialize(): array {
102104
'everyoneIsModerator' => boolval($this->everyoneIsModerator),
103105
'requireModerator' => boolval($this->requireModerator),
104106
'shared' => boolval($this->shared),
107+
'permission' => $this->permission,
105108
'moderatorToken' => $this->moderatorToken,
106109
'listenOnly' => boolval($this->listenOnly),
107110
'mediaCheck' => boolval($this->mediaCheck),

lib/Db/RoomMapper.php

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,24 @@ public function __construct(IDBConnection $db) {
1212
parent::__construct($db, 'bbb_rooms', Room::class);
1313
}
1414

15+
private function joinShares(IQueryBuilder $qb): IQueryBuilder {
16+
$qb->select('r.*')
17+
->from($this->tableName, 'r')
18+
->leftJoin('r', 'bbb_room_shares', 's', $qb->expr()->eq('r.id', 's.room_id'))
19+
->addSelect($qb->createFunction('count(case when `s`.`permission` IN ('.
20+
RoomShare::PERMISSION_ADMIN.','.RoomShare::PERMISSION_MODERATOR.','.RoomShare::PERMISSION_USER
21+
.') then 1 else null end) as shared'));
22+
return $qb;
23+
}
24+
1525
/**
1626
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
1727
* @throws DoesNotExistException
1828
*/
1929
public function find(int $id): Room {
2030
/* @var $qb IQueryBuilder */
2131
$qb = $this->db->getQueryBuilder();
22-
$qb->select('r.*')
23-
->from($this->tableName, 'r')
24-
->leftJoin('r', 'bbb_room_shares', 's', $qb->expr()->eq('r.id', 's.room_id'))
25-
->addSelect($qb->createFunction('count(case when `s`.`permission` = 0 then 1 else null end) as shared'))
32+
$this->joinShares($qb)
2633
->where($qb->expr()->eq('r.id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)))
2734
->groupBy('r.id');
2835
;
@@ -38,10 +45,7 @@ public function find(int $id): Room {
3845
public function findByUid(string $uid): Room {
3946
/* @var $qb IQueryBuilder */
4047
$qb = $this->db->getQueryBuilder();
41-
$qb->select('r.*')
42-
->from($this->tableName, 'r')
43-
->leftJoin('r', 'bbb_room_shares', 's', $qb->expr()->eq('r.id', 's.room_id'))
44-
->addSelect($qb->createFunction('count(case when `s`.`permission` = 0 then 1 else null end) as shared'))
48+
$this->joinShares($qb)
4549
->where($qb->expr()->eq('r.uid', $qb->createNamedParameter($uid)))
4650
->groupBy('r.id');
4751
;
@@ -70,25 +74,20 @@ public function findByUserId(string $userId): array {
7074
public function findAll(string $userId, array $groupIds, array $circleIds): array {
7175
/* @var $qb IQueryBuilder */
7276
$qb = $this->db->getQueryBuilder();
73-
$qb->select('r.*')
74-
->from($this->tableName, 'r')
75-
->leftJoin('r', 'bbb_room_shares', 's', $qb->expr()->eq('r.id', 's.room_id'))
76-
->addSelect($qb->createFunction('count(case when `s`.`permission` = 0 then 1 else null end) as shared'))
77+
$this->joinShares($qb)
78+
->addSelect($qb->createFunction('min(case when '.$qb->expr()->eq('r.user_id', $qb->createNamedParameter($userId)).' then '.RoomShare::PERMISSION_ADMIN.' else `s`.`permission` end) as permission'))
7779
->where(
7880
$qb->expr()->orX(
7981
$qb->expr()->eq('r.user_id', $qb->createNamedParameter($userId)),
8082
$qb->expr()->andX(
81-
$qb->expr()->eq('s.permission', $qb->createNamedParameter(RoomShare::PERMISSION_ADMIN, IQueryBuilder::PARAM_INT)),
8283
$qb->expr()->eq('s.share_type', $qb->createNamedParameter(RoomShare::SHARE_TYPE_USER, IQueryBuilder::PARAM_INT)),
8384
$qb->expr()->eq('s.share_with', $qb->createNamedParameter($userId))
8485
),
8586
$qb->expr()->andX(
86-
$qb->expr()->eq('s.permission', $qb->createNamedParameter(RoomShare::PERMISSION_ADMIN, IQueryBuilder::PARAM_INT)),
8787
$qb->expr()->eq('s.share_type', $qb->createNamedParameter(RoomShare::SHARE_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
8888
$qb->expr()->in('s.share_with', $qb->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY))
8989
),
9090
$qb->expr()->andX(
91-
$qb->expr()->eq('s.permission', $qb->createNamedParameter(RoomShare::PERMISSION_ADMIN, IQueryBuilder::PARAM_INT)),
9291
$qb->expr()->eq('s.share_type', $qb->createNamedParameter(RoomShare::SHARE_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)),
9392
$qb->expr()->in('s.share_with', $qb->createNamedParameter($circleIds, IQueryBuilder::PARAM_STR_ARRAY))
9493
)
@@ -99,7 +98,7 @@ public function findAll(string $userId, array $groupIds, array $circleIds): arra
9998
/** @var array<Room> */
10099
return $this->findEntities($qb);
101100
}
102-
101+
103102
/**
104103
* @return array<Room>
105104
*/

tests/Unit/Controller/RoomShareControllerTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use OCA\BigBlueButton\Service\RoomService;
1010
use OCA\BigBlueButton\Service\RoomShareService;
1111
use OCP\AppFramework\Http;
12+
use OCP\IGroupManager;
1213
use OCP\IRequest;
1314
use OCP\IUserManager;
1415
use PHPUnit\Framework\TestCase;
@@ -19,6 +20,7 @@ class RoomShareControllerTest extends TestCase {
1920
private $roomService;
2021
private $circleHelper;
2122
private $userManager;
23+
private $groupManager;
2224
private $controller;
2325

2426
private $userId = 'user_foo';
@@ -29,6 +31,7 @@ public function setUp(): void {
2931
$this->request = $this->createMock(IRequest::class);
3032
$this->service = $this->createMock(RoomShareService::class);
3133
$this->userManager = $this->createMock(IUserManager::class);
34+
$this->groupManager = $this->createMock(IGroupManager::class);
3235
$this->roomService = $this->createMock(RoomService::class);
3336
$this->circleHelper = $this->createMock(CircleHelper::class);
3437

@@ -37,6 +40,7 @@ public function setUp(): void {
3740
$this->request,
3841
$this->service,
3942
$this->userManager,
43+
$this->groupManager,
4044
$this->roomService,
4145
$this->circleHelper,
4246
$this->userId

ts/Common/Api.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export interface Room {
3939
everyoneIsModerator: boolean;
4040
requireModerator: boolean;
4141
shared: boolean;
42+
permission: Permission;
4243
moderatorToken: string;
4344
listenOnly: boolean,
4445
mediaCheck: boolean,
@@ -200,6 +201,14 @@ class Api {
200201
return response.data;
201202
}
202203

204+
public async publishRecording(id: string, publish: boolean,) {
205+
const response = await axios.post(this.getUrl(`server/record/${id}/publish`), {
206+
published: publish,
207+
});
208+
209+
return response.data;
210+
}
211+
203212
public async storeRecording(recording: Recording, path: string) {
204213
const startDate = new Date(recording.startTime);
205214
const filename = `${encodeURIComponent(recording.name + ' ' + startDate.toISOString())}.url`;

ts/Common/Translation.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Access } from './Api';
1+
import { Access, Permission } from './Api';
22

33
export const AccessOptions = {
44
[Access.Public]: t('bbb', 'Public'),
@@ -8,3 +8,9 @@ export const AccessOptions = {
88
[Access.Internal]: t('bbb', 'Internal'),
99
[Access.InternalRestricted]: t('bbb', 'Internal restricted'),
1010
};
11+
12+
export const PermissionsOptions = {
13+
[Permission.Admin]: t('bbb', 'admin'),
14+
[Permission.Moderator]: t('bbb', 'moderator'),
15+
[Permission.User]: t('bbb', 'user'),
16+
};

ts/Manager/App.scss

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,23 @@ pre {
161161
.bbb-shrink {
162162
width: 44px;
163163
white-space: nowrap;
164-
}
165164

165+
input[type="checkbox"]{
166+
167+
&+label:before {
168+
border-radius: 3px;
169+
border-width: 2px;
170+
}
171+
172+
&:disabled+label:before {
173+
opacity: .5;
174+
}
175+
176+
&:not(input:checked):disabled+label:before {
177+
background-color: transparent !important;
178+
}
179+
}
180+
}
166181

167182
th {
168183
padding: 14px 6px;
@@ -282,6 +297,10 @@ pre {
282297
}
283298
}
284299

300+
.bbb-simple-menu {
301+
min-width: auto;
302+
}
303+
285304
.bbb-input-container {
286305
display: flex;
287306
}

0 commit comments

Comments
 (0)