Compare commits

...

19 Commits

Author SHA1 Message Date
Jonas 66150997b1
Merge 093e286e0f into e5bfcc8ec8 2024-10-23 10:49:24 +02:00
Thibaut e5bfcc8ec8
Merge pull request #294 from arawa/fix/style_lint_and_typescript
fix: style lint warnings and typescript compiler need upgrade
2024-10-23 10:49:14 +02:00
Thibaut dede2b2857
Merge pull request #295 from arawa/fix/289/admin_interface_displays_gid
fix: #289 admin interface displays groups gid instead of displayname
2024-10-23 10:43:30 +02:00
Thibaut 3c45a93ece
Merge pull request #296 from arawa/fix/290/max_number_of_rooms_count_only_owned_rooms
fix: #290 max number of rooms shloud take only owned rooms in account
2024-10-23 10:41:35 +02:00
Nextcloud bot 31bc8aeea1
Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-10-23 02:32:43 +00:00
Thibaut ad65b6803f
Merge pull request #297 from arawa/php-tests-25-30
fix: update php versions for tests in github actions
2024-10-22 18:19:52 +02:00
Sebastien Marinier a00708ffa3 fix: update php versions for tests in github actions (wait for 29 and 30)
Signed-off-by: Sebastien Marinier <sebastien.marinier@arawa.fr>
2024-10-22 18:15:04 +02:00
Sebastien Marinier 95f9425a80 fix: update php versions for tests in github actions (no array syntax)
Signed-off-by: Sebastien Marinier <sebastien.marinier@arawa.fr>
2024-10-22 18:05:53 +02:00
Sebastien Marinier 1b15353dcb fix: update php versions for tests in github actions
Signed-off-by: Sebastien Marinier <sebastien.marinier@arawa.fr>
2024-10-22 18:00:16 +02:00
Sebastien Marinier 79518b9bac fix: #290 max number of rooms shloud take only owned rooms in account
Signed-off-by: Sebastien Marinier <sebastien.marinier@arawa.fr>
2024-10-22 17:11:41 +02:00
Sebastien Marinier ab80d613e7 fix: unit test with groupManager
Signed-off-by: Sebastien Marinier <sebastien.marinier@arawa.fr>
2024-10-22 16:21:15 +02:00
Sebastien Marinier da0cc79b9e fix: unit test with groupManager
Signed-off-by: Sebastien Marinier <sebastien.marinier@arawa.fr>
2024-10-22 15:46:50 +02:00
Sebastien Marinier 71fe272888 fix: #289 admin interface displays groups gid instead of displayname
Signed-off-by: Sebastien Marinier <sebastien.marinier@arawa.fr>
2024-10-22 15:30:10 +02:00
Sebastien Marinier 323e9df9f4 fix: style lint warnings and typescript compiler need upgrade
Signed-off-by: Sebastien Marinier <sebastien.marinier@arawa.fr>
2024-10-22 15:04:46 +02:00
Thibaut 7233d21a85
Merge pull request #293 from arawa/fix/288/expose_app_capabilities
fix: #288 expose app capabilities
2024-10-22 11:34:40 +02:00
Sebastien Marinier a9082d3a46 fix: #288 expose app capabilities
Signed-off-by: Sebastien Marinier <sebastien.marinier@arawa.fr>
2024-10-21 17:54:44 +02:00
Nextcloud bot b7a864c658
Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-10-19 02:33:34 +00:00
Nextcloud bot 2f288e34c0
Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-10-17 02:22:26 +00:00
brtbr 093e286e0f fix: add new hide_presentation_on_join flag
As of BBB 2.6 the userdata flag for hiding the presentation has changed. This commit adds the new `bbb_hide_presentation_on_join` flag when a clean layout is selected.

In order to keep backwards compatability for BBB 2.5 and lower we can
send both flags and remove the deprecated one later on.
2024-06-02 18:16:54 +02:00
21 changed files with 150 additions and 62 deletions

View File

@ -11,13 +11,23 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: ['7.4', '8']
nextcloud-versions: ['stable25', 'stable26', 'stable27']
php-versions: ['7.4', '8.0', '8.1', '8.2', '8.3']
nextcloud-versions: ['stable25', 'stable26', 'stable27', 'stable28']
exclude:
- php-versions: '7.4'
nextcloud-versions: 'stable26'
- php-versions: '7.4'
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
env:
CI: true

View File

@ -72,7 +72,7 @@ OC.L10N.register(
"This message is shown to all users in the chat area after they joined." : "Ce message est affiché à tous les utilisateurs de lespace de discussion après quils lont rejoint.",
"Sets a limit on the number of participants for this room. Zero means there is no limit." : "Fixe une limite au nombre de participants pour cette salle. Zéro signifie quil ny a pas de limite.",
"If enabled, the moderator is able to start the recording." : "Si activé, le modérateur peut lancer l'enregistrement.",
"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." : "Explication des différents concepts qui constituent les options daccès :<br>- Public : Toute personne possédant le lien peut rejoindre la conversation.- <br>Interne : Seuls les utilisateurs Nextcloud peuvent rejoindre la conversation.- <br>Mot de passe : Seuls les invités possédant le mot de passe peuvent rejoindre la conversation..- <br>Salle dattente : Un modérateur doit accepter chaque invité avant quil ne puisse rejoindre la conversation.- <br>Restreint : Seuls les utilisateurs et groupes sélectionnés peuvent accéder à cette conversation.",
"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." : "Explication des différents concepts qui constituent les options daccès :<br>- Public : Toute personne possédant le lien peut rejoindre la conversation.- <br>Interne : Seuls les utilisateurs Nextcloud peuvent rejoindre la conversation.- <br>Mot de passe : Seuls les invités possédant le mot de passe peuvent rejoindre la conversation..- <br>Salle dattente : Un modérateur doit accepter chaque invité avant quil ne puisse rejoindre la conversation.- <br>Restreint : Seuls les utilisateurs et groupes sélectionnés peuvent accéder à cette conversation. ",
"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 modérateur est en mesure de gérer tous les participants d'une réunion, incluant leur éjection de la salle, leur mise en sourdine ou la désignation d'un présentateur. Les utilisateurs ayant le rôle de modérateur peuvent également mettre fin à une réunion ou modifier les paramètres par défaut.",
"If enabled, normal users have to wait until a moderator is in the room." : "Si activé, les utilisateurs devront attendre qu'un modérateur rejoigne la salle.",
"If enabled, a moderator URL is generated which allows access with moderator permission." : "Si activé, une URL de modérateur est générée pour permettre l'accès avec les droits de modération.",

View File

@ -70,7 +70,7 @@
"This message is shown to all users in the chat area after they joined." : "Ce message est affiché à tous les utilisateurs de lespace de discussion après quils lont rejoint.",
"Sets a limit on the number of participants for this room. Zero means there is no limit." : "Fixe une limite au nombre de participants pour cette salle. Zéro signifie quil ny a pas de limite.",
"If enabled, the moderator is able to start the recording." : "Si activé, le modérateur peut lancer l'enregistrement.",
"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." : "Explication des différents concepts qui constituent les options daccès :<br>- Public : Toute personne possédant le lien peut rejoindre la conversation.- <br>Interne : Seuls les utilisateurs Nextcloud peuvent rejoindre la conversation.- <br>Mot de passe : Seuls les invités possédant le mot de passe peuvent rejoindre la conversation..- <br>Salle dattente : Un modérateur doit accepter chaque invité avant quil ne puisse rejoindre la conversation.- <br>Restreint : Seuls les utilisateurs et groupes sélectionnés peuvent accéder à cette conversation.",
"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." : "Explication des différents concepts qui constituent les options daccès :<br>- Public : Toute personne possédant le lien peut rejoindre la conversation.- <br>Interne : Seuls les utilisateurs Nextcloud peuvent rejoindre la conversation.- <br>Mot de passe : Seuls les invités possédant le mot de passe peuvent rejoindre la conversation..- <br>Salle dattente : Un modérateur doit accepter chaque invité avant quil ne puisse rejoindre la conversation.- <br>Restreint : Seuls les utilisateurs et groupes sélectionnés peuvent accéder à cette conversation. ",
"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 modérateur est en mesure de gérer tous les participants d'une réunion, incluant leur éjection de la salle, leur mise en sourdine ou la désignation d'un présentateur. Les utilisateurs ayant le rôle de modérateur peuvent également mettre fin à une réunion ou modifier les paramètres par défaut.",
"If enabled, normal users have to wait until a moderator is in the room." : "Si activé, les utilisateurs devront attendre qu'un modérateur rejoigne la salle.",
"If enabled, a moderator URL is generated which allows access with moderator permission." : "Si activé, une URL de modérateur est générée pour permettre l'accès avec les droits de modération.",

View File

@ -58,6 +58,7 @@ OC.L10N.register(
"No matches" : "Nessuna corrispondenza",
"admin" : "amministratore",
"moderator" : "moderatore",
"user" : "utente",
"Name" : "Nome",
"Access" : "Accesso",
"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.",
"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.",
"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.",
"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.",
@ -114,7 +116,10 @@ OC.L10N.register(
"Delete?" : "Vuoi eliminare?",
"Could not delete record" : "Impossibile eliminare il record",
"Server error" : "Errore del server",
"Could not modify publishing state" : "Impossibile modificare lo stato di pubblicazione",
"Open room" : "Stanza aperta",
"Start" : "Avvia",
"Clone room" : "Clona stanza",
"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.",
"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 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}.",
"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 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}\".",
"No rooms available!" : "Nessuna stanza disponibile",
"Send to BBB" : "Invia a BBB",

View File

@ -56,6 +56,7 @@
"No matches" : "Nessuna corrispondenza",
"admin" : "amministratore",
"moderator" : "moderatore",
"user" : "utente",
"Name" : "Nome",
"Access" : "Accesso",
"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.",
"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.",
"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.",
"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.",
@ -112,7 +114,10 @@
"Delete?" : "Vuoi eliminare?",
"Could not delete record" : "Impossibile eliminare il record",
"Server error" : "Errore del server",
"Could not modify publishing state" : "Impossibile modificare lo stato di pubblicazione",
"Open room" : "Stanza aperta",
"Start" : "Avvia",
"Clone room" : "Clona stanza",
"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.",
"Max. rooms" : "Num. massimo stanze",
@ -128,8 +133,12 @@
"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 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 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}\".",
"No rooms available!" : "Nessuna stanza disponibile",
"Send to BBB" : "Invia a BBB",

View File

@ -48,7 +48,7 @@ OC.L10N.register(
"Display name" : "显示名称",
"Password" : "密码",
"Join" : "加入",
"Have an account? Log in." : "有一个账户吗?登录。",
"Have an account? Log in." : "有一个账?登录。",
"Hello %s" : "%s 你好",
"Name, group …" : "名称、群组 ...",
"Group" : "群组",

View File

@ -46,7 +46,7 @@
"Display name" : "显示名称",
"Password" : "密码",
"Join" : "加入",
"Have an account? Log in." : "有一个账户吗?登录。",
"Have an account? Log in." : "有一个账?登录。",
"Hello %s" : "%s 你好",
"Name, group …" : "名称、群组 ...",
"Group" : "群组",

View File

@ -56,6 +56,8 @@ class Application extends App implements IBootstrap {
$context->registerMiddleware(JoinMiddleware::class);
$context->registerMiddleware(HookMiddleware::class);
$context->registerCapability(Capabilities::class);
}
public function boot(IBootContext $context): void {

View File

@ -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)
];
}
}

View File

@ -118,7 +118,8 @@ class API {
$joinMeetingParams->addUserData('bbb_skip_video_preview_on_first_join', !$room->getMediaCheck()); // 2.3
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_public_chat_on_login', false);
}

View File

@ -16,11 +16,13 @@ use OCP\AppFramework\Db\Entity;
* @method void setMaxRooms(int $number)
* @method void setMaxParticipants(int $number)
* @method void setAllowRecording(bool $allow)
* @method void setGroupName(string $groupName)
*/
class Restriction extends Entity implements JsonSerializable {
public const ALL_ID = '';
protected $groupId;
protected $groupName;
protected $maxRooms = -1;
protected $roomTypes = '[]';
protected $maxParticipants = -1;
@ -32,10 +34,15 @@ class Restriction extends Entity implements JsonSerializable {
$this->addType('allowRecording', 'boolean');
}
public function setGroupName(string $groupName) {
$this->groupName = $groupName;
}
public function jsonSerialize(): array {
return [
'id' => $this->id,
'groupId' => $this->groupId,
'groupName' => $this->groupName,
'maxRooms' => (int) $this->maxRooms,
'roomTypes' => \json_decode($this->roomTypes),
'maxParticipants' => (int) $this->maxParticipants,

View File

@ -19,8 +19,9 @@ class RestrictionMapper extends QBMapper {
public function find(int $id): Restriction {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->tableName)
$qb->select('r.*', 'g.displayname as groupName')
->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)));
return $this->findEntity($qb);
@ -33,8 +34,9 @@ class RestrictionMapper extends QBMapper {
public function findByGroupId(string $groupId): Restriction {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->tableName)
$qb->select('r.*', 'g.displayname as groupName')
->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)));
return $this->findEntity($qb);
@ -46,8 +48,9 @@ class RestrictionMapper extends QBMapper {
public function findByGroupIds(array $groupIds): array {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->tableName)
$qb->select('r.*', 'g.displayname as groupName')
->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)));
/** @var array<Restriction> */
@ -60,8 +63,9 @@ class RestrictionMapper extends QBMapper {
public function findAll(): array {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->tableName);
$qb->select('r.*', 'g.displayname as groupName')
->from($this->tableName, 'r')
->leftJoin('r', 'groups', 'g', $qb->expr()->eq('r.group_id', 'g.gid'));
/** @var array<Restriction> */
return $this->findEntities($qb);

View File

@ -55,10 +55,13 @@ class Permission {
}
public function isAllowedToCreateRoom(string $uid): bool {
$numberOfCreatedRooms = count($this->roomService->findAll($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 {

View File

@ -9,13 +9,18 @@ use OCA\BigBlueButton\Db\RestrictionMapper;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\IGroupManager;
class RestrictionService {
/** @var RestrictionMapper */
private $mapper;
public function __construct(RestrictionMapper $mapper) {
/** @var IGroupManager */
private $groupManager;
public function __construct(RestrictionMapper $mapper, IGroupManager $groupManager) {
$this->mapper = $mapper;
$this->groupManager = $groupManager;
}
public function findAll(): array {
@ -78,6 +83,10 @@ class RestrictionService {
$restriction = new Restriction();
$restriction->setGroupId($groupId);
$group = $this->groupManager->get($groupId);
if ($group) {
$restriction->setGroupName($group->getDisplayName());
}
return $this->mapper->insert($restriction);
}

View File

@ -109,7 +109,7 @@
"stylelint-config-recommended-scss": "^5.0.2",
"stylelint-scss": "^4.2.0",
"ts-loader": "^9.2.8",
"typescript": "^4.0.2",
"typescript": "^4.9.3",
"url-loader": "^4.0.0",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2",

View File

@ -83,7 +83,8 @@ class PermissionTest extends TestCase {
$this->roomService
->expects($this->once())
->method('findAll')
->method('findByUserId')
->with('foobar')
->willReturn([
$this->createRoom(1, 'foo'),
$this->createRoom(2, 'bar'),

View File

@ -8,16 +8,19 @@ use OCA\BigBlueButton\Db\Restriction;
use OCA\BigBlueButton\Db\RestrictionMapper;
use OCA\BigBlueButton\Db\Room;
use OCA\BigBlueButton\Service\RestrictionService;
use OCP\IGroupManager;
use PHPUnit\Framework\TestCase;
class RestrictionServiceTest extends TestCase {
protected $mapper;
protected $groupManager;
protected $service;
public function setUp(): void {
$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() {

View File

@ -20,6 +20,7 @@ export enum Access {
export interface Restriction {
id: number;
groupId: string;
groupName: string;
maxRooms: number;
roomTypes: string[];
maxParticipants: number;

View File

@ -37,6 +37,36 @@
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 {
width: 100%;
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-restrictions {
#bbb-warning,
@ -194,6 +220,7 @@ pre {
padding: 0 6px;
position: relative;
display: table-cell;
border-bottom: 1px solid var(--color-border-dark);
& > form {
margin: -10px;
@ -298,39 +325,9 @@ pre {
}
.bbb-simple-menu {
min-width: auto;
min-width: auto;
}
.bbb-input-container {
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;
}
}
}

View File

@ -146,7 +146,8 @@ const App: React.FC<Props> = () => {
}
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 (
<div id="bbb-react-root"
@ -188,7 +189,7 @@ const App: React.FC<Props> = () => {
{!isLoaded && <span className="icon icon-loading-small icon-visible"></span>}
</td>
<td>
{(maxRooms > rows.length || maxRooms < 0) ?
{(maxRooms > ownRoomsLength || maxRooms < 0) ?
<NewRoomForm addRoom={addRoom} /> :
<p className="text-muted">{maxRooms === 0 ?
t('bbb', 'You are not permitted to create a room.') :

View File

@ -23,10 +23,10 @@ const RestrictionRoom: React.FC<Props> = (props) => {
function deleteRow(ev: MouseEvent) {
ev.preventDefault();
const groupName = restriction.groupName || restriction.groupId;
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', 'Delete restrictions for "{name}"?', { 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: groupName}),
confirmed => {
if (confirmed) {
props.deleteRestriction(restriction.id);
@ -42,7 +42,7 @@ const RestrictionRoom: React.FC<Props> = (props) => {
return (
<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">
{edit('maxRooms', 'number')}
</td>