diff options
author | Roeland Jago Douma <rullzer@users.noreply.github.com> | 2021-03-05 08:49:43 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-05 08:49:43 +0100 |
commit | 54cffefed47f7688800dbbb0d2115ddff02ebbef (patch) | |
tree | df707ce13120ac23532370ecf5ead6173b0916a0 | |
parent | e6ef096e520c512064db3448696c7a3ab8f47147 (diff) | |
parent | 2796ef80ff53684c6b276b054bb2d3b6039a4ef6 (diff) | |
download | nextcloud-server-54cffefed47f7688800dbbb0d2115ddff02ebbef.tar.gz nextcloud-server-54cffefed47f7688800dbbb0d2115ddff02ebbef.zip |
Merge pull request #25660 from hosting-de/feature/add-backend-list-groups
Show group backends in occ group:list --info and group:info
-rw-r--r-- | apps/user_ldap/lib/Group_Proxy.php | 12 | ||||
-rw-r--r-- | core/Command/Group/Info.php | 83 | ||||
-rw-r--r-- | core/Command/Group/ListCommand.php | 25 | ||||
-rw-r--r-- | core/register_command.php | 1 | ||||
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 2 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 2 | ||||
-rw-r--r-- | lib/private/Group/Database.php | 13 | ||||
-rw-r--r-- | lib/private/Group/Group.php | 19 | ||||
-rw-r--r-- | lib/public/Group/Backend/INamedBackend.php | 36 | ||||
-rw-r--r-- | lib/public/IGroup.php | 8 | ||||
-rw-r--r-- | tests/Core/Command/Group/InfoTest.php | 115 | ||||
-rw-r--r-- | tests/Core/Command/Group/ListCommandTest.php | 99 |
12 files changed, 401 insertions, 14 deletions
diff --git a/apps/user_ldap/lib/Group_Proxy.php b/apps/user_ldap/lib/Group_Proxy.php index 490eab44462..0078f0803c0 100644 --- a/apps/user_ldap/lib/Group_Proxy.php +++ b/apps/user_ldap/lib/Group_Proxy.php @@ -28,9 +28,10 @@ namespace OCA\User_LDAP; +use OCP\Group\Backend\INamedBackend; use OCP\Group\Backend\IGetDisplayNameBackend; -class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP, IGetDisplayNameBackend { +class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP, IGetDisplayNameBackend, INamedBackend { private $backends = []; private $refBackend = null; @@ -298,4 +299,13 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP, IGet public function getDisplayName(string $gid): string { return $this->handleRequest($gid, 'getDisplayName', [$gid]); } + + /** + * Backend name to be shown in group management + * @return string the name of the backend to be shown + * @since 22.0.0 + */ + public function getBackendName(): string { + return 'LDAP'; + } } diff --git a/core/Command/Group/Info.php b/core/Command/Group/Info.php new file mode 100644 index 00000000000..225c3444397 --- /dev/null +++ b/core/Command/Group/Info.php @@ -0,0 +1,83 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2021, hosting.de, Johannes Leuker <j.leuker@hosting.de> + * + * @author Johannes Leuker <j.leuker@hosting.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Core\Command\Group; + +use OC\Core\Command\Base; +use OCP\IGroup; +use OCP\IGroupManager; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class Info extends Base { + /** @var IGroupManager */ + protected $groupManager; + + /** + * @param IGroupManager $groupManager + */ + public function __construct(IGroupManager $groupManager) { + $this->groupManager = $groupManager; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('group:info') + ->setDescription('Show information about a group') + ->addArgument( + 'groupid', + InputArgument::REQUIRED, + 'Group id' + )->addOption( + 'output', + null, + InputOption::VALUE_OPTIONAL, + 'Output format (plain, json or json_pretty, default is plain)', + $this->defaultOutputFormat + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $gid = $input->getArgument('groupid'); + $group = $this->groupManager->get($gid); + if (!$group instanceof IGroup) { + $output->writeln('<error>Group "' . $gid . '" does not exist.</error>'); + return 1; + } else { + $groupOutput = [ + 'groupID' => $gid, + 'displayName' => $group->getDisplayName(), + 'backends' => $group->getBackendNames(), + ]; + + $this->writeArrayInOutputFormat($input, $output, $groupOutput); + return 0; + } + } +} diff --git a/core/Command/Group/ListCommand.php b/core/Command/Group/ListCommand.php index 846c36fab39..99c4d6e35c6 100644 --- a/core/Command/Group/ListCommand.php +++ b/core/Command/Group/ListCommand.php @@ -60,6 +60,11 @@ class ListCommand extends Base { 'Offset for retrieving groups', 0 )->addOption( + 'info', + 'i', + InputOption::VALUE_NONE, + 'Show additional info (backend)' + )->addOption( 'output', null, InputOption::VALUE_OPTIONAL, @@ -70,7 +75,7 @@ class ListCommand extends Base { protected function execute(InputInterface $input, OutputInterface $output): int { $groups = $this->groupManager->search('', (int)$input->getOption('limit'), (int)$input->getOption('offset')); - $this->writeArrayInOutputFormat($input, $output, $this->formatGroups($groups)); + $this->writeArrayInOutputFormat($input, $output, $this->formatGroups($groups, (bool)$input->getOption('info'))); return 0; } @@ -78,13 +83,23 @@ class ListCommand extends Base { * @param IGroup[] $groups * @return array */ - private function formatGroups(array $groups) { + private function formatGroups(array $groups, bool $addInfo = false) { $keys = array_map(function (IGroup $group) { return $group->getGID(); }, $groups); - $values = array_map(function (IGroup $group) { - return array_keys($group->getUsers()); - }, $groups); + + if ($addInfo) { + $values = array_map(function (IGroup $group) { + return [ + 'backends' => $group->getBackendNames(), + 'users' => array_keys($group->getUsers()), + ]; + }, $groups); + } else { + $values = array_map(function (IGroup $group) { + return array_keys($group->getUsers()); + }, $groups); + } return array_combine($keys, $values); } } diff --git a/core/register_command.php b/core/register_command.php index 605c545554a..3c8aa50e18c 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -186,6 +186,7 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) { $application->add(new OC\Core\Command\Group\ListCommand(\OC::$server->getGroupManager())); $application->add(new OC\Core\Command\Group\AddUser(\OC::$server->getUserManager(), \OC::$server->getGroupManager())); $application->add(new OC\Core\Command\Group\RemoveUser(\OC::$server->getUserManager(), \OC::$server->getGroupManager())); + $application->add(new OC\Core\Command\Group\Info(\OC::$server->get(\OCP\IGroupManager::class))); $application->add(new OC\Core\Command\Security\ListCertificates(\OC::$server->getCertificateManager(), \OC::$server->getL10N('core'))); $application->add(new OC\Core\Command\Security\ImportCertificate(\OC::$server->getCertificateManager())); diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 4f03731fe59..0ba8212dbfc 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -351,6 +351,7 @@ return array( 'OCP\\Group\\Backend\\IGroupDetailsBackend' => $baseDir . '/lib/public/Group/Backend/IGroupDetailsBackend.php', 'OCP\\Group\\Backend\\IHideFromCollaborationBackend' => $baseDir . '/lib/public/Group/Backend/IHideFromCollaborationBackend.php', 'OCP\\Group\\Backend\\IIsAdminBackend' => $baseDir . '/lib/public/Group/Backend/IIsAdminBackend.php', + 'OCP\\Group\\Backend\\INamedBackend' => $baseDir . '/lib/public/Group/Backend/INamedBackend.php', 'OCP\\Group\\Backend\\IRemoveFromGroupBackend' => $baseDir . '/lib/public/Group/Backend/IRemoveFromGroupBackend.php', 'OCP\\Group\\Backend\\ISetDisplayNameBackend' => $baseDir . '/lib/public/Group/Backend/ISetDisplayNameBackend.php', 'OCP\\Group\\Events\\BeforeGroupCreatedEvent' => $baseDir . '/lib/public/Group/Events/BeforeGroupCreatedEvent.php', @@ -834,6 +835,7 @@ return array( 'OC\\Core\\Command\\Group\\Add' => $baseDir . '/core/Command/Group/Add.php', 'OC\\Core\\Command\\Group\\AddUser' => $baseDir . '/core/Command/Group/AddUser.php', 'OC\\Core\\Command\\Group\\Delete' => $baseDir . '/core/Command/Group/Delete.php', + 'OC\\Core\\Command\\Group\\Info' => $baseDir . '/core/Command/Group/Info.php', 'OC\\Core\\Command\\Group\\ListCommand' => $baseDir . '/core/Command/Group/ListCommand.php', 'OC\\Core\\Command\\Group\\RemoveUser' => $baseDir . '/core/Command/Group/RemoveUser.php', 'OC\\Core\\Command\\Integrity\\CheckApp' => $baseDir . '/core/Command/Integrity/CheckApp.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 87f7f54622c..9558cc49981 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -380,6 +380,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Group\\Backend\\IGroupDetailsBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IGroupDetailsBackend.php', 'OCP\\Group\\Backend\\IHideFromCollaborationBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IHideFromCollaborationBackend.php', 'OCP\\Group\\Backend\\IIsAdminBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IIsAdminBackend.php', + 'OCP\\Group\\Backend\\INamedBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/INamedBackend.php', 'OCP\\Group\\Backend\\IRemoveFromGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IRemoveFromGroupBackend.php', 'OCP\\Group\\Backend\\ISetDisplayNameBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ISetDisplayNameBackend.php', 'OCP\\Group\\Events\\BeforeGroupCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Group/Events/BeforeGroupCreatedEvent.php', @@ -863,6 +864,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Command\\Group\\Add' => __DIR__ . '/../../..' . '/core/Command/Group/Add.php', 'OC\\Core\\Command\\Group\\AddUser' => __DIR__ . '/../../..' . '/core/Command/Group/AddUser.php', 'OC\\Core\\Command\\Group\\Delete' => __DIR__ . '/../../..' . '/core/Command/Group/Delete.php', + 'OC\\Core\\Command\\Group\\Info' => __DIR__ . '/../../..' . '/core/Command/Group/Info.php', 'OC\\Core\\Command\\Group\\ListCommand' => __DIR__ . '/../../..' . '/core/Command/Group/ListCommand.php', 'OC\\Core\\Command\\Group\\RemoveUser' => __DIR__ . '/../../..' . '/core/Command/Group/RemoveUser.php', 'OC\\Core\\Command\\Integrity\\CheckApp' => __DIR__ . '/../../..' . '/core/Command/Integrity/CheckApp.php', diff --git a/lib/private/Group/Database.php b/lib/private/Group/Database.php index c49f3bce596..29fcb503b10 100644 --- a/lib/private/Group/Database.php +++ b/lib/private/Group/Database.php @@ -55,6 +55,7 @@ use OCP\Group\Backend\IGetDisplayNameBackend; use OCP\Group\Backend\IGroupDetailsBackend; use OCP\Group\Backend\IRemoveFromGroupBackend; use OCP\Group\Backend\ISetDisplayNameBackend; +use OCP\Group\Backend\INamedBackend; use OCP\IDBConnection; /** @@ -69,7 +70,8 @@ class Database extends ABackend implements IGetDisplayNameBackend, IGroupDetailsBackend, IRemoveFromGroupBackend, - ISetDisplayNameBackend { + ISetDisplayNameBackend, + INamedBackend { /** @var string[] */ private $groupCache = []; @@ -502,4 +504,13 @@ class Database extends ABackend implements return true; } + + /** + * Backend name to be shown in group management + * @return string the name of the backend to be shown + * @since 21.0.0 + */ + public function getBackendName(): string { + return 'Database'; + } } diff --git a/lib/private/Group/Group.php b/lib/private/Group/Group.php index d3f8c603121..bb9a65de012 100644 --- a/lib/private/Group/Group.php +++ b/lib/private/Group/Group.php @@ -36,6 +36,7 @@ use OC\Hooks\PublicEmitter; use OCP\Group\Backend\ICountDisabledInGroup; use OCP\Group\Backend\IGetDisplayNameBackend; use OCP\Group\Backend\IHideFromCollaborationBackend; +use OCP\Group\Backend\INamedBackend; use OCP\Group\Backend\ISetDisplayNameBackend; use OCP\GroupInterface; use OCP\IGroup; @@ -318,6 +319,24 @@ class Group implements IGroup { } /** + * Get the names of the backend classes the group is connected to + * + * @return string[] + */ + public function getBackendNames() { + $backends = []; + foreach ($this->backends as $backend) { + if ($backend instanceof INamedBackend) { + $backends[] = $backend->getBackendName(); + } else { + $backends[] = get_class($backend); + } + } + + return $backends; + } + + /** * delete the group * * @return bool diff --git a/lib/public/Group/Backend/INamedBackend.php b/lib/public/Group/Backend/INamedBackend.php new file mode 100644 index 00000000000..b6aaea328c4 --- /dev/null +++ b/lib/public/Group/Backend/INamedBackend.php @@ -0,0 +1,36 @@ +<?php +/** + * @copyright Copyright (c) 2021, hosting.de, Johannes Leuker <j.leuker@hosting.de>. + * + * @author Johannes Leuker <j.leuker@hosting.de>. + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCP\Group\Backend; + +/** + * @since 22.0.0 + */ +interface INamedBackend { + + /** + * Backend name to be shown in group management + * @return string the name of the backend to be shown + * @since 22.0.0 + */ + public function getBackendName(): string; +} diff --git a/lib/public/IGroup.php b/lib/public/IGroup.php index ead240cc1a2..014302347ed 100644 --- a/lib/public/IGroup.php +++ b/lib/public/IGroup.php @@ -130,6 +130,14 @@ interface IGroup { public function searchDisplayName($search, $limit = null, $offset = null); /** + * Get the names of the backends the group is connected to + * + * @return string[] + * @since 22.0.0 + */ + public function getBackendNames(); + + /** * delete the group * * @return bool diff --git a/tests/Core/Command/Group/InfoTest.php b/tests/Core/Command/Group/InfoTest.php new file mode 100644 index 00000000000..40b0f78f5ab --- /dev/null +++ b/tests/Core/Command/Group/InfoTest.php @@ -0,0 +1,115 @@ +<?php +/** + * @copyright 2021, hosting.de, Johannes Leuker <j.leuker@hosting.de> + * + * @author Johannes Leuker <j.leuker@hosting.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Afferoq General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace Test\Core\Command\Group; + +use OC\Core\Command\Group\Info; +use OCP\IGroup; +use OCP\IGroupManager; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Test\TestCase; + +class InfoTest extends TestCase { + + /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */ + private $groupManager; + + /** @var Info|\PHPUnit\Framework\MockObject\MockObject */ + private $command; + + /** @var InputInterface|\PHPUnit\Framework\MockObject\MockObject */ + private $input; + + /** @var OutputInterface|\PHPUnit\Framework\MockObject\MockObject */ + private $output; + + protected function setUp(): void { + parent::setUp(); + + $this->groupManager = $this->createMock(IGroupManager::class); + $this->command = $this->getMockBuilder(Info::class) + ->setConstructorArgs([$this->groupManager]) + ->setMethods(['writeArrayInOutputFormat']) + ->getMock(); + + $this->input = $this->createMock(InputInterface::class); + $this->output = $this->createMock(OutputInterface::class); + } + + public function testDoesNotExists() { + $gid = 'myGroup'; + $this->input->method('getArgument') + ->willReturnCallback(function ($arg) use ($gid) { + if ($arg === 'groupid') { + return $gid; + } + throw new \Exception(); + }); + $this->groupManager->method('get') + ->with($gid) + ->willReturn(null); + + $this->output->expects($this->once()) + ->method('writeln') + ->with($this->equalTo('<error>Group "' . $gid . '" does not exist.</error>')); + + $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); + } + + public function testInfo() { + $gid = 'myGroup'; + $this->input->method('getArgument') + ->willReturnCallback(function ($arg) use ($gid) { + if ($arg === 'groupid') { + return $gid; + } + throw new \Exception(); + }); + + $group = $this->createMock(IGroup::class); + $group->method('getGID')->willReturn($gid); + $group->method('getDisplayName') + ->willReturn('My Group'); + $group->method('getBackendNames') + ->willReturn(['Database']); + + $this->groupManager->method('get') + ->with($gid) + ->willReturn($group); + + $this->command->expects($this->once()) + ->method('writeArrayInOutputFormat') + ->with( + $this->equalTo($this->input), + $this->equalTo($this->output), + [ + 'groupID' => 'myGroup', + 'displayName' => 'My Group', + 'backends' => ['Database'], + ] + ); + + $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); + } +} diff --git a/tests/Core/Command/Group/ListCommandTest.php b/tests/Core/Command/Group/ListCommandTest.php index 1c1dd3c95eb..ed454a796a6 100644 --- a/tests/Core/Command/Group/ListCommandTest.php +++ b/tests/Core/Command/Group/ListCommandTest.php @@ -55,21 +55,77 @@ class ListCommandTest extends TestCase { ->getMock(); $this->input = $this->createMock(InputInterface::class); + $this->output = $this->createMock(OutputInterface::class); + } + + public function testExecute() { + $group1 = $this->createMock(IGroup::class); + $group1->method('getGID')->willReturn('group1'); + $group2 = $this->createMock(IGroup::class); + $group2->method('getGID')->willReturn('group2'); + $group3 = $this->createMock(IGroup::class); + $group3->method('getGID')->willReturn('group3'); + + $user = $this->createMock(IUser::class); + + $this->groupManager->method('search') + ->with( + '', + 100, + 42, + )->willReturn([$group1, $group2, $group3]); + + $group1->method('getUsers') + ->willReturn([ + 'user1' => $user, + 'user2' => $user, + ]); + + $group2->method('getUsers') + ->willReturn([ + ]); + + $group3->method('getUsers') + ->willReturn([ + 'user1' => $user, + 'user3' => $user, + ]); + $this->input->method('getOption') ->willReturnCallback(function ($arg) { if ($arg === 'limit') { return '100'; } elseif ($arg === 'offset') { return '42'; + } elseif ($arg === 'info') { + return null; } throw new \Exception(); }); + $this->command->expects($this->once()) + ->method('writeArrayInOutputFormat') + ->with( + $this->equalTo($this->input), + $this->equalTo($this->output), + [ + 'group1' => [ + 'user1', + 'user2', + ], + 'group2' => [ + ], + 'group3' => [ + 'user1', + 'user3', + ] + ] + ); - $this->output = $this->createMock(OutputInterface::class); + $this->invokePrivate($this->command, 'execute', [$this->input, $this->output]); } - public function testExecute() { + public function testInfo() { $group1 = $this->createMock(IGroup::class); $group1->method('getGID')->willReturn('group1'); $group2 = $this->createMock(IGroup::class); @@ -83,7 +139,7 @@ class ListCommandTest extends TestCase { ->with( '', 100, - 42 + 42, )->willReturn([$group1, $group2, $group3]); $group1->method('getUsers') @@ -92,16 +148,37 @@ class ListCommandTest extends TestCase { 'user2' => $user, ]); + $group1->method('getBackendNames') + ->willReturn(['Database']); + $group2->method('getUsers') ->willReturn([ ]); + $group2->method('getBackendNames') + ->willReturn(['Database']); + $group3->method('getUsers') ->willReturn([ 'user1' => $user, 'user3' => $user, ]); + $group3->method('getBackendNames') + ->willReturn(['LDAP']); + + $this->input->method('getOption') + ->willReturnCallback(function ($arg) { + if ($arg === 'limit') { + return '100'; + } elseif ($arg === 'offset') { + return '42'; + } elseif ($arg === 'info') { + return true; + } + throw new \Exception(); + }); + $this->command->expects($this->once()) ->method('writeArrayInOutputFormat') ->with( @@ -109,14 +186,22 @@ class ListCommandTest extends TestCase { $this->equalTo($this->output), [ 'group1' => [ - 'user1', - 'user2', + 'backends' => ['Database'], + 'users' => [ + 'user1', + 'user2', + ], ], 'group2' => [ + 'backends' => ['Database'], + 'users' => [], ], 'group3' => [ - 'user1', - 'user3', + 'backends' => ['LDAP'], + 'users' => [ + 'user1', + 'user3', + ], ] ] ); |