diff options
29 files changed, 451 insertions, 80 deletions
diff --git a/apps/files_external/lib/Lib/Storage/SMB.php b/apps/files_external/lib/Lib/Storage/SMB.php index 952f6c08931..bc065b24552 100644 --- a/apps/files_external/lib/Lib/Storage/SMB.php +++ b/apps/files_external/lib/Lib/Storage/SMB.php @@ -556,7 +556,13 @@ class SMB extends Common implements INotifyStorage { } public function getMetaData($path) { - $fileInfo = $this->getFileInfo($path); + try { + $fileInfo = $this->getFileInfo($path); + } catch (NotFoundException $e) { + return null; + } catch (ForbiddenException $e) { + return null; + } if (!$fileInfo) { return null; } diff --git a/apps/files_sharing/lib/External/Scanner.php b/apps/files_sharing/lib/External/Scanner.php index 34ef65f0621..71187707ad7 100644 --- a/apps/files_sharing/lib/External/Scanner.php +++ b/apps/files_sharing/lib/External/Scanner.php @@ -56,7 +56,7 @@ class Scanner extends \OC\Files\Cache\Scanner { * @param int $parentId * @param array | null $cacheData existing data in the cache for the file to be scanned * @param bool $lock set to false to disable getting an additional read lock during scanning - * @return array an array of metadata of the scanned file + * @return array | null an array of metadata of the scanned file */ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true, $data = null) { try { diff --git a/apps/files_sharing/lib/Scanner.php b/apps/files_sharing/lib/Scanner.php index 450256782e7..21d2565a4cd 100644 --- a/apps/files_sharing/lib/Scanner.php +++ b/apps/files_sharing/lib/Scanner.php @@ -45,7 +45,7 @@ class Scanner extends \OC\Files\Cache\Scanner { * * @param string $path path of the file for which to retrieve metadata * - * @return array an array of metadata of the file + * @return array|null an array of metadata of the file */ public function getData($path) { $data = parent::getData($path); diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index b4a0c557539..6311576dff6 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -445,6 +445,13 @@ class UsersController extends AUserData { ] ); throw $e; + } catch (\InvalidArgumentException $e) { + $this->logger->logException($e, [ + 'message' => 'Failed addUser attempt with invalid argument exeption.', + 'level' => ILogger::ERROR, + 'app' => 'ocs_api', + ]); + throw new OCSException($e->getMessage(), 101); } catch (\Exception $e) { $this->logger->error('Failed addUser attempt with exception.', [ 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/build/package-lock.json b/build/package-lock.json index 5feedd4c5ce..a24775e526f 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -780,13 +780,6 @@ "delayed-stream": "~1.0.0" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "optional": true - }, "component-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", @@ -1390,9 +1383,9 @@ "dev": true }, "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { "minimist": "^1.2.5", @@ -1400,20 +1393,6 @@ "source-map": "^0.6.1", "uglify-js": "^3.1.4", "wordwrap": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } } }, "har-schema": { @@ -2547,6 +2526,12 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.5", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, "minipass": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", @@ -2608,9 +2593,9 @@ "dev": true }, "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "nise": { @@ -3974,15 +3959,11 @@ "dev": true }, "uglify-js": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.1.tgz", - "integrity": "sha512-W7KxyzeaQmZvUFbGj4+YFshhVrMBGSg2IbcYAjGWGvx8DHvJMclbTDMpffdxFUGPBHjIytk7KJUR/KUXstUGDw==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.0.tgz", + "integrity": "sha512-TWYSWa9T2pPN4DIJYbU9oAjQx+5qdV5RUDxwARg8fmJZrD/V27Zj0JngW5xg1DFz42G0uDYl2XhzF6alSzD62w==", "dev": true, - "optional": true, - "requires": { - "commander": "~2.20.3", - "source-map": "~0.6.1" - } + "optional": true }, "unbzip2-stream": { "version": "1.4.3", @@ -4096,6 +4077,12 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, "wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", diff --git a/build/package.json b/build/package.json index 246c91c1fb0..9abd800348e 100644 --- a/build/package.json +++ b/build/package.json @@ -10,7 +10,7 @@ "homepage": "https://github.com/nextcloud/", "contributors": [], "devDependencies": { - "handlebars": "^4.7.6", + "handlebars": "^4.7.7", "jasmine-core": "~2.5.2", "jasmine-sinon": "^0.4.0", "jsdoc": "^3.6.6", 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/DB/QueryBuilder/QueryBuilder.php b/lib/private/DB/QueryBuilder/QueryBuilder.php index 83b233ac1b5..3549606c2db 100644 --- a/lib/private/DB/QueryBuilder/QueryBuilder.php +++ b/lib/private/DB/QueryBuilder/QueryBuilder.php @@ -1271,11 +1271,11 @@ class QueryBuilder implements IQueryBuilder { * @return int * @throws \BadMethodCallException When being called before an insert query has been run. */ - public function getLastInsertId() { + public function getLastInsertId(): int { if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::INSERT && $this->lastInsertedTable) { // lastInsertId() needs the prefix but no quotes $table = $this->prefixTableName($this->lastInsertedTable); - return (int) $this->connection->lastInsertId($table); + return $this->connection->lastInsertId($table); } throw new \BadMethodCallException('Invalid call to getLastInsertId without using insert() before.'); diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index 0dbc34fae2f..7bb0341e201 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -109,7 +109,7 @@ class Scanner extends BasicEmitter implements IScanner { * * * * @param string $path - * @return array an array of metadata of the file + * @return array|null an array of metadata of the file */ protected function getData($path) { $data = $this->storage->getMetaData($path); @@ -128,7 +128,7 @@ class Scanner extends BasicEmitter implements IScanner { * @param array|null|false $cacheData existing data in the cache for the file to be scanned * @param bool $lock set to false to disable getting an additional read lock during scanning * @param null $data the metadata for the file, as returned by the storage - * @return array an array of metadata of the scanned file + * @return array|null an array of metadata of the scanned file * @throws \OCP\Lock\LockedException */ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true, $data = null) { @@ -323,7 +323,7 @@ class Scanner extends BasicEmitter implements IScanner { * @param bool $recursive * @param int $reuse * @param bool $lock set to false to disable getting an additional read lock during scanning - * @return array an array of the meta data of the scanned file or folder + * @return array|null an array of the meta data of the scanned file or folder */ public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true) { if ($reuse === -1) { diff --git a/lib/private/Files/Cache/Storage.php b/lib/private/Files/Cache/Storage.php index 74f5df2a5b1..af37bef8415 100644 --- a/lib/private/Files/Cache/Storage.php +++ b/lib/private/Files/Cache/Storage.php @@ -77,7 +77,7 @@ class Storage { $connection = \OC::$server->getDatabaseConnection(); $available = $isAvailable ? 1 : 0; if ($connection->insertIfNotExist('*PREFIX*storages', ['id' => $this->storageId, 'available' => $available])) { - $this->numericId = (int)$connection->lastInsertId('*PREFIX*storages'); + $this->numericId = $connection->lastInsertId('*PREFIX*storages'); } else { if ($row = self::getStorageById($this->storageId)) { $this->numericId = (int)$row['numeric_id']; diff --git a/lib/private/Files/Storage/Storage.php b/lib/private/Files/Storage/Storage.php index 56d997ab974..73793aa31fb 100644 --- a/lib/private/Files/Storage/Storage.php +++ b/lib/private/Files/Storage/Storage.php @@ -93,7 +93,7 @@ interface Storage extends \OCP\Files\Storage { /** * @param string $path - * @return array + * @return array|null */ public function getMetaData($path); diff --git a/lib/private/Files/Storage/Wrapper/Encoding.php b/lib/private/Files/Storage/Wrapper/Encoding.php index c0587cd0263..e2b486546af 100644 --- a/lib/private/Files/Storage/Wrapper/Encoding.php +++ b/lib/private/Files/Storage/Wrapper/Encoding.php @@ -531,10 +531,6 @@ class Encoding extends Wrapper { return $result; } - /** - * @param string $path - * @return array - */ public function getMetaData($path) { return $this->storage->getMetaData($this->findPathToUse($path)); } diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php index ef44be5cefb..a7a915afad9 100644 --- a/lib/private/Files/Storage/Wrapper/Encryption.php +++ b/lib/private/Files/Storage/Wrapper/Encryption.php @@ -192,10 +192,6 @@ class Encryption extends Wrapper { return $data; } - /** - * @param string $path - * @return array - */ public function getMetaData($path) { $data = $this->storage->getMetaData($path); if (is_null($data)) { diff --git a/lib/private/Files/Storage/Wrapper/Jail.php b/lib/private/Files/Storage/Wrapper/Jail.php index dbbe2890df0..b7933708da8 100644 --- a/lib/private/Files/Storage/Wrapper/Jail.php +++ b/lib/private/Files/Storage/Wrapper/Jail.php @@ -441,10 +441,6 @@ class Jail extends Wrapper { return $this->getWrapperStorage()->getETag($this->getUnjailedPath($path)); } - /** - * @param string $path - * @return array - */ public function getMetaData($path) { return $this->getWrapperStorage()->getMetaData($this->getUnjailedPath($path)); } diff --git a/lib/private/Files/Storage/Wrapper/Wrapper.php b/lib/private/Files/Storage/Wrapper/Wrapper.php index ef8f7293ccb..cffe610c6c2 100644 --- a/lib/private/Files/Storage/Wrapper/Wrapper.php +++ b/lib/private/Files/Storage/Wrapper/Wrapper.php @@ -577,10 +577,6 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStrea return $this->getWrapperStorage()->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); } - /** - * @param string $path - * @return array - */ public function getMetaData($path) { return $this->getWrapperStorage()->getMetaData($path); } 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/private/User/Session.php b/lib/private/User/Session.php index 70c7f11c45f..c33d79b83cf 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -647,7 +647,7 @@ class Session implements IUserSession, Emitter { // Ignore and use empty string instead } - $this->manager->emit('\OC\User', 'preLogin', [$uid, $password]); + $this->manager->emit('\OC\User', 'preLogin', [$dbToken->getLoginName(), $password]); $user = $this->manager->get($uid); if (is_null($user)) { diff --git a/lib/public/DB/QueryBuilder/IQueryBuilder.php b/lib/public/DB/QueryBuilder/IQueryBuilder.php index 91ffab02f48..a4f3f3b10b0 100644 --- a/lib/public/DB/QueryBuilder/IQueryBuilder.php +++ b/lib/public/DB/QueryBuilder/IQueryBuilder.php @@ -990,7 +990,7 @@ interface IQueryBuilder { * @throws \BadMethodCallException When being called before an insert query has been run. * @since 9.0.0 */ - public function getLastInsertId(); + public function getLastInsertId(): int; /** * Returns the table name quoted and with database prefix as needed by the implementation diff --git a/lib/public/Files/Cache/IScanner.php b/lib/public/Files/Cache/IScanner.php index 3b00fa2af13..24281e2903d 100644 --- a/lib/public/Files/Cache/IScanner.php +++ b/lib/public/Files/Cache/IScanner.php @@ -45,7 +45,7 @@ interface IScanner { * @param int $parentId * @param array | null $cacheData existing data in the cache for the file to be scanned * @param bool $lock set to false to disable getting an additional read lock during scanning - * @return array an array of metadata of the scanned file + * @return array | null an array of metadata of the scanned file * @throws \OC\ServerNotAvailableException * @throws \OCP\Lock\LockedException * @since 9.0.0 @@ -59,7 +59,7 @@ interface IScanner { * @param bool $recursive * @param int $reuse * @param bool $lock set to false to disable getting an additional read lock during scanning - * @return array an array of the meta data of the scanned file or folder + * @return array | null an array of the meta data of the scanned file or folder * @since 9.0.0 */ public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true); 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', + ], ] ] ); |