mirror of https://github.com/sualko/cloud_bbb
Compare commits
19 Commits
f1033dceea
...
66150997b1
Author | SHA1 | Date |
---|---|---|
|
66150997b1 | |
|
e5bfcc8ec8 | |
|
dede2b2857 | |
|
3c45a93ece | |
|
31bc8aeea1 | |
|
ad65b6803f | |
|
a00708ffa3 | |
|
95f9425a80 | |
|
1b15353dcb | |
|
79518b9bac | |
|
ab80d613e7 | |
|
da0cc79b9e | |
|
71fe272888 | |
|
323e9df9f4 | |
|
7233d21a85 | |
|
a9082d3a46 | |
|
b7a864c658 | |
|
2f288e34c0 | |
|
093e286e0f |
|
@ -11,13 +11,23 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
php-versions: ['7.4', '8']
|
php-versions: ['7.4', '8.0', '8.1', '8.2', '8.3']
|
||||||
nextcloud-versions: ['stable25', 'stable26', 'stable27']
|
nextcloud-versions: ['stable25', 'stable26', 'stable27', 'stable28']
|
||||||
exclude:
|
exclude:
|
||||||
- php-versions: '7.4'
|
- php-versions: '7.4'
|
||||||
nextcloud-versions: 'stable26'
|
nextcloud-versions: 'stable26'
|
||||||
- php-versions: '7.4'
|
- php-versions: '7.4'
|
||||||
nextcloud-versions: 'stable27'
|
nextcloud-versions: 'stable27'
|
||||||
|
- php-versions: '7.4'
|
||||||
|
nextcloud-versions: 'stable28'
|
||||||
|
- php-versions: '8.2'
|
||||||
|
nextcloud-versions: 'stable25'
|
||||||
|
- php-versions: '8.3'
|
||||||
|
nextcloud-versions: 'stable25'
|
||||||
|
- php-versions: '8.3'
|
||||||
|
nextcloud-versions: 'stable26'
|
||||||
|
- php-versions: '8.3'
|
||||||
|
nextcloud-versions: 'stable27'
|
||||||
name: php${{ matrix.php-versions }} on ${{ matrix.nextcloud-versions }} unit tests
|
name: php${{ matrix.php-versions }} on ${{ matrix.nextcloud-versions }} unit tests
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
|
|
|
@ -58,6 +58,7 @@ OC.L10N.register(
|
||||||
"No matches" : "Nessuna corrispondenza",
|
"No matches" : "Nessuna corrispondenza",
|
||||||
"admin" : "amministratore",
|
"admin" : "amministratore",
|
||||||
"moderator" : "moderatore",
|
"moderator" : "moderatore",
|
||||||
|
"user" : "utente",
|
||||||
"Name" : "Nome",
|
"Name" : "Nome",
|
||||||
"Access" : "Accesso",
|
"Access" : "Accesso",
|
||||||
"Max" : "Massimo",
|
"Max" : "Massimo",
|
||||||
|
@ -71,6 +72,7 @@ OC.L10N.register(
|
||||||
"This message is shown to all users in the chat area after they joined." : "Questo messaggio è mostrato a tutti gli utenti nell'area di chat dopo il loro ingresso.",
|
"This message is shown to all users in the chat area after they joined." : "Questo messaggio è mostrato a tutti gli utenti nell'area di chat dopo il loro ingresso.",
|
||||||
"Sets a limit on the number of participants for this room. Zero means there is no limit." : "Imposta un limite sul numero di partecipanti per questa stanza. Zero significa che non ci sono limiti.",
|
"Sets a limit on the number of participants for this room. Zero means there is no limit." : "Imposta un limite sul numero di partecipanti per questa stanza. Zero significa che non ci sono limiti.",
|
||||||
"If enabled, the moderator is able to start the recording." : "Se abilitata, il moderatore è in grado di avviare la registrazione.",
|
"If enabled, the moderator is able to start the recording." : "Se abilitata, il moderatore è in grado di avviare la registrazione.",
|
||||||
|
"Explanation of the different concepts that constitute access options :<br>- Public: Anyone who has the link can join.- <br>Internal: Only Nextcloud users can join.- <br>Password: Only guests who have the password can join..- <br>Waiting room: A moderator must accept each guest before they can join.- <br>Restricted : Only selected users and groups can access this room." : "Spiegazione dei diversi concetti che costituiscono l'accesso :<br>- Pubblico: chiunque abbia il link può partecipare.-<br>Interno: possono partecipare solo gli utenti Nextcloud.-<br>Password: possono partecipare solo gli ospiti che hanno la password..- <br>Sala d'attesa: un moderatore deve accettare ogni ospite prima che possa partecipare.- <br>Limitato: solo gli utenti e i gruppi selezionati possono accedere a questa stanza.",
|
||||||
"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." : "Un moderatore è in grado di gestire tutti i partecipanti a una riunione, inclusa l'espulsione, il silenziamento o la selezione di un relatore. Gli utenti con il ruolo di moderatore possono anche chiudere una riunione o modificare le impostazioni predefinite.",
|
"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." : "Un moderatore è in grado di gestire tutti i partecipanti a una riunione, inclusa l'espulsione, il silenziamento o la selezione di un relatore. Gli utenti con il ruolo di moderatore possono anche chiudere una riunione o modificare le impostazioni predefinite.",
|
||||||
"If enabled, normal users have to wait until a moderator is in the room." : "Se abilitata, gli utenti normali devono attendere fino a quando un moderatore è nella stanza.",
|
"If enabled, normal users have to wait until a moderator is in the room." : "Se abilitata, gli utenti normali devono attendere fino a quando un moderatore è nella stanza.",
|
||||||
"If enabled, a moderator URL is generated which allows access with moderator permission." : "Se abilitata, viene generato un URL moderatore che consente l'accesso con l'autorizzazione del moderatore.",
|
"If enabled, a moderator URL is generated which allows access with moderator permission." : "Se abilitata, viene generato un URL moderatore che consente l'accesso con l'autorizzazione del moderatore.",
|
||||||
|
@ -114,7 +116,10 @@ OC.L10N.register(
|
||||||
"Delete?" : "Vuoi eliminare?",
|
"Delete?" : "Vuoi eliminare?",
|
||||||
"Could not delete record" : "Impossibile eliminare il record",
|
"Could not delete record" : "Impossibile eliminare il record",
|
||||||
"Server error" : "Errore del server",
|
"Server error" : "Errore del server",
|
||||||
|
"Could not modify publishing state" : "Impossibile modificare lo stato di pubblicazione",
|
||||||
|
"Open room" : "Stanza aperta",
|
||||||
"Start" : "Avvia",
|
"Start" : "Avvia",
|
||||||
|
"Clone room" : "Clona stanza",
|
||||||
"Loading" : "Caricamento",
|
"Loading" : "Caricamento",
|
||||||
"You are not allowed to change this option, because this room is shared with you." : "Non ti è consentito modificare questa opzione, poiché questa stanza è condivisa con te.",
|
"You are not allowed to change this option, because this room is shared with you." : "Non ti è consentito modificare questa opzione, poiché questa stanza è condivisa con te.",
|
||||||
"Max. rooms" : "Num. massimo stanze",
|
"Max. rooms" : "Num. massimo stanze",
|
||||||
|
@ -130,8 +135,12 @@ OC.L10N.register(
|
||||||
"URL has to start with HTTPS" : "L'URL deve iniziare con HTTPS",
|
"URL has to start with HTTPS" : "L'URL deve iniziare con HTTPS",
|
||||||
"URL has to contain the {token} placeholder" : "L'URL deve contenere il segnaposto {token}",
|
"URL has to contain the {token} placeholder" : "L'URL deve contenere il segnaposto {token}",
|
||||||
"URL has to start with https:// and contain {token}. Additionally the {user} placeholder can be used." : "L'URL deve iniziare con https: // e contenere {token}. Inoltre è possibile utilizzare il segnaposto {user}.",
|
"URL has to start with https:// and contain {token}. Additionally the {user} placeholder can be used." : "L'URL deve iniziare con https: // e contenere {token}. Inoltre è possibile utilizzare il segnaposto {user}.",
|
||||||
|
"The file \"{filename}\" was uploaded to your room." : "Il file \"{filename}\" è stato caricato nella tua stanza.",
|
||||||
|
"The file \"{filename}\" could not be uploaded to your room." : "Il file \"{filename}\" non è stato possibile caricarlo nella tua stanza.",
|
||||||
|
"The file \"{filename}\" could not be uploaded to your room. Maybe your BigBlueButton server does not support this action." : "Il file \"{filename}\" non può essere caricato nella tua stanza. Forse il tuo server BigBlueButton non supporta questa azione.",
|
||||||
"Send file to BBB" : "Invia file a BBB",
|
"Send file to BBB" : "Invia file a BBB",
|
||||||
"Send to" : "Invia a",
|
"Send to" : "Invia a",
|
||||||
|
"Start with" : "Inizia con",
|
||||||
"Please select the room in which you like to use the file \"{filename}\"." : "Seleziona la stanza in cui vorresti usare il file \"{filename}\".",
|
"Please select the room in which you like to use the file \"{filename}\"." : "Seleziona la stanza in cui vorresti usare il file \"{filename}\".",
|
||||||
"No rooms available!" : "Nessuna stanza disponibile",
|
"No rooms available!" : "Nessuna stanza disponibile",
|
||||||
"Send to BBB" : "Invia a BBB",
|
"Send to BBB" : "Invia a BBB",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"No matches" : "Nessuna corrispondenza",
|
"No matches" : "Nessuna corrispondenza",
|
||||||
"admin" : "amministratore",
|
"admin" : "amministratore",
|
||||||
"moderator" : "moderatore",
|
"moderator" : "moderatore",
|
||||||
|
"user" : "utente",
|
||||||
"Name" : "Nome",
|
"Name" : "Nome",
|
||||||
"Access" : "Accesso",
|
"Access" : "Accesso",
|
||||||
"Max" : "Massimo",
|
"Max" : "Massimo",
|
||||||
|
@ -69,6 +70,7 @@
|
||||||
"This message is shown to all users in the chat area after they joined." : "Questo messaggio è mostrato a tutti gli utenti nell'area di chat dopo il loro ingresso.",
|
"This message is shown to all users in the chat area after they joined." : "Questo messaggio è mostrato a tutti gli utenti nell'area di chat dopo il loro ingresso.",
|
||||||
"Sets a limit on the number of participants for this room. Zero means there is no limit." : "Imposta un limite sul numero di partecipanti per questa stanza. Zero significa che non ci sono limiti.",
|
"Sets a limit on the number of participants for this room. Zero means there is no limit." : "Imposta un limite sul numero di partecipanti per questa stanza. Zero significa che non ci sono limiti.",
|
||||||
"If enabled, the moderator is able to start the recording." : "Se abilitata, il moderatore è in grado di avviare la registrazione.",
|
"If enabled, the moderator is able to start the recording." : "Se abilitata, il moderatore è in grado di avviare la registrazione.",
|
||||||
|
"Explanation of the different concepts that constitute access options :<br>- Public: Anyone who has the link can join.- <br>Internal: Only Nextcloud users can join.- <br>Password: Only guests who have the password can join..- <br>Waiting room: A moderator must accept each guest before they can join.- <br>Restricted : Only selected users and groups can access this room." : "Spiegazione dei diversi concetti che costituiscono l'accesso :<br>- Pubblico: chiunque abbia il link può partecipare.-<br>Interno: possono partecipare solo gli utenti Nextcloud.-<br>Password: possono partecipare solo gli ospiti che hanno la password..- <br>Sala d'attesa: un moderatore deve accettare ogni ospite prima che possa partecipare.- <br>Limitato: solo gli utenti e i gruppi selezionati possono accedere a questa stanza.",
|
||||||
"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." : "Un moderatore è in grado di gestire tutti i partecipanti a una riunione, inclusa l'espulsione, il silenziamento o la selezione di un relatore. Gli utenti con il ruolo di moderatore possono anche chiudere una riunione o modificare le impostazioni predefinite.",
|
"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." : "Un moderatore è in grado di gestire tutti i partecipanti a una riunione, inclusa l'espulsione, il silenziamento o la selezione di un relatore. Gli utenti con il ruolo di moderatore possono anche chiudere una riunione o modificare le impostazioni predefinite.",
|
||||||
"If enabled, normal users have to wait until a moderator is in the room." : "Se abilitata, gli utenti normali devono attendere fino a quando un moderatore è nella stanza.",
|
"If enabled, normal users have to wait until a moderator is in the room." : "Se abilitata, gli utenti normali devono attendere fino a quando un moderatore è nella stanza.",
|
||||||
"If enabled, a moderator URL is generated which allows access with moderator permission." : "Se abilitata, viene generato un URL moderatore che consente l'accesso con l'autorizzazione del moderatore.",
|
"If enabled, a moderator URL is generated which allows access with moderator permission." : "Se abilitata, viene generato un URL moderatore che consente l'accesso con l'autorizzazione del moderatore.",
|
||||||
|
@ -112,7 +114,10 @@
|
||||||
"Delete?" : "Vuoi eliminare?",
|
"Delete?" : "Vuoi eliminare?",
|
||||||
"Could not delete record" : "Impossibile eliminare il record",
|
"Could not delete record" : "Impossibile eliminare il record",
|
||||||
"Server error" : "Errore del server",
|
"Server error" : "Errore del server",
|
||||||
|
"Could not modify publishing state" : "Impossibile modificare lo stato di pubblicazione",
|
||||||
|
"Open room" : "Stanza aperta",
|
||||||
"Start" : "Avvia",
|
"Start" : "Avvia",
|
||||||
|
"Clone room" : "Clona stanza",
|
||||||
"Loading" : "Caricamento",
|
"Loading" : "Caricamento",
|
||||||
"You are not allowed to change this option, because this room is shared with you." : "Non ti è consentito modificare questa opzione, poiché questa stanza è condivisa con te.",
|
"You are not allowed to change this option, because this room is shared with you." : "Non ti è consentito modificare questa opzione, poiché questa stanza è condivisa con te.",
|
||||||
"Max. rooms" : "Num. massimo stanze",
|
"Max. rooms" : "Num. massimo stanze",
|
||||||
|
@ -128,8 +133,12 @@
|
||||||
"URL has to start with HTTPS" : "L'URL deve iniziare con HTTPS",
|
"URL has to start with HTTPS" : "L'URL deve iniziare con HTTPS",
|
||||||
"URL has to contain the {token} placeholder" : "L'URL deve contenere il segnaposto {token}",
|
"URL has to contain the {token} placeholder" : "L'URL deve contenere il segnaposto {token}",
|
||||||
"URL has to start with https:// and contain {token}. Additionally the {user} placeholder can be used." : "L'URL deve iniziare con https: // e contenere {token}. Inoltre è possibile utilizzare il segnaposto {user}.",
|
"URL has to start with https:// and contain {token}. Additionally the {user} placeholder can be used." : "L'URL deve iniziare con https: // e contenere {token}. Inoltre è possibile utilizzare il segnaposto {user}.",
|
||||||
|
"The file \"{filename}\" was uploaded to your room." : "Il file \"{filename}\" è stato caricato nella tua stanza.",
|
||||||
|
"The file \"{filename}\" could not be uploaded to your room." : "Il file \"{filename}\" non è stato possibile caricarlo nella tua stanza.",
|
||||||
|
"The file \"{filename}\" could not be uploaded to your room. Maybe your BigBlueButton server does not support this action." : "Il file \"{filename}\" non può essere caricato nella tua stanza. Forse il tuo server BigBlueButton non supporta questa azione.",
|
||||||
"Send file to BBB" : "Invia file a BBB",
|
"Send file to BBB" : "Invia file a BBB",
|
||||||
"Send to" : "Invia a",
|
"Send to" : "Invia a",
|
||||||
|
"Start with" : "Inizia con",
|
||||||
"Please select the room in which you like to use the file \"{filename}\"." : "Seleziona la stanza in cui vorresti usare il file \"{filename}\".",
|
"Please select the room in which you like to use the file \"{filename}\"." : "Seleziona la stanza in cui vorresti usare il file \"{filename}\".",
|
||||||
"No rooms available!" : "Nessuna stanza disponibile",
|
"No rooms available!" : "Nessuna stanza disponibile",
|
||||||
"Send to BBB" : "Invia a BBB",
|
"Send to BBB" : "Invia a BBB",
|
||||||
|
|
|
@ -48,7 +48,7 @@ OC.L10N.register(
|
||||||
"Display name" : "显示名称",
|
"Display name" : "显示名称",
|
||||||
"Password" : "密码",
|
"Password" : "密码",
|
||||||
"Join" : "加入",
|
"Join" : "加入",
|
||||||
"Have an account? Log in." : "有一个账户吗?登录。",
|
"Have an account? Log in." : "有一个账号?登录。",
|
||||||
"Hello %s" : "%s 你好",
|
"Hello %s" : "%s 你好",
|
||||||
"Name, group …" : "名称、群组 ...",
|
"Name, group …" : "名称、群组 ...",
|
||||||
"Group" : "群组",
|
"Group" : "群组",
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
"Display name" : "显示名称",
|
"Display name" : "显示名称",
|
||||||
"Password" : "密码",
|
"Password" : "密码",
|
||||||
"Join" : "加入",
|
"Join" : "加入",
|
||||||
"Have an account? Log in." : "有一个账户吗?登录。",
|
"Have an account? Log in." : "有一个账号?登录。",
|
||||||
"Hello %s" : "%s 你好",
|
"Hello %s" : "%s 你好",
|
||||||
"Name, group …" : "名称、群组 ...",
|
"Name, group …" : "名称、群组 ...",
|
||||||
"Group" : "群组",
|
"Group" : "群组",
|
||||||
|
|
|
@ -56,6 +56,8 @@ class Application extends App implements IBootstrap {
|
||||||
|
|
||||||
$context->registerMiddleware(JoinMiddleware::class);
|
$context->registerMiddleware(JoinMiddleware::class);
|
||||||
$context->registerMiddleware(HookMiddleware::class);
|
$context->registerMiddleware(HookMiddleware::class);
|
||||||
|
|
||||||
|
$context->registerCapability(Capabilities::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function boot(IBootContext $context): void {
|
public function boot(IBootContext $context): void {
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\BigBlueButton\AppInfo;
|
||||||
|
|
||||||
|
use OCA\BigBlueButton\Permission;
|
||||||
|
use OCP\App\IAppManager;
|
||||||
|
use OCP\Capabilities\ICapability;
|
||||||
|
use OCP\IUserSession;
|
||||||
|
|
||||||
|
class Capabilities implements ICapability {
|
||||||
|
public function __construct(private IUserSession $userSession, private IAppManager $appManager, private Permission $permission) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCapabilities(): array {
|
||||||
|
$user = $this->userSession->getUser();
|
||||||
|
if (!$user) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$restriction = $this->permission->getRestriction($user->getUID());
|
||||||
|
$capabilities = array_filter($restriction->jsonSerialize(), function ($key) {
|
||||||
|
return in_array($key, ['maxRooms', 'maxParticipants', 'allowRecording']);
|
||||||
|
}, ARRAY_FILTER_USE_KEY);
|
||||||
|
|
||||||
|
return [
|
||||||
|
Application::ID => array_merge([
|
||||||
|
'appVersion' => $this->appManager->getAppVersion(Application::ID),
|
||||||
|
'isAllowedToCreateRoom' => $this->permission->isAllowedToCreateRoom($user->getUID()),
|
||||||
|
], $capabilities)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -118,7 +118,8 @@ class API {
|
||||||
$joinMeetingParams->addUserData('bbb_skip_video_preview_on_first_join', !$room->getMediaCheck()); // 2.3
|
$joinMeetingParams->addUserData('bbb_skip_video_preview_on_first_join', !$room->getMediaCheck()); // 2.3
|
||||||
|
|
||||||
if ($room->getCleanLayout()) {
|
if ($room->getCleanLayout()) {
|
||||||
$joinMeetingParams->addUserData('bbb_auto_swap_layout', true);
|
$joinMeetingParams->addUserData('bbb_auto_swap_layout', true); // 2.5 and below // ToDo: remove in the future
|
||||||
|
$joinMeetingParams->addUserData('bbb_hide_presentation_on_join', true); // 2.6 and up
|
||||||
$joinMeetingParams->addUserData('bbb_show_participants_on_login', false);
|
$joinMeetingParams->addUserData('bbb_show_participants_on_login', false);
|
||||||
$joinMeetingParams->addUserData('bbb_show_public_chat_on_login', false);
|
$joinMeetingParams->addUserData('bbb_show_public_chat_on_login', false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,13 @@ use OCP\AppFramework\Db\Entity;
|
||||||
* @method void setMaxRooms(int $number)
|
* @method void setMaxRooms(int $number)
|
||||||
* @method void setMaxParticipants(int $number)
|
* @method void setMaxParticipants(int $number)
|
||||||
* @method void setAllowRecording(bool $allow)
|
* @method void setAllowRecording(bool $allow)
|
||||||
|
* @method void setGroupName(string $groupName)
|
||||||
*/
|
*/
|
||||||
class Restriction extends Entity implements JsonSerializable {
|
class Restriction extends Entity implements JsonSerializable {
|
||||||
public const ALL_ID = '';
|
public const ALL_ID = '';
|
||||||
|
|
||||||
protected $groupId;
|
protected $groupId;
|
||||||
|
protected $groupName;
|
||||||
protected $maxRooms = -1;
|
protected $maxRooms = -1;
|
||||||
protected $roomTypes = '[]';
|
protected $roomTypes = '[]';
|
||||||
protected $maxParticipants = -1;
|
protected $maxParticipants = -1;
|
||||||
|
@ -32,10 +34,15 @@ class Restriction extends Entity implements JsonSerializable {
|
||||||
$this->addType('allowRecording', 'boolean');
|
$this->addType('allowRecording', 'boolean');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setGroupName(string $groupName) {
|
||||||
|
$this->groupName = $groupName;
|
||||||
|
}
|
||||||
|
|
||||||
public function jsonSerialize(): array {
|
public function jsonSerialize(): array {
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'groupId' => $this->groupId,
|
'groupId' => $this->groupId,
|
||||||
|
'groupName' => $this->groupName,
|
||||||
'maxRooms' => (int) $this->maxRooms,
|
'maxRooms' => (int) $this->maxRooms,
|
||||||
'roomTypes' => \json_decode($this->roomTypes),
|
'roomTypes' => \json_decode($this->roomTypes),
|
||||||
'maxParticipants' => (int) $this->maxParticipants,
|
'maxParticipants' => (int) $this->maxParticipants,
|
||||||
|
|
|
@ -19,8 +19,9 @@ class RestrictionMapper extends QBMapper {
|
||||||
public function find(int $id): Restriction {
|
public function find(int $id): Restriction {
|
||||||
/* @var $qb IQueryBuilder */
|
/* @var $qb IQueryBuilder */
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->select('*')
|
$qb->select('r.*', 'g.displayname as groupName')
|
||||||
->from($this->tableName)
|
->from($this->tableName, 'r')
|
||||||
|
->leftJoin('r', 'groups', 'g', $qb->expr()->eq('r.group_id', 'g.gid'))
|
||||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
|
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
|
||||||
|
|
||||||
return $this->findEntity($qb);
|
return $this->findEntity($qb);
|
||||||
|
@ -33,8 +34,9 @@ class RestrictionMapper extends QBMapper {
|
||||||
public function findByGroupId(string $groupId): Restriction {
|
public function findByGroupId(string $groupId): Restriction {
|
||||||
/* @var $qb IQueryBuilder */
|
/* @var $qb IQueryBuilder */
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->select('*')
|
$qb->select('r.*', 'g.displayname as groupName')
|
||||||
->from($this->tableName)
|
->from($this->tableName, 'r')
|
||||||
|
->leftJoin('r', 'groups', 'g', $qb->expr()->eq('r.group_id', 'g.gid'))
|
||||||
->where($qb->expr()->eq('group_id', $qb->createNamedParameter($groupId)));
|
->where($qb->expr()->eq('group_id', $qb->createNamedParameter($groupId)));
|
||||||
|
|
||||||
return $this->findEntity($qb);
|
return $this->findEntity($qb);
|
||||||
|
@ -46,8 +48,9 @@ class RestrictionMapper extends QBMapper {
|
||||||
public function findByGroupIds(array $groupIds): array {
|
public function findByGroupIds(array $groupIds): array {
|
||||||
/* @var $qb IQueryBuilder */
|
/* @var $qb IQueryBuilder */
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->select('*')
|
$qb->select('r.*', 'g.displayname as groupName')
|
||||||
->from($this->tableName)
|
->from($this->tableName, 'r')
|
||||||
|
->leftJoin('r', 'groups', 'g', $qb->expr()->eq('r.group_id', 'g.gid'))
|
||||||
->where($qb->expr()->in('group_id', $qb->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)));
|
->where($qb->expr()->in('group_id', $qb->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)));
|
||||||
|
|
||||||
/** @var array<Restriction> */
|
/** @var array<Restriction> */
|
||||||
|
@ -60,8 +63,9 @@ class RestrictionMapper extends QBMapper {
|
||||||
public function findAll(): array {
|
public function findAll(): array {
|
||||||
/* @var $qb IQueryBuilder */
|
/* @var $qb IQueryBuilder */
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->select('*')
|
$qb->select('r.*', 'g.displayname as groupName')
|
||||||
->from($this->tableName);
|
->from($this->tableName, 'r')
|
||||||
|
->leftJoin('r', 'groups', 'g', $qb->expr()->eq('r.group_id', 'g.gid'));
|
||||||
|
|
||||||
/** @var array<Restriction> */
|
/** @var array<Restriction> */
|
||||||
return $this->findEntities($qb);
|
return $this->findEntities($qb);
|
||||||
|
|
|
@ -55,10 +55,13 @@ class Permission {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAllowedToCreateRoom(string $uid): bool {
|
public function isAllowedToCreateRoom(string $uid): bool {
|
||||||
$numberOfCreatedRooms = count($this->roomService->findAll($uid, [], []));
|
|
||||||
$restriction = $this->getRestriction($uid);
|
$restriction = $this->getRestriction($uid);
|
||||||
|
if ($restriction->getMaxRooms() < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$numberOfCreatedRooms = count($this->roomService->findByUserId($uid));
|
||||||
|
|
||||||
return $restriction->getMaxRooms() < 0 || $restriction->getMaxRooms() > $numberOfCreatedRooms;
|
return $restriction->getMaxRooms() > $numberOfCreatedRooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isUser(Room $room, ?string $uid): bool {
|
public function isUser(Room $room, ?string $uid): bool {
|
||||||
|
|
|
@ -9,13 +9,18 @@ use OCA\BigBlueButton\Db\RestrictionMapper;
|
||||||
|
|
||||||
use OCP\AppFramework\Db\DoesNotExistException;
|
use OCP\AppFramework\Db\DoesNotExistException;
|
||||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||||
|
use OCP\IGroupManager;
|
||||||
|
|
||||||
class RestrictionService {
|
class RestrictionService {
|
||||||
/** @var RestrictionMapper */
|
/** @var RestrictionMapper */
|
||||||
private $mapper;
|
private $mapper;
|
||||||
|
|
||||||
public function __construct(RestrictionMapper $mapper) {
|
/** @var IGroupManager */
|
||||||
|
private $groupManager;
|
||||||
|
|
||||||
|
public function __construct(RestrictionMapper $mapper, IGroupManager $groupManager) {
|
||||||
$this->mapper = $mapper;
|
$this->mapper = $mapper;
|
||||||
|
$this->groupManager = $groupManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findAll(): array {
|
public function findAll(): array {
|
||||||
|
@ -78,6 +83,10 @@ class RestrictionService {
|
||||||
$restriction = new Restriction();
|
$restriction = new Restriction();
|
||||||
|
|
||||||
$restriction->setGroupId($groupId);
|
$restriction->setGroupId($groupId);
|
||||||
|
$group = $this->groupManager->get($groupId);
|
||||||
|
if ($group) {
|
||||||
|
$restriction->setGroupName($group->getDisplayName());
|
||||||
|
}
|
||||||
|
|
||||||
return $this->mapper->insert($restriction);
|
return $this->mapper->insert($restriction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
"stylelint-config-recommended-scss": "^5.0.2",
|
"stylelint-config-recommended-scss": "^5.0.2",
|
||||||
"stylelint-scss": "^4.2.0",
|
"stylelint-scss": "^4.2.0",
|
||||||
"ts-loader": "^9.2.8",
|
"ts-loader": "^9.2.8",
|
||||||
"typescript": "^4.0.2",
|
"typescript": "^4.9.3",
|
||||||
"url-loader": "^4.0.0",
|
"url-loader": "^4.0.0",
|
||||||
"webpack": "^5.70.0",
|
"webpack": "^5.70.0",
|
||||||
"webpack-cli": "^4.9.2",
|
"webpack-cli": "^4.9.2",
|
||||||
|
|
|
@ -83,7 +83,8 @@ class PermissionTest extends TestCase {
|
||||||
|
|
||||||
$this->roomService
|
$this->roomService
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('findAll')
|
->method('findByUserId')
|
||||||
|
->with('foobar')
|
||||||
->willReturn([
|
->willReturn([
|
||||||
$this->createRoom(1, 'foo'),
|
$this->createRoom(1, 'foo'),
|
||||||
$this->createRoom(2, 'bar'),
|
$this->createRoom(2, 'bar'),
|
||||||
|
|
|
@ -8,16 +8,19 @@ use OCA\BigBlueButton\Db\Restriction;
|
||||||
use OCA\BigBlueButton\Db\RestrictionMapper;
|
use OCA\BigBlueButton\Db\RestrictionMapper;
|
||||||
use OCA\BigBlueButton\Db\Room;
|
use OCA\BigBlueButton\Db\Room;
|
||||||
use OCA\BigBlueButton\Service\RestrictionService;
|
use OCA\BigBlueButton\Service\RestrictionService;
|
||||||
|
use OCP\IGroupManager;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class RestrictionServiceTest extends TestCase {
|
class RestrictionServiceTest extends TestCase {
|
||||||
protected $mapper;
|
protected $mapper;
|
||||||
|
protected $groupManager;
|
||||||
protected $service;
|
protected $service;
|
||||||
|
|
||||||
public function setUp(): void {
|
public function setUp(): void {
|
||||||
$this->mapper = $this->createMock(RestrictionMapper::class);
|
$this->mapper = $this->createMock(RestrictionMapper::class);
|
||||||
|
$this->groupManager = $this->createMock(IGroupManager::class);
|
||||||
|
|
||||||
$this->service = new RestrictionService($this->mapper);
|
$this->service = new RestrictionService($this->mapper, $this->groupManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFindByGroupIds() {
|
public function testFindByGroupIds() {
|
||||||
|
|
|
@ -20,6 +20,7 @@ export enum Access {
|
||||||
export interface Restriction {
|
export interface Restriction {
|
||||||
id: number;
|
id: number;
|
||||||
groupId: string;
|
groupId: string;
|
||||||
|
groupName: string;
|
||||||
maxRooms: number;
|
maxRooms: number;
|
||||||
roomTypes: string[];
|
roomTypes: string[];
|
||||||
maxParticipants: number;
|
maxParticipants: number;
|
||||||
|
|
|
@ -37,6 +37,36 @@
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bbb-qrcode-container {
|
||||||
|
display: block;
|
||||||
|
height: 34px;
|
||||||
|
width: 34px;
|
||||||
|
margin: 3px;
|
||||||
|
position: relative;
|
||||||
|
cursor: zoom-in;
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&:checked + canvas {
|
||||||
|
max-width: none;
|
||||||
|
max-height: none;
|
||||||
|
box-shadow: 0 0 10px;
|
||||||
|
box-shadow: 0 0 5px var(--color-box-shadow);
|
||||||
|
cursor: zoom-out;
|
||||||
|
border: 5px solid #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#bbb-root, #bbb-app {
|
#bbb-root, #bbb-app {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: var(--color-main-background);
|
background-color: var(--color-main-background);
|
||||||
|
@ -95,10 +125,6 @@ pre {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#bbb-react-root table tbody tr td {
|
|
||||||
border-bottom: 1px solid var(--color-border-dark);
|
|
||||||
}
|
|
||||||
|
|
||||||
#bbb-react-root,
|
#bbb-react-root,
|
||||||
#bbb-restrictions {
|
#bbb-restrictions {
|
||||||
#bbb-warning,
|
#bbb-warning,
|
||||||
|
@ -194,6 +220,7 @@ pre {
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
|
border-bottom: 1px solid var(--color-border-dark);
|
||||||
|
|
||||||
& > form {
|
& > form {
|
||||||
margin: -10px;
|
margin: -10px;
|
||||||
|
@ -304,33 +331,3 @@ pre {
|
||||||
.bbb-input-container {
|
.bbb-input-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bbb-qrcode-container {
|
|
||||||
display: block;
|
|
||||||
height: 34px;
|
|
||||||
width: 34px;
|
|
||||||
margin: 3px;
|
|
||||||
position: relative;
|
|
||||||
cursor: zoom-in;
|
|
||||||
|
|
||||||
canvas {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"] {
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
&:checked + canvas {
|
|
||||||
max-width: none;
|
|
||||||
max-height: none;
|
|
||||||
box-shadow: 0 0 10px;
|
|
||||||
box-shadow: 0 0 5px var(--color-box-shadow);
|
|
||||||
cursor: zoom-out;
|
|
||||||
border: 5px solid #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -146,7 +146,8 @@ const App: React.FC<Props> = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxRooms = restriction?.maxRooms || 0;
|
const maxRooms = restriction?.maxRooms || 0;
|
||||||
const quota = maxRooms < 0 ? t('bbb', 'unlimited') : rooms.filter(room => room.userId === OC.currentUser).length + ' / ' + maxRooms;
|
const ownRoomsLength = rooms.filter(room => room.userId === OC.currentUser).length;
|
||||||
|
const quota = maxRooms < 0 ? t('bbb', 'unlimited') : ownRoomsLength + ' / ' + maxRooms;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="bbb-react-root"
|
<div id="bbb-react-root"
|
||||||
|
@ -188,7 +189,7 @@ const App: React.FC<Props> = () => {
|
||||||
{!isLoaded && <span className="icon icon-loading-small icon-visible"></span>}
|
{!isLoaded && <span className="icon icon-loading-small icon-visible"></span>}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{(maxRooms > rows.length || maxRooms < 0) ?
|
{(maxRooms > ownRoomsLength || maxRooms < 0) ?
|
||||||
<NewRoomForm addRoom={addRoom} /> :
|
<NewRoomForm addRoom={addRoom} /> :
|
||||||
<p className="text-muted">{maxRooms === 0 ?
|
<p className="text-muted">{maxRooms === 0 ?
|
||||||
t('bbb', 'You are not permitted to create a room.') :
|
t('bbb', 'You are not permitted to create a room.') :
|
||||||
|
|
|
@ -23,10 +23,10 @@ const RestrictionRoom: React.FC<Props> = (props) => {
|
||||||
|
|
||||||
function deleteRow(ev: MouseEvent) {
|
function deleteRow(ev: MouseEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
const groupName = restriction.groupName || restriction.groupId;
|
||||||
OC.dialogs.confirm(
|
OC.dialogs.confirm(
|
||||||
t('bbb', 'Are you sure you want to delete the restrictions for group "{name}"? This operation cannot be undone.', { name: restriction.groupId }),
|
t('bbb', 'Are you sure you want to delete the restrictions for group "{name}"? This operation cannot be undone.', { name: groupName }),
|
||||||
t('bbb', 'Delete restrictions for "{name}"?', { name: restriction.groupId }),
|
t('bbb', 'Delete restrictions for "{name}"?', { name: groupName}),
|
||||||
confirmed => {
|
confirmed => {
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
props.deleteRestriction(restriction.id);
|
props.deleteRestriction(restriction.id);
|
||||||
|
@ -42,7 +42,7 @@ const RestrictionRoom: React.FC<Props> = (props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td className="name">{restriction.groupId || t('bbb', 'All users')}</td>
|
<td className="name">{restriction.groupName || restriction.groupId || t('bbb', 'All users')}</td>
|
||||||
<td className="max-rooms bbb-shrink">
|
<td className="max-rooms bbb-shrink">
|
||||||
{edit('maxRooms', 'number')}
|
{edit('maxRooms', 'number')}
|
||||||
</td>
|
</td>
|
||||||
|
|
Loading…
Reference in New Issue