mirror of https://github.com/sualko/cloud_bbb
parent
bee124d19f
commit
ad7eedf14b
|
@ -2,17 +2,29 @@
|
||||||
|
|
||||||
namespace OCA\BigBlueButton\Controller;
|
namespace OCA\BigBlueButton\Controller;
|
||||||
|
|
||||||
|
use OCA\BigBlueButton\Service\RoomService;
|
||||||
|
use OCA\BigBlueButton\Permission;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
|
use OCP\AppFramework\Http;
|
||||||
use OCP\AppFramework\Http\DataResponse;
|
use OCP\AppFramework\Http\DataResponse;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\IGroupManager;
|
||||||
use OCA\BigBlueButton\Service\RoomService;
|
use OCP\IUserManager;
|
||||||
|
|
||||||
class RoomController extends Controller
|
class RoomController extends Controller
|
||||||
{
|
{
|
||||||
/** @var RoomService */
|
/** @var RoomService */
|
||||||
private $service;
|
private $service;
|
||||||
|
|
||||||
|
/** @var IUserManager */
|
||||||
|
private $userManager;
|
||||||
|
|
||||||
|
/** @var IGroupManager */
|
||||||
|
private $groupManager;
|
||||||
|
|
||||||
|
/** @var Permission */
|
||||||
|
private $permission;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $userId;
|
private $userId;
|
||||||
|
|
||||||
|
@ -22,10 +34,16 @@ class RoomController extends Controller
|
||||||
$appName,
|
$appName,
|
||||||
IRequest $request,
|
IRequest $request,
|
||||||
RoomService $service,
|
RoomService $service,
|
||||||
|
IUserManager $userManager,
|
||||||
|
IGroupManager $groupManager,
|
||||||
|
Permission $permission,
|
||||||
$userId
|
$userId
|
||||||
) {
|
) {
|
||||||
parent::__construct($appName, $request);
|
parent::__construct($appName, $request);
|
||||||
$this->service = $service;
|
$this->service = $service;
|
||||||
|
$this->userManager = $userManager;
|
||||||
|
$this->groupManager = $groupManager;
|
||||||
|
$this->permission = $permission;
|
||||||
$this->userId = $userId;
|
$this->userId = $userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,17 +52,10 @@ class RoomController extends Controller
|
||||||
*/
|
*/
|
||||||
public function index(): DataResponse
|
public function index(): DataResponse
|
||||||
{
|
{
|
||||||
return new DataResponse($this->service->findAll($this->userId));
|
$user = $this->userManager->get($this->userId);
|
||||||
}
|
$groupIds = $this->groupManager->getUserGroupIds($user);
|
||||||
|
|
||||||
/**
|
return new DataResponse($this->service->findAll($this->userId, $groupIds));
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function show(int $id): DataResponse
|
|
||||||
{
|
|
||||||
return $this->handleNotFound(function () use ($id) {
|
|
||||||
return $this->service->find($id, $this->userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,8 +88,14 @@ class RoomController extends Controller
|
||||||
string $access,
|
string $access,
|
||||||
bool $everyoneIsModerator
|
bool $everyoneIsModerator
|
||||||
): DataResponse {
|
): DataResponse {
|
||||||
|
$room = $this->service->find($id);
|
||||||
|
|
||||||
|
if (!$this->permission->isAdmin($room, $this->userId)) {
|
||||||
|
return new DataResponse(null, Http::STATUS_FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->handleNotFound(function () use ($id, $name, $welcome, $maxParticipants, $record, $everyoneIsModerator, $access) {
|
return $this->handleNotFound(function () use ($id, $name, $welcome, $maxParticipants, $record, $everyoneIsModerator, $access) {
|
||||||
return $this->service->update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $this->userId);
|
return $this->service->update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +104,15 @@ class RoomController extends Controller
|
||||||
*/
|
*/
|
||||||
public function destroy(int $id): DataResponse
|
public function destroy(int $id): DataResponse
|
||||||
{
|
{
|
||||||
|
$room = $this->service->find($id);
|
||||||
|
|
||||||
|
if (!$this->permission->isAdmin($room, $this->userId)) {
|
||||||
|
return new DataResponse(null, Http::STATUS_FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->handleNotFound(function () use ($id) {
|
return $this->handleNotFound(function () use ($id) {
|
||||||
return $this->service->delete($id, $this->userId);
|
//@TODO delete shares
|
||||||
|
return $this->service->delete($id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,9 +143,9 @@ class RoomShareController extends Controller
|
||||||
private function isUserAllowed(int $roomId): bool
|
private function isUserAllowed(int $roomId): bool
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$room = $this->roomService->find($roomId, $this->userId);
|
$room = $this->roomService->find($roomId);
|
||||||
|
|
||||||
return $room !== null;
|
return $room->getUserId() === $this->userId;
|
||||||
} catch (RoomShareNotFound $e) {
|
} catch (RoomShareNotFound $e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace OCA\BigBlueButton\Controller;
|
namespace OCA\BigBlueButton\Controller;
|
||||||
|
|
||||||
use OCA\BigBlueButton\BigBlueButton\API;
|
use OCA\BigBlueButton\BigBlueButton\API;
|
||||||
|
use OCA\BigBlueButton\Permission;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
use OCP\AppFramework\Http\DataResponse;
|
use OCP\AppFramework\Http\DataResponse;
|
||||||
|
@ -18,6 +19,9 @@ class ServerController extends Controller
|
||||||
/** @var API */
|
/** @var API */
|
||||||
private $server;
|
private $server;
|
||||||
|
|
||||||
|
/** @var Permission */
|
||||||
|
private $permission;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $userId;
|
private $userId;
|
||||||
|
|
||||||
|
@ -26,12 +30,14 @@ class ServerController extends Controller
|
||||||
IRequest $request,
|
IRequest $request,
|
||||||
RoomService $service,
|
RoomService $service,
|
||||||
API $server,
|
API $server,
|
||||||
|
Permission $permission,
|
||||||
$UserId
|
$UserId
|
||||||
) {
|
) {
|
||||||
parent::__construct($appName, $request);
|
parent::__construct($appName, $request);
|
||||||
|
|
||||||
$this->service = $service;
|
$this->service = $service;
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
|
$this->permission = $permission;
|
||||||
$this->userId = $UserId;
|
$this->userId = $UserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +52,7 @@ class ServerController extends Controller
|
||||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($room->userId !== $this->userId) {
|
if (!$this->permission->isAdmin($room, $this->userId)) {
|
||||||
return new DataResponse([], Http::STATUS_FORBIDDEN);
|
return new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +74,7 @@ class ServerController extends Controller
|
||||||
return new DataResponse(false, Http::STATUS_NOT_FOUND);
|
return new DataResponse(false, Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($room->userId !== $this->userId) {
|
if (!$this->permission->isAdmin($room, $this->userId)) {
|
||||||
return new DataResponse(false, Http::STATUS_FORBIDDEN);
|
return new DataResponse(false, Http::STATUS_FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ class Room extends Entity implements JsonSerializable
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'uid' => $this->uid,
|
'uid' => $this->uid,
|
||||||
|
'userId' => $this->userId,
|
||||||
'name' => $this->name,
|
'name' => $this->name,
|
||||||
'welcome' => $this->welcome,
|
'welcome' => $this->welcome,
|
||||||
'maxParticipants' => (int) $this->maxParticipants,
|
'maxParticipants' => (int) $this->maxParticipants,
|
||||||
|
|
|
@ -21,14 +21,13 @@ class RoomMapper extends QBMapper
|
||||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||||
* @throws DoesNotExistException
|
* @throws DoesNotExistException
|
||||||
*/
|
*/
|
||||||
public function find(int $id, string $userId): Room
|
public function find(int $id): Room
|
||||||
{
|
{
|
||||||
/* @var $qb IQueryBuilder */
|
/* @var $qb IQueryBuilder */
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->select('*')
|
$qb->select('*')
|
||||||
->from('bbb_rooms')
|
->from($this->tableName)
|
||||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)))
|
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
|
||||||
->andWhere($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
|
|
||||||
return $this->findEntity($qb);
|
return $this->findEntity($qb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,22 +42,39 @@ class RoomMapper extends QBMapper
|
||||||
/* @var $qb IQueryBuilder */
|
/* @var $qb IQueryBuilder */
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->select('*')
|
$qb->select('*')
|
||||||
->from('bbb_rooms')
|
->from($this->tableName)
|
||||||
->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
|
->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
|
||||||
return $this->findEntity($qb);
|
return $this->findEntity($qb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $userId
|
* @param int $userId
|
||||||
|
* @param array $groupIds
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function findAll(string $userId): array
|
public function findAll(string $userId, array $groupIds): array
|
||||||
{
|
{
|
||||||
/* @var $qb IQueryBuilder */
|
/* @var $qb IQueryBuilder */
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->select('*')
|
$qb->select('r.*')
|
||||||
->from('bbb_rooms')
|
->from($this->tableName, 'r')
|
||||||
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
|
->leftJoin('r', 'bbb_room_shares', 's', $qb->expr()->eq('r.id', 's.room_id'))
|
||||||
|
->where(
|
||||||
|
$qb->expr()->orX(
|
||||||
|
$qb->expr()->eq('r.user_id', $qb->createNamedParameter($userId)),
|
||||||
|
$qb->expr()->andX(
|
||||||
|
$qb->expr()->eq('s.permission', $qb->createNamedParameter(RoomShare::PERMISSION_ADMIN, IQueryBuilder::PARAM_INT)),
|
||||||
|
$qb->expr()->eq('s.share_type', $qb->createNamedParameter(RoomShare::SHARE_TYPE_USER, IQueryBuilder::PARAM_INT)),
|
||||||
|
$qb->expr()->eq('s.share_with', $qb->createNamedParameter($userId))
|
||||||
|
),
|
||||||
|
$qb->expr()->andX(
|
||||||
|
$qb->expr()->eq('s.permission', $qb->createNamedParameter(RoomShare::PERMISSION_ADMIN, IQueryBuilder::PARAM_INT)),
|
||||||
|
$qb->expr()->eq('s.share_type', $qb->createNamedParameter(RoomShare::SHARE_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
|
||||||
|
$qb->expr()->in('s.share_with', $groupIds)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->groupBy('r.id');
|
||||||
return $this->findEntities($qb);
|
return $this->findEntities($qb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||||
|
|
||||||
use OCA\BigBlueButton\Db\Room;
|
use OCA\BigBlueButton\Db\Room;
|
||||||
use OCA\BigBlueButton\Db\RoomMapper;
|
use OCA\BigBlueButton\Db\RoomMapper;
|
||||||
|
use OCA\BigBlueButton\NoPermissionException;
|
||||||
|
|
||||||
class RoomService
|
class RoomService
|
||||||
{
|
{
|
||||||
|
@ -20,9 +21,9 @@ class RoomService
|
||||||
$this->mapper = $mapper;
|
$this->mapper = $mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findAll(string $userId): array
|
public function findAll(string $userId, array $groupIds): array
|
||||||
{
|
{
|
||||||
return $this->mapper->findAll($userId);
|
return $this->mapper->findAll($userId, $groupIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleException(Exception $e): void
|
private function handleException(Exception $e): void
|
||||||
|
@ -35,10 +36,10 @@ class RoomService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function find($id, $userId)
|
public function find($id): Room
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return $this->mapper->find($id, $userId);
|
return $this->mapper->find($id);
|
||||||
|
|
||||||
// in order to be able to plug in different storage backends like files
|
// in order to be able to plug in different storage backends like files
|
||||||
// for instance it is a good idea to turn storage related exceptions
|
// for instance it is a good idea to turn storage related exceptions
|
||||||
|
@ -75,10 +76,10 @@ class RoomService
|
||||||
return $this->mapper->insert($room);
|
return $this->mapper->insert($room);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator, $userId)
|
public function update($id, $name, $welcome, $maxParticipants, $record, $access, $everyoneIsModerator)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$room = $this->mapper->find($id, $userId);
|
$room = $this->mapper->find($id);
|
||||||
|
|
||||||
if ($room->access !== $access) {
|
if ($room->access !== $access) {
|
||||||
$room->setPassword($access === Room::ACCESS_PASSWORD ? $this->humanReadableRandom(8) : null);
|
$room->setPassword($access === Room::ACCESS_PASSWORD ? $this->humanReadableRandom(8) : null);
|
||||||
|
@ -90,7 +91,6 @@ class RoomService
|
||||||
$room->setRecord($record);
|
$room->setRecord($record);
|
||||||
$room->setAccess($access);
|
$room->setAccess($access);
|
||||||
$room->setEveryoneIsModerator($everyoneIsModerator);
|
$room->setEveryoneIsModerator($everyoneIsModerator);
|
||||||
$room->setUserId($userId);
|
|
||||||
|
|
||||||
return $this->mapper->update($room);
|
return $this->mapper->update($room);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
@ -98,10 +98,10 @@ class RoomService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($id, $userId)
|
public function delete($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$room = $this->mapper->find($id, $userId);
|
$room = $this->mapper->find($id);
|
||||||
$this->mapper->delete($room);
|
$this->mapper->delete($room);
|
||||||
return $room;
|
return $room;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
|
|
@ -21,6 +21,8 @@ class RoomShareControllerTest extends TestCase
|
||||||
private $userManager;
|
private $userManager;
|
||||||
private $controller;
|
private $controller;
|
||||||
|
|
||||||
|
private $userId = 'user_foo';
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
@ -36,7 +38,7 @@ class RoomShareControllerTest extends TestCase
|
||||||
$this->service,
|
$this->service,
|
||||||
$this->userManager,
|
$this->userManager,
|
||||||
$this->roomService,
|
$this->roomService,
|
||||||
'user_foo'
|
$this->userId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,10 +57,14 @@ class RoomShareControllerTest extends TestCase
|
||||||
->with('id')
|
->with('id')
|
||||||
->willReturn(1234);
|
->willReturn(1234);
|
||||||
|
|
||||||
|
$room = new Room();
|
||||||
|
$room->setUserId('user_bar');
|
||||||
|
|
||||||
$this->roomService
|
$this->roomService
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('find')
|
->method('find')
|
||||||
->will($this->throwException(new RoomShareNotFound));
|
->with(1234)
|
||||||
|
->willReturn($room);
|
||||||
|
|
||||||
$response = $this->controller->index();
|
$response = $this->controller->index();
|
||||||
|
|
||||||
|
@ -74,10 +80,13 @@ class RoomShareControllerTest extends TestCase
|
||||||
->with('id')
|
->with('id')
|
||||||
->willReturn($roomId);
|
->willReturn($roomId);
|
||||||
|
|
||||||
|
$room = new Room();
|
||||||
|
$room->setUserId($this->userId);
|
||||||
|
|
||||||
$this->roomService
|
$this->roomService
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('find')
|
->method('find')
|
||||||
->willReturn(new Room());
|
->willReturn($room);
|
||||||
|
|
||||||
$this->service
|
$this->service
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
|
@ -100,10 +109,13 @@ class RoomShareControllerTest extends TestCase
|
||||||
->with('id')
|
->with('id')
|
||||||
->willReturn($roomId);
|
->willReturn($roomId);
|
||||||
|
|
||||||
|
$room = new Room();
|
||||||
|
$room->setUserId($this->userId);
|
||||||
|
|
||||||
$this->roomService
|
$this->roomService
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('find')
|
->method('find')
|
||||||
->willReturn(new Room());
|
->willReturn($room);
|
||||||
|
|
||||||
$this->service
|
$this->service
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
|
|
|
@ -15,6 +15,7 @@ export enum Access {
|
||||||
export interface Room {
|
export interface Room {
|
||||||
id: number;
|
id: number;
|
||||||
uid: string;
|
uid: string;
|
||||||
|
userId: string;
|
||||||
name: string;
|
name: string;
|
||||||
welcome: string;
|
welcome: string;
|
||||||
maxParticipants: number;
|
maxParticipants: number;
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bbb-avatar {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
#bbb-warning {
|
#bbb-warning {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
background-color: rgb(255, 255, 123);
|
background-color: rgb(255, 255, 123);
|
||||||
|
|
|
@ -107,6 +107,7 @@ const App: React.FC<Props> = () => {
|
||||||
<th onClick={() => onOrderBy('name')}>
|
<th onClick={() => onOrderBy('name')}>
|
||||||
{t('bbb', 'Name')} <SortArrow name='name' value={orderBy} direction={sortOrder} />
|
{t('bbb', 'Name')} <SortArrow name='name' value={orderBy} direction={sortOrder} />
|
||||||
</th>
|
</th>
|
||||||
|
<th />
|
||||||
<th onClick={() => onOrderBy('maxParticipants')}>
|
<th onClick={() => onOrderBy('maxParticipants')}>
|
||||||
{t('bbb', 'Max')} <SortArrow name='maxParticipants' value={orderBy} direction={sortOrder} />
|
{t('bbb', 'Max')} <SortArrow name='maxParticipants' value={orderBy} direction={sortOrder} />
|
||||||
</th>
|
</th>
|
||||||
|
|
|
@ -158,6 +158,12 @@ const RoomRow: React.FC<Props> = (props) => {
|
||||||
return <EditableValue field={field} value={room[field]} setValue={updateRoom} type={type} />;
|
return <EditableValue field={field} value={room[field]} setValue={updateRoom} type={type} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const avatarUrl = OC.generateUrl('/avatar/' + encodeURIComponent(room.userId) + '/' + 24, {
|
||||||
|
user: room.userId,
|
||||||
|
size: 24,
|
||||||
|
requesttoken: OC.requestToken,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<tr className={showRecordings ? 'selected-row' : ''}>
|
<tr className={showRecordings ? 'selected-row' : ''}>
|
||||||
|
@ -175,6 +181,9 @@ const RoomRow: React.FC<Props> = (props) => {
|
||||||
<td className="name">
|
<td className="name">
|
||||||
{edit('name')}
|
{edit('name')}
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{room.userId !== OC.currentUser && <img src={avatarUrl} alt="Avatar" className="bbb-avatar" />}
|
||||||
|
</td>
|
||||||
<td className="max-participants">
|
<td className="max-participants">
|
||||||
{edit('maxParticipants', 'number')}
|
{edit('maxParticipants', 'number')}
|
||||||
</td>
|
</td>
|
||||||
|
@ -193,7 +202,7 @@ const RoomRow: React.FC<Props> = (props) => {
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{showRecordings && <tr className="recordings-row">
|
{showRecordings && <tr className="recordings-row">
|
||||||
<td colSpan={9}>
|
<td colSpan={10}>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{recordings?.map(recording => <RecordingRow key={recording.id} recording={recording} deleteRecording={deleteRecording} storeRecording={storeRecording} />)}
|
{recordings?.map(recording => <RecordingRow key={recording.id} recording={recording} deleteRecording={deleteRecording} storeRecording={storeRecording} />)}
|
||||||
|
|
|
@ -62,3 +62,11 @@
|
||||||
.bbb-form-shareWith {
|
.bbb-form-shareWith {
|
||||||
margin-top: -1.5em;
|
margin-top: -1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bbb-icon-unselected {
|
||||||
|
opacity: 0.2 !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.5 !important;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,8 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
const [recommendations, setRecommendations] = useState<ShareWith>();
|
const [recommendations, setRecommendations] = useState<ShareWith>();
|
||||||
const [searchResults, setSearchResults] = useState<ShareWith>();
|
const [searchResults, setSearchResults] = useState<ShareWith>();
|
||||||
|
|
||||||
|
const isOwner = room.userId === OC.currentUser;
|
||||||
|
|
||||||
const shares = (allShares && permission === Permission.Moderator) ?
|
const shares = (allShares && permission === Permission.Moderator) ?
|
||||||
allShares.filter(share => share.permission !== Permission.User) : allShares;
|
allShares.filter(share => share.permission !== Permission.User) : allShares;
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
api.getRecommendedShareWith().then(result => setRecommendations(result));
|
api.getRecommendedShareWith().then(result => setRecommendations(result));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
async function addRoomShare(shareWith: string, shareType: number, displayName: string) {
|
async function addRoomShare(shareWith: string, shareType: number, displayName: string, permission: Permission) {
|
||||||
const roomShare = await api.createRoomShare(room.id, shareType, shareWith, permission);
|
const roomShare = await api.createRoomShare(room.id, shareType, shareWith, permission);
|
||||||
|
|
||||||
roomShare.shareWithDisplayName = displayName;
|
roomShare.shareWithDisplayName = displayName;
|
||||||
|
@ -60,6 +62,12 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
setShares((allShares ? [...allShares] : []).filter(share => share.id !== id));
|
setShares((allShares ? [...allShares] : []).filter(share => share.id !== id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function toggleAdminShare(share: RoomShare) {
|
||||||
|
const newPermission = share.permission === Permission.Admin ? Permission.Moderator : Permission.Admin;
|
||||||
|
|
||||||
|
return addRoomShare(share.shareWith, share.shareType, share.shareWithDisplayName || share.shareWith, newPermission);
|
||||||
|
}
|
||||||
|
|
||||||
function renderSearchResults(options: ShareWith) {
|
function renderSearchResults(options: ShareWith) {
|
||||||
return (
|
return (
|
||||||
<ul className="bbb-selection">
|
<ul className="bbb-selection">
|
||||||
|
@ -67,7 +75,7 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
...options.users.filter(user => !sharedUserIds.includes(user.value.shareWith)),
|
...options.users.filter(user => !sharedUserIds.includes(user.value.shareWith)),
|
||||||
...options.groups.filter(group => !sharedGroupIds.includes(group.value.shareWith)),
|
...options.groups.filter(group => !sharedGroupIds.includes(group.value.shareWith)),
|
||||||
].map(option => {
|
].map(option => {
|
||||||
return (<li key={option.value.shareWith} onClick={() => addRoomShare(option.value.shareWith, option.value.shareType, option.label)}>
|
return (<li key={option.value.shareWith} onClick={() => addRoomShare(option.value.shareWith, option.value.shareType, option.label, permission)}>
|
||||||
{option.label}{option.value.shareType === ShareType.Group ? ` (${t('bbb', 'Group')})` : ''}
|
{option.label}{option.value.shareType === ShareType.Group ? ` (${t('bbb', 'Group')})` : ''}
|
||||||
</li>);
|
</li>);
|
||||||
})}
|
})}
|
||||||
|
@ -103,9 +111,16 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
{share.shareType === ShareType.Group && <span className="icon-group-white"></span>}
|
{share.shareType === ShareType.Group && <span className="icon-group-white"></span>}
|
||||||
</div>
|
</div>
|
||||||
<div className="bbb-shareWith__item__label">
|
<div className="bbb-shareWith__item__label">
|
||||||
<h5>{displayName}{(share.permission === Permission.Moderator && permission === Permission.User) ? ` (${t('bbb', 'moderator')})` : ''}</h5>
|
<h5>{displayName}
|
||||||
|
{(share.permission === Permission.Moderator && permission === Permission.User) && ` (${t('bbb', 'moderator')})`}
|
||||||
|
{(share.permission === Permission.Admin) && ` (${t('bbb', 'admin')})`}</h5>
|
||||||
</div>
|
</div>
|
||||||
{share.id > -1 && <div className="bbb-shareWith__item__action">
|
{(share.id > -1 && permission === Permission.Moderator && isOwner) && <div className="bbb-shareWith__item__action">
|
||||||
|
<a className={`icon icon-shared icon-visible ${share.permission === Permission.Admin ? 'bbb-icon-selected' : 'bbb-icon-unselected'}`}
|
||||||
|
onClick={ev => {ev.preventDefault(); toggleAdminShare(share);}}
|
||||||
|
title={t('bbb', 'Share')} />
|
||||||
|
</div>}
|
||||||
|
{(share.id > -1 && isOwner) && <div className="bbb-shareWith__item__action">
|
||||||
<a className="icon icon-delete icon-visible"
|
<a className="icon icon-delete icon-visible"
|
||||||
onClick={ev => {ev.preventDefault(); deleteRoomShare(share.id);}}
|
onClick={ev => {ev.preventDefault(); deleteRoomShare(share.id);}}
|
||||||
title={t('bbb', 'Delete')} />
|
title={t('bbb', 'Delete')} />
|
||||||
|
@ -124,13 +139,14 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
|
||||||
{shares ? renderShares(shares) : loading}
|
{shares ? renderShares(shares) : loading}
|
||||||
|
|
||||||
<div className="bbb-selection-container">
|
<div className="bbb-selection-container">
|
||||||
<input
|
{isOwner ? <input
|
||||||
type="text"
|
type="text"
|
||||||
value={search}
|
value={search}
|
||||||
onChange={ev => setSearch(ev.currentTarget.value)}
|
onChange={ev => setSearch(ev.currentTarget.value)}
|
||||||
onFocus={() => setFocus(true)}
|
onFocus={() => setFocus(true)}
|
||||||
onBlur={() => setTimeout(() => setFocus(false), 100)}
|
onBlur={() => setTimeout(() => setFocus(false), 100)}
|
||||||
placeholder={t('bbb', 'Name, group, ...')} />
|
placeholder={t('bbb', 'Name, group, ...')} /> :
|
||||||
|
<em><span className="icon icon-details icon-visible"></span> {t('bbb', 'You are not allowed to change this option, because this room is shared with you.')}</em>}
|
||||||
{hasFocus && (searchResults ? renderSearchResults(searchResults) : (recommendations ? renderSearchResults(recommendations) : loading))}
|
{hasFocus && (searchResults ? renderSearchResults(searchResults) : (recommendations ? renderSearchResults(recommendations) : loading))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
Loading…
Reference in New Issue