diff options
Diffstat (limited to 'apps/provisioning_api/tests')
7 files changed, 1630 insertions, 840 deletions
diff --git a/apps/provisioning_api/tests/CapabilitiesTest.php b/apps/provisioning_api/tests/CapabilitiesTest.php new file mode 100644 index 00000000000..86d2bb8c4fa --- /dev/null +++ b/apps/provisioning_api/tests/CapabilitiesTest.php @@ -0,0 +1,77 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Provisioning_API\Tests; + +use OCA\FederatedFileSharing\FederatedShareProvider; +use OCA\Provisioning_API\Capabilities; +use OCP\App\IAppManager; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +/** + * Capabilities test for provisioning API. + * + * Note: group DB needed because of usage of overwriteService() + * + * @package OCA\Provisioning_API\Tests + * @group DB + */ +class CapabilitiesTest extends TestCase { + + protected IAppManager&MockObject $appManager; + protected Capabilities $capabilities; + + public function setUp(): void { + parent::setUp(); + $this->appManager = $this->createMock(IAppManager::class); + $this->capabilities = new Capabilities($this->appManager); + + $this->appManager->expects($this->once()) + ->method('getAppVersion') + ->with('provisioning_api') + ->willReturn('1.12'); + } + + public static function getCapabilitiesProvider(): array { + return [ + [true, false, false, true, false], + [true, true, false, true, false], + [true, true, true, true, true], + [false, false, false, false, false], + [false, true, false, false, false], + [false, true, true, false, true], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('getCapabilitiesProvider')] + public function testGetCapabilities(bool $federationAppEnabled, bool $federatedFileSharingAppEnabled, bool $lookupServerEnabled, bool $expectedFederatedScopeEnabled, bool $expectedPublishedScopeEnabled): void { + $this->appManager->expects($this->any()) + ->method('isEnabledForUser') + ->willReturnMap([ + ['federation', null, $federationAppEnabled], + ['federatedfilesharing', null, $federatedFileSharingAppEnabled], + ]); + + $federatedShareProvider = $this->createMock(FederatedShareProvider::class); + $this->overwriteService(FederatedShareProvider::class, $federatedShareProvider); + + $federatedShareProvider->expects($this->any()) + ->method('isLookupServerUploadEnabled') + ->willReturn($lookupServerEnabled); + + $expected = [ + 'provisioning_api' => [ + 'version' => '1.12', + 'AccountPropertyScopesVersion' => 2, + 'AccountPropertyScopesFederatedEnabled' => $expectedFederatedScopeEnabled, + 'AccountPropertyScopesPublishedEnabled' => $expectedPublishedScopeEnabled, + ], + ]; + $this->assertSame($expected, $this->capabilities->getCapabilities()); + } +} diff --git a/apps/provisioning_api/tests/Controller/AppConfigControllerTest.php b/apps/provisioning_api/tests/Controller/AppConfigControllerTest.php index cc4b6aa7555..1b09838cbc3 100644 --- a/apps/provisioning_api/tests/Controller/AppConfigControllerTest.php +++ b/apps/provisioning_api/tests/Controller/AppConfigControllerTest.php @@ -1,38 +1,30 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Provisioning_API\Tests\Controller; +use OC\AppConfig; use OCA\Provisioning_API\Controller\AppConfigController; +use OCP\App\IAppManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\Exceptions\AppConfigUnknownKeyException; use OCP\IAppConfig; -use OCP\IConfig; +use OCP\IGroupManager; +use OCP\IL10N; use OCP\IRequest; +use OCP\IUser; +use OCP\IUserSession; +use OCP\Server; +use OCP\Settings\IManager; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; +use function json_decode; +use function json_encode; /** * Class AppConfigControllerTest @@ -40,22 +32,27 @@ use Test\TestCase; * @package OCA\Provisioning_API\Tests */ class AppConfigControllerTest extends TestCase { - - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $config; - /** @var IAppConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $appConfig; + private IAppConfig&MockObject $appConfig; + private IUserSession&MockObject $userSession; + private IL10N&MockObject $l10n; + private IManager&MockObject $settingManager; + private IGroupManager&MockObject $groupManager; + private IAppManager $appManager; protected function setUp(): void { parent::setUp(); - $this->config = $this->createMock(IConfig::class); - $this->appConfig = $this->createMock(IAppConfig::class); + $this->appConfig = $this->createMock(AppConfig::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->l10n = $this->createMock(IL10N::class); + $this->settingManager = $this->createMock(IManager::class); + $this->groupManager = $this->createMock(IGroupManager::class); + $this->appManager = Server::get(IAppManager::class); } /** * @param string[] $methods - * @return AppConfigController|\PHPUnit\Framework\MockObject\MockObject + * @return AppConfigController|MockObject */ protected function getInstance(array $methods = []) { $request = $this->createMock(IRequest::class); @@ -64,23 +61,31 @@ class AppConfigControllerTest extends TestCase { return new AppConfigController( 'provisioning_api', $request, - $this->config, - $this->appConfig + $this->appConfig, + $this->userSession, + $this->l10n, + $this->groupManager, + $this->settingManager, + $this->appManager, ); } else { return $this->getMockBuilder(AppConfigController::class) ->setConstructorArgs([ 'provisioning_api', $request, - $this->config, $this->appConfig, + $this->userSession, + $this->l10n, + $this->groupManager, + $this->settingManager, + $this->appManager, ]) - ->setMethods($methods) + ->onlyMethods($methods) ->getMock(); } } - public function testGetApps() { + public function testGetApps(): void { $this->appConfig->expects($this->once()) ->method('getApps') ->willReturn(['apps']); @@ -91,21 +96,15 @@ class AppConfigControllerTest extends TestCase { $this->assertEquals(['data' => ['apps']], $result->getData()); } - public function dataGetKeys() { + public static function dataGetKeys(): array { return [ ['app1 ', null, new \InvalidArgumentException('error'), Http::STATUS_FORBIDDEN], ['app2', ['keys'], null, Http::STATUS_OK], ]; } - /** - * @dataProvider dataGetKeys - * @param string $app - * @param array|null $keys - * @param \Exception|null $throws - * @param int $status - */ - public function testGetKeys($app, $keys, $throws, $status) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetKeys')] + public function testGetKeys(string $app, ?array $keys, ?\Throwable $throws, int $status): void { $api = $this->getInstance(['verifyAppId']); if ($throws instanceof \Exception) { $api->expects($this->once()) @@ -113,15 +112,15 @@ class AppConfigControllerTest extends TestCase { ->with($app) ->willThrowException($throws); - $this->config->expects($this->never()) - ->method('getAppKeys'); + $this->appConfig->expects($this->never()) + ->method('getKeys'); } else { $api->expects($this->once()) ->method('verifyAppId') ->with($app); - $this->config->expects($this->once()) - ->method('getAppKeys') + $this->appConfig->expects($this->once()) + ->method('getKeys') ->with($app) ->willReturn($keys); } @@ -136,39 +135,28 @@ class AppConfigControllerTest extends TestCase { } } - public function dataGetValue() { + public static function dataGetValue(): array { return [ ['app1', 'key', 'default', null, new \InvalidArgumentException('error'), Http::STATUS_FORBIDDEN], ['app2', 'key', 'default', 'return', null, Http::STATUS_OK], ]; } - /** - * @dataProvider dataGetValue - * @param string $app - * @param string|null $key - * @param string|null $default - * @param string|null $return - * @param \Exception|null $throws - * @param int $status - */ - public function testGetValue($app, $key, $default, $return, $throws, $status) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetValue')] + public function testGetValue(string $app, string $key, string $default, ?string $return, ?\Throwable $throws, int $status): void { $api = $this->getInstance(['verifyAppId']); if ($throws instanceof \Exception) { $api->expects($this->once()) ->method('verifyAppId') ->with($app) ->willThrowException($throws); - - $this->config->expects($this->never()) - ->method('getAppValue'); } else { $api->expects($this->once()) ->method('verifyAppId') ->with($app); - $this->config->expects($this->once()) - ->method('getAppValue') + $this->appConfig->expects($this->once()) + ->method('getValueMixed') ->with($app, $key, $default) ->willReturn($return); } @@ -183,24 +171,35 @@ class AppConfigControllerTest extends TestCase { } } - public function dataSetValue() { + public static function dataSetValue(): array { return [ ['app1', 'key', 'default', new \InvalidArgumentException('error1'), null, Http::STATUS_FORBIDDEN], ['app2', 'key', 'default', null, new \InvalidArgumentException('error2'), Http::STATUS_FORBIDDEN], ['app2', 'key', 'default', null, null, Http::STATUS_OK], + ['app2', 'key', '1', null, null, Http::STATUS_OK, IAppConfig::VALUE_BOOL], + ['app2', 'key', '42', null, null, Http::STATUS_OK, IAppConfig::VALUE_INT], + ['app2', 'key', '4.2', null, null, Http::STATUS_OK, IAppConfig::VALUE_FLOAT], + ['app2', 'key', '42', null, null, Http::STATUS_OK, IAppConfig::VALUE_STRING], + ['app2', 'key', 'secret', null, null, Http::STATUS_OK, IAppConfig::VALUE_STRING | IAppConfig::VALUE_SENSITIVE], + ['app2', 'key', json_encode([4, 2]), null, null, Http::STATUS_OK, IAppConfig::VALUE_ARRAY], + ['app2', 'key', json_encode([4, 2]), null, null, Http::STATUS_OK, new AppConfigUnknownKeyException()], ]; } - /** - * @dataProvider dataSetValue - * @param string $app - * @param string|null $key - * @param string|null $value - * @param \Exception|null $appThrows - * @param \Exception|null $keyThrows - * @param int $status - */ - public function testSetValue($app, $key, $value, $appThrows, $keyThrows, $status) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSetValue')] + public function testSetValue(string $app, string $key, string $value, ?\Throwable $appThrows, ?\Throwable $keyThrows, int $status, int|\Throwable $type = IAppConfig::VALUE_MIXED): void { + $adminUser = $this->createMock(IUser::class); + $adminUser->expects($this->once()) + ->method('getUid') + ->willReturn('admin'); + + $this->userSession->expects($this->once()) + ->method('getUser') + ->willReturn($adminUser); + $this->groupManager->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->willReturn(true); $api = $this->getInstance(['verifyAppId', 'verifyConfigKey']); if ($appThrows instanceof \Exception) { $api->expects($this->once()) @@ -210,8 +209,8 @@ class AppConfigControllerTest extends TestCase { $api->expects($this->never()) ->method('verifyConfigKey'); - $this->config->expects($this->never()) - ->method('setAppValue'); + $this->appConfig->expects($this->never()) + ->method('setValueMixed'); } elseif ($keyThrows instanceof \Exception) { $api->expects($this->once()) ->method('verifyAppId') @@ -221,8 +220,8 @@ class AppConfigControllerTest extends TestCase { ->with($app, $key) ->willThrowException($keyThrows); - $this->config->expects($this->never()) - ->method('setAppValue'); + $this->appConfig->expects($this->never()) + ->method('setValueMixed'); } else { $api->expects($this->once()) ->method('verifyAppId') @@ -231,9 +230,38 @@ class AppConfigControllerTest extends TestCase { ->method('verifyConfigKey') ->with($app, $key); - $this->config->expects($this->once()) - ->method('setAppValue') - ->with($app, $key, $value); + if ($type instanceof \Throwable) { + $this->appConfig->expects($this->once()) + ->method('getDetails') + ->with($app, $key) + ->willThrowException($type); + } else { + $this->appConfig->expects($this->once()) + ->method('getDetails') + ->with($app, $key) + ->willReturn([ + 'app' => $app, + 'key' => $key, + 'value' => '', // 🤷 + 'type' => $type, + 'lazy' => false, + 'typeString' => (string)$type, // this is not accurate, but acceptable + 'sensitive' => ($type & IAppConfig::VALUE_SENSITIVE) !== 0, + ]); + } + + $configValueSetter = match ($type) { + IAppConfig::VALUE_BOOL => 'setValueBool', + IAppConfig::VALUE_FLOAT => 'setValueFloat', + IAppConfig::VALUE_INT => 'setValueInt', + IAppConfig::VALUE_STRING => 'setValueString', + IAppConfig::VALUE_ARRAY => 'setValueArray', + default => 'setValueMixed', + }; + + $this->appConfig->expects($this->once()) + ->method($configValueSetter) + ->with($app, $key, $configValueSetter === 'setValueArray' ? json_decode($value, true) : $value); } $result = $api->setValue($app, $key, $value); @@ -248,7 +276,7 @@ class AppConfigControllerTest extends TestCase { } } - public function dataDeleteValue() { + public static function dataDeleteValue(): array { return [ ['app1', 'key', new \InvalidArgumentException('error1'), null, Http::STATUS_FORBIDDEN], ['app2', 'key', null, new \InvalidArgumentException('error2'), Http::STATUS_FORBIDDEN], @@ -256,15 +284,8 @@ class AppConfigControllerTest extends TestCase { ]; } - /** - * @dataProvider dataDeleteValue - * @param string $app - * @param string|null $key - * @param \Exception|null $appThrows - * @param \Exception|null $keyThrows - * @param int $status - */ - public function testDeleteValue($app, $key, $appThrows, $keyThrows, $status) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataDeleteValue')] + public function testDeleteValue(string $app, string $key, ?\Throwable $appThrows, ?\Throwable $keyThrows, int $status): void { $api = $this->getInstance(['verifyAppId', 'verifyConfigKey']); if ($appThrows instanceof \Exception) { $api->expects($this->once()) @@ -274,8 +295,8 @@ class AppConfigControllerTest extends TestCase { $api->expects($this->never()) ->method('verifyConfigKey'); - $this->config->expects($this->never()) - ->method('deleteAppValue'); + $this->appConfig->expects($this->never()) + ->method('deleteKey'); } elseif ($keyThrows instanceof \Exception) { $api->expects($this->once()) ->method('verifyAppId') @@ -285,8 +306,8 @@ class AppConfigControllerTest extends TestCase { ->with($app, $key) ->willThrowException($keyThrows); - $this->config->expects($this->never()) - ->method('deleteAppValue'); + $this->appConfig->expects($this->never()) + ->method('deleteKey'); } else { $api->expects($this->once()) ->method('verifyAppId') @@ -295,8 +316,8 @@ class AppConfigControllerTest extends TestCase { ->method('verifyConfigKey') ->with($app, $key); - $this->config->expects($this->once()) - ->method('deleteAppValue') + $this->appConfig->expects($this->once()) + ->method('deleteKey') ->with($app, $key); } @@ -312,13 +333,13 @@ class AppConfigControllerTest extends TestCase { } } - public function testVerifyAppId() { + public function testVerifyAppId(): void { $api = $this->getInstance(); $this->invokePrivate($api, 'verifyAppId', ['activity']); $this->addToAssertionCount(1); } - public function dataVerifyAppIdThrows() { + public static function dataVerifyAppIdThrows(): array { return [ ['activity..'], ['activity/'], @@ -327,18 +348,15 @@ class AppConfigControllerTest extends TestCase { ]; } - /** - * @dataProvider dataVerifyAppIdThrows - * @param string $app - */ - public function testVerifyAppIdThrows($app) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataVerifyAppIdThrows')] + public function testVerifyAppIdThrows(string $app): void { $this->expectException(\InvalidArgumentException::class); $api = $this->getInstance(); $this->invokePrivate($api, 'verifyAppId', [$app]); } - public function dataVerifyConfigKey() { + public static function dataVerifyConfigKey(): array { return [ ['activity', 'abc', ''], ['dav', 'public_route', ''], @@ -347,19 +365,14 @@ class AppConfigControllerTest extends TestCase { ]; } - /** - * @dataProvider dataVerifyConfigKey - * @param string $app - * @param string $key - * @param string $value - */ - public function testVerifyConfigKey($app, $key, $value) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataVerifyConfigKey')] + public function testVerifyConfigKey(string $app, string $key, string $value): void { $api = $this->getInstance(); $this->invokePrivate($api, 'verifyConfigKey', [$app, $key, $value]); $this->addToAssertionCount(1); } - public function dataVerifyConfigKeyThrows() { + public static function dataVerifyConfigKeyThrows(): array { return [ ['activity', 'installed_version', ''], ['calendar', 'enabled', ''], @@ -373,13 +386,8 @@ class AppConfigControllerTest extends TestCase { ]; } - /** - * @dataProvider dataVerifyConfigKeyThrows - * @param string $app - * @param string $key - * @param string $value - */ - public function testVerifyConfigKeyThrows($app, $key, $value) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataVerifyConfigKeyThrows')] + public function testVerifyConfigKeyThrows(string $app, string $key, string $value): void { $this->expectException(\InvalidArgumentException::class); $api = $this->getInstance(); diff --git a/apps/provisioning_api/tests/Controller/AppsControllerTest.php b/apps/provisioning_api/tests/Controller/AppsControllerTest.php index 88125a93488..f95daeae7d3 100644 --- a/apps/provisioning_api/tests/Controller/AppsControllerTest.php +++ b/apps/provisioning_api/tests/Controller/AppsControllerTest.php @@ -1,37 +1,23 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Tom Needham <tom@owncloud.com> - * - * @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/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Provisioning_API\Tests\Controller; +use OC\Installer; use OCA\Provisioning_API\Controller\AppsController; +use OCA\Provisioning_API\Tests\TestCase; use OCP\App\IAppManager; +use OCP\AppFramework\OCS\OCSException; +use OCP\IAppConfig; +use OCP\IGroupManager; use OCP\IRequest; use OCP\IUserSession; +use OCP\Server; +use PHPUnit\Framework\MockObject\MockObject; /** * Class AppsTest @@ -40,47 +26,52 @@ use OCP\IUserSession; * * @package OCA\Provisioning_API\Tests */ -class AppsControllerTest extends \OCA\Provisioning_API\Tests\TestCase { - /** @var IAppManager */ - private $appManager; - /** @var AppsController */ - private $api; - /** @var IUserSession */ - private $userSession; +class AppsControllerTest extends TestCase { + private IAppManager $appManager; + private IAppConfig&MockObject $appConfig; + private Installer&MockObject $installer; + private AppsController $api; + private IUserSession $userSession; protected function setUp(): void { parent::setUp(); - $this->appManager = \OC::$server->getAppManager(); - $this->groupManager = \OC::$server->getGroupManager(); - $this->userSession = \OC::$server->getUserSession(); + $this->appManager = Server::get(IAppManager::class); + $this->groupManager = Server::get(IGroupManager::class); + $this->userSession = Server::get(IUserSession::class); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->installer = $this->createMock(Installer::class); - $request = $this->getMockBuilder(IRequest::class) - ->disableOriginalConstructor() - ->getMock(); + $request = $this->createMock(IRequest::class); $this->api = new AppsController( 'provisioning_api', $request, - $this->appManager + $this->appManager, + $this->installer, + $this->appConfig, ); } - public function testGetAppInfo() { + protected function tearDown(): void { + $this->userSession->setUser(null); + } + + public function testGetAppInfo(): void { $result = $this->api->getAppInfo('provisioning_api'); - $expected = \OC_App::getAppInfo('provisioning_api'); + $expected = $this->appManager->getAppInfo('provisioning_api'); $this->assertEquals($expected, $result->getData()); } - - public function testGetAppInfoOnBadAppID() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + + public function testGetAppInfoOnBadAppID(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(998); $this->api->getAppInfo('not_provisioning_api'); } - public function testGetApps() { + public function testGetApps(): void { $user = $this->generateUsers(); $this->groupManager->get('admin')->addUser($user); $this->userSession->setUser($user); @@ -91,13 +82,13 @@ class AppsControllerTest extends \OCA\Provisioning_API\Tests\TestCase { $this->assertEquals(count((new \OC_App())->listAllApps()), count($data['apps'])); } - public function testGetAppsEnabled() { + public function testGetAppsEnabled(): void { $result = $this->api->getApps('enabled'); $data = $result->getData(); $this->assertEquals(count(\OC_App::getEnabledApps()), count($data['apps'])); } - public function testGetAppsDisabled() { + public function testGetAppsDisabled(): void { $result = $this->api->getApps('disabled'); $data = $result->getData(); $apps = (new \OC_App)->listAllApps(); @@ -109,9 +100,9 @@ class AppsControllerTest extends \OCA\Provisioning_API\Tests\TestCase { $this->assertEquals(count($disabled), count($data['apps'])); } - - public function testGetAppsInvalidFilter() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + + public function testGetAppsInvalidFilter(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(101); $this->api->getApps('foo'); diff --git a/apps/provisioning_api/tests/Controller/GroupsControllerTest.php b/apps/provisioning_api/tests/Controller/GroupsControllerTest.php index bb8ec854390..85e5d733b1f 100644 --- a/apps/provisioning_api/tests/Controller/GroupsControllerTest.php +++ b/apps/provisioning_api/tests/Controller/GroupsControllerTest.php @@ -1,71 +1,43 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Tom Needham <tom@owncloud.com> - * - * @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/> - * + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Provisioning_API\Tests\Controller; -use OC\Accounts\AccountManager; use OC\Group\Manager; -use OC\SubAdmin; use OC\User\NoUserException; use OCA\Provisioning_API\Controller\GroupsController; use OCP\Accounts\IAccountManager; +use OCP\AppFramework\OCS\OCSException; +use OCP\Files\IRootFolder; +use OCP\Group\ISubAdmin; use OCP\IConfig; -use OCP\ILogger; +use OCP\IGroup; use OCP\IRequest; use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use OCP\L10N\IFactory; use OCP\UserInterface; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; class GroupsControllerTest extends \Test\TestCase { + protected IRequest&MockObject $request; + protected IUserManager&MockObject $userManager; + protected IConfig&MockObject $config; + protected Manager&MockObject $groupManager; + protected IUserSession&MockObject $userSession; + protected IAccountManager&MockObject $accountManager; + protected ISubAdmin&MockObject $subAdminManager; + protected IFactory&MockObject $l10nFactory; + protected LoggerInterface&MockObject $logger; + protected GroupsController&MockObject $api; - /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */ - protected $request; - /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */ - protected $userManager; - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ - protected $config; - /** @var Manager|\PHPUnit\Framework\MockObject\MockObject */ - protected $groupManager; - /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */ - protected $userSession; - /** @var AccountManager|\PHPUnit\Framework\MockObject\MockObject */ - protected $accountManager; - /** @var ILogger|\PHPUnit\Framework\MockObject\MockObject */ - protected $logger; - /** @var SubAdmin|\PHPUnit\Framework\MockObject\MockObject */ - protected $subAdminManager; - - /** @var GroupsController|\PHPUnit\Framework\MockObject\MockObject */ - protected $api; + private IRootFolder $rootFolder; protected function setUp(): void { @@ -76,15 +48,15 @@ class GroupsControllerTest extends \Test\TestCase { $this->config = $this->createMock(IConfig::class); $this->groupManager = $this->createMock(Manager::class); $this->userSession = $this->createMock(IUserSession::class); - $this->accountManager = $this->createMock(AccountManager::class); + $this->accountManager = $this->createMock(IAccountManager::class); + $this->subAdminManager = $this->createMock(ISubAdmin::class); $this->l10nFactory = $this->createMock(IFactory::class); - $this->logger = $this->createMock(ILogger::class); - - $this->subAdminManager = $this->createMock(SubAdmin::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->rootFolder = $this->createMock(IRootFolder::class); $this->groupManager - ->method('getSubAdmin') - ->willReturn($this->subAdminManager); + ->method('getSubAdmin') + ->willReturn($this->subAdminManager); $this->api = $this->getMockBuilder(GroupsController::class) ->setConstructorArgs([ @@ -95,25 +67,23 @@ class GroupsControllerTest extends \Test\TestCase { $this->groupManager, $this->userSession, $this->accountManager, + $this->subAdminManager, $this->l10nFactory, + $this->rootFolder, $this->logger ]) - ->setMethods(['fillStorageInfo']) + ->onlyMethods(['fillStorageInfo']) ->getMock(); } - /** - * @param string $gid - * @return \OCP\IGroup|\PHPUnit\Framework\MockObject\MockObject - */ - private function createGroup($gid) { - $group = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock(); + private function createGroup(string $gid): IGroup&MockObject { + $group = $this->createMock(IGroup::class); $group ->method('getGID') ->willReturn($gid); $group ->method('getDisplayName') - ->willReturn($gid.'-name'); + ->willReturn($gid . '-name'); $group ->method('count') ->willReturn(123); @@ -132,7 +102,7 @@ class GroupsControllerTest extends \Test\TestCase { /** * @param string $uid - * @return \OCP\IUser|\PHPUnit\Framework\MockObject\MockObject + * @return IUser&MockObject */ private function createUser($uid) { $user = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -181,20 +151,7 @@ class GroupsControllerTest extends \Test\TestCase { }); } - private function useAccountManager() { - $this->accountManager->expects($this->any()) - ->method('getUser') - ->willReturnCallback(function (IUser $user) { - return [ - IAccountManager::PROPERTY_PHONE => ['value' => '0800-call-' . $user->getUID()], - IAccountManager::PROPERTY_ADDRESS => ['value' => 'Holzweg 99, 0601 Herrera, Panama'], - IAccountManager::PROPERTY_WEBSITE => ['value' => 'https://' . $user->getUid() . '.pa'], - IAccountManager::PROPERTY_TWITTER => ['value' => '@' . $user->getUID()], - ]; - }); - } - - public function dataGetGroups() { + public static function dataGetGroups(): array { return [ [null, 0, 0], ['foo', 0, 0], @@ -204,14 +161,8 @@ class GroupsControllerTest extends \Test\TestCase { ]; } - /** - * @dataProvider dataGetGroups - * - * @param string|null $search - * @param int|null $limit - * @param int|null $offset - */ - public function testGetGroups($search, $limit, $offset) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetGroups')] + public function testGetGroups(?string $search, int $limit, int $offset): void { $groups = [$this->createGroup('group1'), $this->createGroup('group2')]; $search = $search === null ? '' : $search; @@ -227,13 +178,13 @@ class GroupsControllerTest extends \Test\TestCase { } /** - * @dataProvider dataGetGroups * * @param string|null $search * @param int|null $limit * @param int|null $offset */ - public function testGetGroupsDetails($search, $limit, $offset) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetGroups')] + public function testGetGroupsDetails($search, $limit, $offset): void { $groups = [$this->createGroup('group1'), $this->createGroup('group2')]; $search = $search === null ? '' : $search; @@ -265,7 +216,7 @@ class GroupsControllerTest extends \Test\TestCase { ]], $result->getData()); } - public function testGetGroupAsSubadmin() { + public function testGetGroupAsSubadmin(): void { $group = $this->createGroup('group'); $this->asSubAdminOfGroup($group); @@ -290,8 +241,8 @@ class GroupsControllerTest extends \Test\TestCase { } - public function testGetGroupAsIrrelevantSubadmin() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testGetGroupAsIrrelevantSubadmin(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(403); $group = $this->createGroup('group'); @@ -310,7 +261,7 @@ class GroupsControllerTest extends \Test\TestCase { $this->api->getGroup('group'); } - public function testGetGroupAsAdmin() { + public function testGetGroupAsAdmin(): void { $group = $this->createGroup('group'); $this->asAdmin(); @@ -335,8 +286,8 @@ class GroupsControllerTest extends \Test\TestCase { } - public function testGetGroupNonExisting() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testGetGroupNonExisting(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('The requested group could not be found'); $this->expectExceptionCode(404); @@ -346,15 +297,15 @@ class GroupsControllerTest extends \Test\TestCase { } - public function testGetSubAdminsOfGroupsNotExists() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testGetSubAdminsOfGroupsNotExists(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Group does not exist'); $this->expectExceptionCode(101); $this->api->getSubAdminsOfGroup('NonExistingGroup'); } - public function testGetSubAdminsOfGroup() { + public function testGetSubAdminsOfGroup(): void { $group = $this->createGroup('GroupWithSubAdmins'); $this->groupManager ->method('get') @@ -374,7 +325,7 @@ class GroupsControllerTest extends \Test\TestCase { $this->assertEquals(['SubAdmin1', 'SubAdmin2'], $result->getData()); } - public function testGetSubAdminsOfGroupEmptyList() { + public function testGetSubAdminsOfGroupEmptyList(): void { $group = $this->createGroup('GroupWithOutSubAdmins'); $this->groupManager ->method('get') @@ -393,8 +344,8 @@ class GroupsControllerTest extends \Test\TestCase { } - public function testAddGroupEmptyGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddGroupEmptyGroup(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Invalid group name'); $this->expectExceptionCode(101); @@ -402,8 +353,8 @@ class GroupsControllerTest extends \Test\TestCase { } - public function testAddGroupExistingGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddGroupExistingGroup(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(102); $this->groupManager @@ -414,45 +365,49 @@ class GroupsControllerTest extends \Test\TestCase { $this->api->addGroup('ExistingGroup'); } - public function testAddGroup() { + public function testAddGroup(): void { $this->groupManager ->method('groupExists') ->with('NewGroup') ->willReturn(false); + $group = $this->createGroup('NewGroup'); $this->groupManager ->expects($this->once()) ->method('createGroup') - ->with('NewGroup'); + ->with('NewGroup') + ->willReturn($group); $this->api->addGroup('NewGroup'); } - public function testAddGroupWithSpecialChar() { + public function testAddGroupWithSpecialChar(): void { $this->groupManager ->method('groupExists') ->with('Iñtërnâtiônà lizætiøn') ->willReturn(false); + $group = $this->createGroup('Iñtërnâtiônà lizætiøn'); $this->groupManager ->expects($this->once()) ->method('createGroup') - ->with('Iñtërnâtiônà lizætiøn'); + ->with('Iñtërnâtiônà lizætiøn') + ->willReturn($group); $this->api->addGroup('Iñtërnâtiônà lizætiøn'); } - public function testDeleteGroupNonExisting() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testDeleteGroupNonExisting(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(101); $this->api->deleteGroup('NonExistingGroup'); } - public function testDeleteAdminGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testDeleteAdminGroup(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(102); $this->groupManager @@ -463,7 +418,7 @@ class GroupsControllerTest extends \Test\TestCase { $this->api->deleteGroup('admin'); } - public function testDeleteGroup() { + public function testDeleteGroup(): void { $this->groupManager ->method('groupExists') ->with('ExistingGroup') @@ -482,7 +437,7 @@ class GroupsControllerTest extends \Test\TestCase { $this->api->deleteGroup('ExistingGroup'); } - public function testDeleteGroupEncoding() { + public function testDeleteGroupEncoding(): void { $this->groupManager ->method('groupExists') ->with('ExistingGroup A/B') @@ -501,11 +456,10 @@ class GroupsControllerTest extends \Test\TestCase { $this->api->deleteGroup(urlencode('ExistingGroup A/B')); } - public function testGetGroupUsersDetails() { + public function testGetGroupUsersDetails(): void { $gid = 'ncg1'; $this->asAdmin(); - $this->useAccountManager(); $users = [ 'ncu1' => $this->createUser('ncu1'), # regular @@ -518,7 +472,7 @@ class GroupsControllerTest extends \Test\TestCase { $this->userManager->expects($this->any()) ->method('get') ->willReturnCallback(function (string $uid) use ($users) { - return isset($users[$uid]) ? $users[$uid] : null; + return $users[$uid] ?? null; }); $group = $this->createGroup($gid); @@ -535,7 +489,7 @@ class GroupsControllerTest extends \Test\TestCase { ->method('getUserGroups') ->willReturn([$group]); - /** @var \PHPUnit\Framework\MockObject\MockObject */ + /** @var MockObject */ $this->subAdminManager->expects($this->any()) ->method('isSubAdminOfGroup') ->willReturn(false); @@ -547,11 +501,10 @@ class GroupsControllerTest extends \Test\TestCase { $this->api->getGroupUsersDetails($gid); } - public function testGetGroupUsersDetailsEncoded() { + public function testGetGroupUsersDetailsEncoded(): void { $gid = 'Department A/B C/D'; $this->asAdmin(); - $this->useAccountManager(); $users = [ 'ncu1' => $this->createUser('ncu1'), # regular @@ -564,7 +517,7 @@ class GroupsControllerTest extends \Test\TestCase { $this->userManager->expects($this->any()) ->method('get') ->willReturnCallback(function (string $uid) use ($users) { - return isset($users[$uid]) ? $users[$uid] : null; + return $users[$uid] ?? null; }); $group = $this->createGroup($gid); @@ -581,7 +534,7 @@ class GroupsControllerTest extends \Test\TestCase { ->method('getUserGroups') ->willReturn([$group]); - /** @var \PHPUnit\Framework\MockObject\MockObject */ + /** @var MockObject */ $this->subAdminManager->expects($this->any()) ->method('isSubAdminOfGroup') ->willReturn(false); diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php index 10f5a4841d4..0c0a0ae3d74 100644 --- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php +++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php @@ -1,62 +1,35 @@ <?php + + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Daniel Kesselberg <mail@danielkesselberg.de> - * @author Georg Ehrke <oc.list@georgehrke.com> - * @author GretaD <gretadoci@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author michag86 <micha_g@arcor.de> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sujith Haridasan <sujith.h@gmail.com> - * @author Thomas Citharel <nextcloud@tcit.fr> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Tom Needham <tom@owncloud.com> - * @author zulan <git@zulan.net> - * - * @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/> - * + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Provisioning_API\Tests\Controller; use Exception; -use OC\Accounts\AccountManager; use OC\Authentication\Token\RemoteWipe; use OC\Group\Manager; +use OC\KnownUser\KnownUserService; +use OC\PhoneNumberUtil; use OC\SubAdmin; -use OCA\FederatedFileSharing\FederatedShareProvider; use OCA\Provisioning_API\Controller\UsersController; -use OCA\Provisioning_API\FederatedShareProviderFactory; use OCA\Settings\Mailer\NewUserMailHelper; +use OCP\Accounts\IAccount; use OCP\Accounts\IAccountManager; +use OCP\Accounts\IAccountProperty; +use OCP\Accounts\IAccountPropertyCollection; use OCP\App\IAppManager; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCS\OCSException; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\IRootFolder; +use OCP\Group\ISubAdmin; use OCP\IConfig; use OCP\IGroup; use OCP\IL10N; -use OCP\ILogger; +use OCP\IPhoneNumberUtil; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUser; @@ -66,63 +39,59 @@ use OCP\L10N\IFactory; use OCP\Mail\IEMailTemplate; use OCP\Security\Events\GenerateSecurePasswordEvent; use OCP\Security\ISecureRandom; +use OCP\User\Backend\ISetDisplayNameBackend; use OCP\UserInterface; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use RuntimeException; use Test\TestCase; class UsersControllerTest extends TestCase { - - /** @var IUserManager|MockObject */ - protected $userManager; - /** @var IConfig|MockObject */ - protected $config; - /** @var IAppManager|MockObject */ - protected $appManager; - /** @var Manager|MockObject */ - protected $groupManager; - /** @var IUserSession|MockObject */ - protected $userSession; - /** @var ILogger|MockObject */ - protected $logger; - /** @var UsersController|MockObject */ - protected $api; - /** @var AccountManager|MockObject */ - protected $accountManager; - /** @var IURLGenerator|MockObject */ - protected $urlGenerator; - /** @var IRequest|MockObject */ - protected $request; - /** @var IFactory|MockObject */ - private $l10nFactory; - /** @var NewUserMailHelper|MockObject */ - private $newUserMailHelper; - /** @var FederatedShareProviderFactory|MockObject */ - private $federatedShareProviderFactory; - /** @var ISecureRandom|MockObject */ - private $secureRandom; - /** @var RemoteWipe|MockObject */ - private $remoteWipe; - /** @var IEventDispatcher */ - private $eventDispatcher; + protected IUserManager&MockObject $userManager; + protected IConfig&MockObject $config; + protected Manager&MockObject $groupManager; + protected IUserSession&MockObject $userSession; + protected LoggerInterface&MockObject $logger; + protected UsersController&MockObject $api; + protected IAccountManager&MockObject $accountManager; + protected ISubAdmin&MockObject $subAdminManager; + protected IURLGenerator&MockObject $urlGenerator; + protected IRequest&MockObject $request; + private IFactory&MockObject $l10nFactory; + private NewUserMailHelper&MockObject $newUserMailHelper; + private ISecureRandom&MockObject $secureRandom; + private RemoteWipe&MockObject $remoteWipe; + private KnownUserService&MockObject $knownUserService; + private IEventDispatcher&MockObject $eventDispatcher; + private IRootFolder $rootFolder; + private IPhoneNumberUtil $phoneNumberUtil; + private IAppManager $appManager; protected function setUp(): void { parent::setUp(); $this->userManager = $this->createMock(IUserManager::class); $this->config = $this->createMock(IConfig::class); - $this->appManager = $this->createMock(IAppManager::class); $this->groupManager = $this->createMock(Manager::class); $this->userSession = $this->createMock(IUserSession::class); - $this->logger = $this->createMock(ILogger::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->request = $this->createMock(IRequest::class); - $this->accountManager = $this->createMock(AccountManager::class); + $this->accountManager = $this->createMock(IAccountManager::class); + $this->subAdminManager = $this->createMock(ISubAdmin::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->l10nFactory = $this->createMock(IFactory::class); $this->newUserMailHelper = $this->createMock(NewUserMailHelper::class); - $this->federatedShareProviderFactory = $this->createMock(FederatedShareProviderFactory::class); $this->secureRandom = $this->createMock(ISecureRandom::class); $this->remoteWipe = $this->createMock(RemoteWipe::class); + $this->knownUserService = $this->createMock(KnownUserService::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + $this->phoneNumberUtil = new PhoneNumberUtil(); + $this->appManager = $this->createMock(IAppManager::class); + $this->rootFolder = $this->createMock(IRootFolder::class); + + $l10n = $this->createMock(IL10N::class); + $l10n->method('t')->willReturnCallback(fn (string $txt, array $replacement = []) => sprintf($txt, ...$replacement)); + $this->l10nFactory->method('get')->with('provisioning_api')->willReturn($l10n); $this->api = $this->getMockBuilder(UsersController::class) ->setConstructorArgs([ @@ -130,24 +99,27 @@ class UsersControllerTest extends TestCase { $this->request, $this->userManager, $this->config, - $this->appManager, $this->groupManager, $this->userSession, $this->accountManager, + $this->subAdminManager, + $this->l10nFactory, + $this->rootFolder, $this->urlGenerator, $this->logger, - $this->l10nFactory, $this->newUserMailHelper, - $this->federatedShareProviderFactory, $this->secureRandom, $this->remoteWipe, + $this->knownUserService, $this->eventDispatcher, + $this->phoneNumberUtil, + $this->appManager, ]) - ->setMethods(['fillStorageInfo']) + ->onlyMethods(['fillStorageInfo']) ->getMock(); } - public function testGetUsersAsAdmin() { + public function testGetUsersAsAdmin(): void { $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); @@ -169,16 +141,17 @@ class UsersControllerTest extends TestCase { ->with('MyCustomSearch') ->willReturn(['Admin' => [], 'Foo' => [], 'Bar' => []]); - $expected = ['users' => [ - 'Admin', - 'Foo', - 'Bar', - ], + $expected = [ + 'users' => [ + 'Admin', + 'Foo', + 'Bar', + ], ]; $this->assertEquals($expected, $this->api->getUsers('MyCustomSearch')->getData()); } - public function testGetUsersAsSubAdmin() { + public function testGetUsersAsSubAdmin(): void { $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); @@ -226,8 +199,7 @@ class UsersControllerTest extends TestCase { ->willReturn($subAdminManager); $this->groupManager ->expects($this->any()) - ->method('displayNamesInGroup') - ->will($this->onConsecutiveCalls(['AnotherUserInTheFirstGroup' => []], ['UserInTheSecondGroup' => []])); + ->method('displayNamesInGroup')->willReturnOnConsecutiveCalls(['AnotherUserInTheFirstGroup' => []], ['UserInTheSecondGroup' => []]); $expected = [ 'users' => [ @@ -238,9 +210,134 @@ class UsersControllerTest extends TestCase { $this->assertEquals($expected, $this->api->getUsers('MyCustomSearch')->getData()); } + private function createUserMock(string $uid, bool $enabled): MockObject&IUser { + $mockUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $mockUser + ->method('getUID') + ->willReturn($uid); + $mockUser + ->method('isEnabled') + ->willReturn($enabled); + return $mockUser; + } + + public function testGetDisabledUsersAsAdmin(): void { + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->willReturn('admin'); + $this->userSession + ->expects($this->atLeastOnce()) + ->method('getUser') + ->willReturn($loggedInUser); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->willReturn(true); + $this->userManager + ->expects($this->once()) + ->method('getDisabledUsers') + ->with(3, 0, 'MyCustomSearch') + ->willReturn([ + $this->createUserMock('admin', false), + $this->createUserMock('foo', false), + $this->createUserMock('bar', false), + ]); + + $expected = [ + 'users' => [ + 'admin' => ['id' => 'admin'], + 'foo' => ['id' => 'foo'], + 'bar' => ['id' => 'bar'], + ], + ]; + $this->assertEquals($expected, $this->api->getDisabledUsersDetails('MyCustomSearch', 3)->getData()); + } + + public function testGetDisabledUsersAsSubAdmin(): void { + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->willReturn('subadmin'); + $this->userSession + ->expects($this->atLeastOnce()) + ->method('getUser') + ->willReturn($loggedInUser); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->willReturn(false); + $firstGroup = $this->getMockBuilder('OCP\IGroup') + ->disableOriginalConstructor() + ->getMock(); + $secondGroup = $this->getMockBuilder('OCP\IGroup') + ->disableOriginalConstructor() + ->getMock(); + $subAdminManager = $this->getMockBuilder('OC\SubAdmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdmin') + ->with($loggedInUser) + ->willReturn(true); + $subAdminManager + ->expects($this->once()) + ->method('getSubAdminsGroups') + ->with($loggedInUser) + ->willReturn([$firstGroup, $secondGroup]); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->willReturn($subAdminManager); + $this->groupManager + ->expects($this->never()) + ->method('displayNamesInGroup'); - public function testAddUserAlreadyExisting() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + $firstGroup + ->expects($this->once()) + ->method('searchUsers') + ->with('MyCustomSearch') + ->willReturn([ + $this->createUserMock('user1', false), + $this->createUserMock('bob', true), + $this->createUserMock('user2', false), + $this->createUserMock('alice', true), + ]); + + $secondGroup + ->expects($this->once()) + ->method('searchUsers') + ->with('MyCustomSearch') + ->willReturn([ + $this->createUserMock('user2', false), + $this->createUserMock('joe', true), + $this->createUserMock('user3', false), + $this->createUserMock('jim', true), + $this->createUserMock('john', true), + ]); + + + $expected = [ + 'users' => [ + 'user1' => ['id' => 'user1'], + 'user2' => ['id' => 'user2'], + 'user3' => ['id' => 'user3'], + ], + ]; + $this->assertEquals($expected, $this->api->getDisabledUsersDetails('MyCustomSearch', 3)->getData()); + } + + + public function testAddUserAlreadyExisting(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(102); $this->userManager @@ -256,7 +353,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -273,9 +370,9 @@ class UsersControllerTest extends TestCase { } - public function testAddUserNonExistingGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('group NonExistingGroup does not exist'); + public function testAddUserNonExistingGroup(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('Group NonExistingGroup does not exist'); $this->expectExceptionCode(104); $this->userManager @@ -287,7 +384,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -309,9 +406,9 @@ class UsersControllerTest extends TestCase { } - public function testAddUserExistingGroupNonExistingGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('group NonExistingGroup does not exist'); + public function testAddUserExistingGroupNonExistingGroup(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('Group NonExistingGroup does not exist'); $this->expectExceptionCode(104); $this->userManager @@ -323,7 +420,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -338,10 +435,6 @@ class UsersControllerTest extends TestCase { $this->groupManager ->expects($this->exactly(2)) ->method('groupExists') - ->withConsecutive( - ['ExistingGroup'], - ['NonExistingGroup'] - ) ->willReturnMap([ ['ExistingGroup', true], ['NonExistingGroup', false] @@ -350,7 +443,7 @@ class UsersControllerTest extends TestCase { $this->api->addUser('NewUser', 'pass', '', '', ['ExistingGroup', 'NonExistingGroup']); } - public function testAddUserSuccessful() { + public function testAddUserSuccessful(): void { $this->userManager ->expects($this->once()) ->method('userExists') @@ -359,7 +452,8 @@ class UsersControllerTest extends TestCase { $this->userManager ->expects($this->once()) ->method('createUser') - ->with('NewUser', 'PasswordOfTheNewUser'); + ->with('NewUser', 'PasswordOfTheNewUser') + ->willReturn($this->createMock(IUser::class)); $this->logger ->expects($this->once()) ->method('info') @@ -368,7 +462,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -387,27 +481,33 @@ class UsersControllerTest extends TestCase { )); } - public function testAddUserSuccessfulWithDisplayName() { + public function testAddUserSuccessfulWithDisplayName(): void { + /** + * @var UserController + */ $api = $this->getMockBuilder(UsersController::class) ->setConstructorArgs([ 'provisioning_api', $this->request, $this->userManager, $this->config, - $this->appManager, $this->groupManager, $this->userSession, $this->accountManager, + $this->subAdminManager, + $this->l10nFactory, + $this->rootFolder, $this->urlGenerator, $this->logger, - $this->l10nFactory, $this->newUserMailHelper, - $this->federatedShareProviderFactory, $this->secureRandom, $this->remoteWipe, + $this->knownUserService, $this->eventDispatcher, + $this->phoneNumberUtil, + $this->appManager, ]) - ->setMethods(['editUser']) + ->onlyMethods(['editUser']) ->getMock(); $this->userManager @@ -418,7 +518,8 @@ class UsersControllerTest extends TestCase { $this->userManager ->expects($this->once()) ->method('createUser') - ->with('NewUser', 'PasswordOfTheNewUser'); + ->with('NewUser', 'PasswordOfTheNewUser') + ->willReturn($this->createMock(IUser::class)); $this->logger ->expects($this->once()) ->method('info') @@ -450,7 +551,7 @@ class UsersControllerTest extends TestCase { )); } - public function testAddUserSuccessfulGenerateUserID() { + public function testAddUserSuccessfulGenerateUserID(): void { $this->config ->expects($this->any()) ->method('getAppValue') @@ -468,7 +569,8 @@ class UsersControllerTest extends TestCase { $this->userManager ->expects($this->once()) ->method('createUser') - ->with($this->anything(), 'PasswordOfTheNewUser'); + ->with($this->anything(), 'PasswordOfTheNewUser') + ->willReturn($this->createMock(IUser::class)); $this->logger ->expects($this->once()) ->method('info') @@ -477,7 +579,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -493,7 +595,7 @@ class UsersControllerTest extends TestCase { ->method('generate') ->with(10) ->willReturnCallback(function () { - return (string)rand(1000000000, 9999999999); + return (string)rand(100000000, 999999999); }); $this->assertTrue(key_exists( @@ -502,7 +604,7 @@ class UsersControllerTest extends TestCase { )); } - public function testAddUserSuccessfulGeneratePassword() { + public function testAddUserSuccessfulGeneratePassword(): void { $this->userManager ->expects($this->once()) ->method('userExists') @@ -510,7 +612,7 @@ class UsersControllerTest extends TestCase { ->willReturn(false); $newUser = $this->createMock(IUser::class); $newUser->expects($this->once()) - ->method('setEMailAddress'); + ->method('setSystemEMailAddress'); $this->userManager ->expects($this->once()) ->method('createUser') @@ -523,7 +625,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -546,10 +648,55 @@ class UsersControllerTest extends TestCase { )); } + public function testAddUserSuccessfulLowercaseEmail(): void { + $this->userManager + ->expects($this->once()) + ->method('userExists') + ->with('NewUser') + ->willReturn(false); + $newUser = $this->createMock(IUser::class); + $newUser->expects($this->once()) + ->method('setSystemEMailAddress') + ->with('foo@bar.com'); + $this->userManager + ->expects($this->once()) + ->method('createUser') + ->willReturn($newUser); + $this->logger + ->expects($this->once()) + ->method('info') + ->with('Successful addUser call with userid: NewUser', ['app' => 'ocs_api']); + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->exactly(2)) + ->method('getUID') + ->willReturn('adminUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->willReturn($loggedInUser); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('adminUser') + ->willReturn(true); + $this->eventDispatcher + ->expects($this->once()) + ->method('dispatchTyped') + ->with(new GenerateSecurePasswordEvent()); + + $this->assertTrue(key_exists( + 'id', + $this->api->addUser('NewUser', '', '', 'fOo@BaR.CoM')->getData() + )); + } + - public function testAddUserFailedToGenerateUserID() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('Could not create non-existing user id'); + public function testAddUserFailedToGenerateUserID(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('Could not create non-existing user ID'); $this->expectExceptionCode(111); $this->config @@ -573,7 +720,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -590,8 +737,8 @@ class UsersControllerTest extends TestCase { } - public function testAddUserEmailRequired() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddUserEmailRequired(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Required email address was not provided'); $this->expectExceptionCode(110); @@ -616,7 +763,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -635,7 +782,7 @@ class UsersControllerTest extends TestCase { )); } - public function testAddUserExistingGroup() { + public function testAddUserExistingGroup(): void { $this->userManager ->expects($this->once()) ->method('userExists') @@ -645,7 +792,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -682,23 +829,25 @@ class UsersControllerTest extends TestCase { ->method('get') ->with('ExistingGroup') ->willReturn($group); + + $calls = [ + ['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']], + ['Added userid NewUser to group ExistingGroup', ['app' => 'ocs_api']], + ]; $this->logger ->expects($this->exactly(2)) ->method('info') - ->withConsecutive( - ['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']], - ['Added userid NewUser to group ExistingGroup', ['app' => 'ocs_api']] - ); + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, func_get_args()); + }); - $this->assertTrue(key_exists( - 'id', - $this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', '', ['ExistingGroup'])->getData() - )); + $this->assertArrayHasKey('id', $this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', '', ['ExistingGroup'])->getData()); } - public function testAddUserUnsuccessful() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddUserUnsuccessful(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Bad request'); $this->expectExceptionCode(101); @@ -712,20 +861,22 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('createUser') ->with('NewUser', 'PasswordOfTheNewUser') - ->will($this->throwException($exception)); + ->willThrowException($exception); $this->logger ->expects($this->once()) - ->method('logException') - ->with($exception, [ - 'message' => 'Failed addUser attempt with exception.', - 'level' => ILogger::ERROR, - 'app' => 'ocs_api', - ]); + ->method('error') + ->with( + 'Failed addUser attempt with exception.', + [ + 'app' => 'ocs_api', + 'exception' => $exception + ] + ); $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('adminUser'); $this->userSession @@ -742,16 +893,16 @@ class UsersControllerTest extends TestCase { } - public function testAddUserAsSubAdminNoGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('no group specified (required for subadmins)'); + public function testAddUserAsSubAdminNoGroup(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('No group specified (required for sub-admins)'); $this->expectExceptionCode(106); $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('regularUser'); $this->userSession @@ -775,16 +926,16 @@ class UsersControllerTest extends TestCase { } - public function testAddUserAsSubAdminValidGroupNotSubAdmin() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('insufficient privileges for group ExistingGroup'); + public function testAddUserAsSubAdminValidGroupNotSubAdmin(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('Insufficient privileges for group ExistingGroup'); $this->expectExceptionCode(105); $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('regularUser'); $this->userSession @@ -823,7 +974,7 @@ class UsersControllerTest extends TestCase { $this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', '', ['ExistingGroup'])->getData(); } - public function testAddUserAsSubAdminExistingGroups() { + public function testAddUserAsSubAdminExistingGroups(): void { $this->userManager ->expects($this->once()) ->method('userExists') @@ -833,7 +984,7 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('subAdminUser'); $this->userSession @@ -848,11 +999,10 @@ class UsersControllerTest extends TestCase { $this->groupManager ->expects($this->exactly(2)) ->method('groupExists') - ->withConsecutive( - ['ExistingGroup1'], - ['ExistingGroup2'] - ) - ->willReturn(true); + ->willReturnMap([ + ['ExistingGroup1', true], + ['ExistingGroup2', true] + ]); $user = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); @@ -878,24 +1028,23 @@ class UsersControllerTest extends TestCase { $this->groupManager ->expects($this->exactly(4)) ->method('get') - ->withConsecutive( - ['ExistingGroup1'], - ['ExistingGroup2'], - ['ExistingGroup1'], - ['ExistingGroup2'] - ) ->willReturnMap([ ['ExistingGroup1', $existingGroup1], ['ExistingGroup2', $existingGroup2] ]); + + $calls = [ + ['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']], + ['Added userid NewUser to group ExistingGroup1', ['app' => 'ocs_api']], + ['Added userid NewUser to group ExistingGroup2', ['app' => 'ocs_api']], + ]; $this->logger ->expects($this->exactly(3)) ->method('info') - ->withConsecutive( - ['Successful addUser call with userid: NewUser', ['app' => 'ocs_api']], - ['Added userid NewUser to group ExistingGroup1', ['app' => 'ocs_api']], - ['Added userid NewUser to group ExistingGroup2', ['app' => 'ocs_api']] - ); + ->willReturnCallback(function () use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, func_get_args()); + }); $subAdminManager = $this->getMockBuilder('OC\SubAdmin') ->disableOriginalConstructor()->getMock(); $this->groupManager @@ -905,21 +1054,17 @@ class UsersControllerTest extends TestCase { $subAdminManager ->expects($this->exactly(2)) ->method('isSubAdminOfGroup') - ->withConsecutive( - [$loggedInUser, $existingGroup1], - [$loggedInUser, $existingGroup2] - ) - ->willReturn(true); + ->willReturnMap([ + [$loggedInUser, $existingGroup1, true], + [$loggedInUser, $existingGroup2, true], + ]); - $this->assertTrue(key_exists( - 'id', - $this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', '', ['ExistingGroup1', 'ExistingGroup2'])->getData() - )); + $this->assertArrayHasKey('id', $this->api->addUser('NewUser', 'PasswordOfTheNewUser', '', '', ['ExistingGroup1', 'ExistingGroup2'])->getData()); } - public function testGetUserTargetDoesNotExist() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testGetUserTargetDoesNotExist(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('User does not exist'); $this->expectExceptionCode(404); @@ -927,7 +1072,6 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $this->userSession - ->expects($this->once()) ->method('getUser') ->willReturn($loggedInUser); $this->userManager @@ -939,10 +1083,11 @@ class UsersControllerTest extends TestCase { $this->api->getUser('UserToGet'); } - public function testGetUserDataAsAdmin() { - $group = $this->getMockBuilder(IGroup::class) - ->disableOriginalConstructor() - ->getMock(); + public function testGetUserDataAsAdmin(): void { + $group0 = $this->createMock(IGroup::class); + $group1 = $this->createMock(IGroup::class); + $group2 = $this->createMock(IGroup::class); + $group3 = $this->createMock(IGroup::class); $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); @@ -950,33 +1095,29 @@ class UsersControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) ->method('getUID') ->willReturn('admin'); $targetUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $targetUser->expects($this->once()) - ->method('getEMailAddress') + ->method('getSystemEMailAddress') ->willReturn('demo@nextcloud.com'); $this->userSession - ->expects($this->once()) ->method('getUser') ->willReturn($loggedInUser); $this->userManager - ->expects($this->exactly(2)) ->method('get') ->with('UID') ->willReturn($targetUser); $this->groupManager - ->expects($this->once()) ->method('isAdmin') ->with('admin') ->willReturn(true); $this->groupManager ->expects($this->any()) ->method('getUserGroups') - ->willReturn([$group, $group, $group]); + ->willReturn([$group0, $group1, $group2]); $this->groupManager ->expects($this->once()) ->method('getSubAdmin') @@ -984,38 +1125,43 @@ class UsersControllerTest extends TestCase { $subAdminManager ->expects($this->once()) ->method('getSubAdminsGroups') - ->willReturn([$group]); - $group->expects($this->at(0)) + ->willReturn([$group3]); + $group0->expects($this->once()) ->method('getGID') ->willReturn('group0'); - $group->expects($this->at(1)) + $group1->expects($this->once()) ->method('getGID') ->willReturn('group1'); - $group->expects($this->at(2)) + $group2->expects($this->once()) ->method('getGID') ->willReturn('group2'); - $group->expects($this->at(3)) + $group3->expects($this->once()) ->method('getGID') ->willReturn('group3'); - $this->accountManager->expects($this->any())->method('getUser') - ->with($targetUser) - ->willReturn( - [ - IAccountManager::PROPERTY_ADDRESS => ['value' => 'address'], - IAccountManager::PROPERTY_PHONE => ['value' => 'phone'], - IAccountManager::PROPERTY_TWITTER => ['value' => 'twitter'], - IAccountManager::PROPERTY_WEBSITE => ['value' => 'website'], - ] - ); + + $this->mockAccount($targetUser, [ + IAccountManager::PROPERTY_ADDRESS => ['value' => 'address'], + IAccountManager::PROPERTY_PHONE => ['value' => 'phone'], + IAccountManager::PROPERTY_TWITTER => ['value' => 'twitter'], + IAccountManager::PROPERTY_BLUESKY => ['value' => 'bluesky'], + IAccountManager::PROPERTY_FEDIVERSE => ['value' => 'fediverse'], + IAccountManager::PROPERTY_WEBSITE => ['value' => 'website'], + IAccountManager::PROPERTY_ORGANISATION => ['value' => 'organisation'], + IAccountManager::PROPERTY_ROLE => ['value' => 'role'], + IAccountManager::PROPERTY_HEADLINE => ['value' => 'headline'], + IAccountManager::PROPERTY_BIOGRAPHY => ['value' => 'biography'], + IAccountManager::PROPERTY_PROFILE_ENABLED => ['value' => '1'], + IAccountManager::PROPERTY_PRONOUNS => ['value' => 'they/them'], + ]); $this->config - ->expects($this->at(0)) ->method('getUserValue') - ->with('UID', 'core', 'enabled', 'true') - ->willReturn('true'); + ->willReturnMap([ + ['UID', 'core', 'enabled', 'true', 'true'], + ]); $this->api ->expects($this->once()) ->method('fillStorageInfo') - ->with('UID') + ->with($targetUser) ->willReturn(['DummyValue']); $backend = $this->createMock(UserInterface::class); @@ -1032,11 +1178,15 @@ class UsersControllerTest extends TestCase { ->method('getHome') ->willReturn('/var/www/newtcloud/data/UID'); $targetUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getLastLogin') ->willReturn(1521191471); $targetUser ->expects($this->once()) + ->method('getFirstLogin') + ->willReturn(1511191471); + $targetUser + ->expects($this->once()) ->method('getBackendClassName') ->willReturn('Database'); $targetUser @@ -1057,53 +1207,63 @@ class UsersControllerTest extends TestCase { 'id' => 'UID', 'enabled' => true, 'storageLocation' => '/var/www/newtcloud/data/UID', + 'firstLoginTimestamp' => 1511191471, + 'lastLoginTimestamp' => 1521191471, 'lastLogin' => 1521191471000, 'backend' => 'Database', 'subadmin' => ['group3'], 'quota' => ['DummyValue'], 'email' => 'demo@nextcloud.com', 'displayname' => 'Demo User', + 'display-name' => 'Demo User', 'phone' => 'phone', 'address' => 'address', 'website' => 'website', 'twitter' => 'twitter', + 'bluesky' => 'bluesky', + 'fediverse' => 'fediverse', 'groups' => ['group0', 'group1', 'group2'], 'language' => 'de', 'locale' => null, 'backendCapabilities' => [ 'setDisplayName' => true, 'setPassword' => true, - ] + ], + 'additional_mail' => [], + 'organisation' => 'organisation', + 'role' => 'role', + 'headline' => 'headline', + 'biography' => 'biography', + 'profile_enabled' => '1', + 'notify_email' => null, + 'manager' => '', + 'pronouns' => 'they/them', ]; $this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID'])); } - public function testGetUserDataAsSubAdminAndUserIsAccessible() { + public function testGetUserDataAsSubAdminAndUserIsAccessible(): void { $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->once()) ->method('getUID') ->willReturn('subadmin'); $targetUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $targetUser - ->expects($this->once()) - ->method('getEMailAddress') - ->willReturn('demo@nextcloud.com'); - $this->userSession ->expects($this->once()) + ->method('getSystemEMailAddress') + ->willReturn('demo@nextcloud.com'); + $this->userSession ->method('getUser') ->willReturn($loggedInUser); $this->userManager - ->expects($this->exactly(2)) ->method('get') ->with('UID') ->willReturn($targetUser); $this->groupManager - ->expects($this->once()) ->method('isAdmin') ->with('subadmin') ->willReturn(false); @@ -1128,14 +1288,14 @@ class UsersControllerTest extends TestCase { ->method('getSubAdmin') ->willReturn($subAdminManager); $this->config - ->expects($this->at(0)) ->method('getUserValue') - ->with('UID', 'core', 'enabled', 'true') - ->willReturn('true'); + ->willReturnMap([ + ['UID', 'core', 'enabled', 'true', 'true'], + ]); $this->api ->expects($this->once()) ->method('fillStorageInfo') - ->with('UID') + ->with($targetUser) ->willReturn(['DummyValue']); $backend = $this->createMock(UserInterface::class); @@ -1148,15 +1308,18 @@ class UsersControllerTest extends TestCase { ->method('getDisplayName') ->willReturn('Demo User'); $targetUser - ->expects($this->once()) - ->method('getHome') - ->willReturn('/var/www/newtcloud/data/UID'); + ->expects($this->never()) + ->method('getHome'); $targetUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getLastLogin') ->willReturn(1521191471); $targetUser ->expects($this->once()) + ->method('getFirstLogin') + ->willReturn(1511191471); + $targetUser + ->expects($this->once()) ->method('getBackendClassName') ->willReturn('Database'); $targetUser @@ -1166,16 +1329,21 @@ class UsersControllerTest extends TestCase { $targetUser ->method('getUID') ->willReturn('UID'); - $this->accountManager->expects($this->any())->method('getUser') - ->with($targetUser) - ->willReturn( - [ - IAccountManager::PROPERTY_ADDRESS => ['value' => 'address'], - IAccountManager::PROPERTY_PHONE => ['value' => 'phone'], - IAccountManager::PROPERTY_TWITTER => ['value' => 'twitter'], - IAccountManager::PROPERTY_WEBSITE => ['value' => 'website'], - ] - ); + + $this->mockAccount($targetUser, [ + IAccountManager::PROPERTY_ADDRESS => ['value' => 'address'], + IAccountManager::PROPERTY_PHONE => ['value' => 'phone'], + IAccountManager::PROPERTY_TWITTER => ['value' => 'twitter'], + IAccountManager::PROPERTY_BLUESKY => ['value' => 'bluesky'], + IAccountManager::PROPERTY_FEDIVERSE => ['value' => 'fediverse'], + IAccountManager::PROPERTY_WEBSITE => ['value' => 'website'], + IAccountManager::PROPERTY_ORGANISATION => ['value' => 'organisation'], + IAccountManager::PROPERTY_ROLE => ['value' => 'role'], + IAccountManager::PROPERTY_HEADLINE => ['value' => 'headline'], + IAccountManager::PROPERTY_BIOGRAPHY => ['value' => 'biography'], + IAccountManager::PROPERTY_PROFILE_ENABLED => ['value' => '1'], + IAccountManager::PROPERTY_PRONOUNS => ['value' => 'they/them'], + ]); $this->l10nFactory ->expects($this->once()) @@ -1186,46 +1354,58 @@ class UsersControllerTest extends TestCase { $expected = [ 'id' => 'UID', 'enabled' => true, - 'storageLocation' => '/var/www/newtcloud/data/UID', + 'firstLoginTimestamp' => 1511191471, + 'lastLoginTimestamp' => 1521191471, 'lastLogin' => 1521191471000, 'backend' => 'Database', 'subadmin' => [], 'quota' => ['DummyValue'], 'email' => 'demo@nextcloud.com', 'displayname' => 'Demo User', + 'display-name' => 'Demo User', 'phone' => 'phone', 'address' => 'address', 'website' => 'website', 'twitter' => 'twitter', + 'bluesky' => 'bluesky', + 'fediverse' => 'fediverse', 'groups' => [], 'language' => 'da', 'locale' => null, 'backendCapabilities' => [ 'setDisplayName' => true, 'setPassword' => true, - ] + ], + 'additional_mail' => [], + 'organisation' => 'organisation', + 'role' => 'role', + 'headline' => 'headline', + 'biography' => 'biography', + 'profile_enabled' => '1', + 'notify_email' => null, + 'manager' => '', + 'pronouns' => 'they/them', ]; $this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID'])); } - public function testGetUserDataAsSubAdminAndUserIsNotAccessible() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionCode(997); + public function testGetUserDataAsSubAdminAndUserIsNotAccessible(): void { + $this->expectException(OCSException::class); + $this->expectExceptionCode(998); $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->exactly(2)) + ->expects($this->exactly(4)) ->method('getUID') ->willReturn('subadmin'); $targetUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $this->userSession - ->expects($this->once()) ->method('getUser') ->willReturn($loggedInUser); $this->userManager @@ -1254,28 +1434,24 @@ class UsersControllerTest extends TestCase { $this->invokePrivate($this->api, 'getUser', ['UserToGet']); } - public function testGetUserDataAsSubAdminSelfLookup() { + public function testGetUserDataAsSubAdminSelfLookup(): void { $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->exactly(2)) ->method('getUID') ->willReturn('UID'); $targetUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $this->userSession - ->expects($this->once()) ->method('getUser') ->willReturn($loggedInUser); $this->userManager - ->expects($this->exactly(2)) ->method('get') ->with('UID') ->willReturn($targetUser); $this->groupManager - ->expects($this->once()) ->method('isAdmin') ->with('UID') ->willReturn(false); @@ -1302,7 +1478,7 @@ class UsersControllerTest extends TestCase { $this->api ->expects($this->once()) ->method('fillStorageInfo') - ->with('UID') + ->with($targetUser) ->willReturn(['DummyValue']); $backend = $this->createMock(UserInterface::class); @@ -1316,37 +1492,44 @@ class UsersControllerTest extends TestCase { ->willReturn('Subadmin User'); $targetUser ->expects($this->once()) - ->method('getEMailAddress') + ->method('getSystemEMailAddress') ->willReturn('subadmin@nextcloud.com'); $targetUser ->method('getUID') ->willReturn('UID'); $targetUser - ->expects($this->once()) - ->method('getHome') - ->willReturn('/var/www/newtcloud/data/UID'); + ->expects($this->never()) + ->method('getHome'); $targetUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getLastLogin') ->willReturn(1521191471); $targetUser ->expects($this->once()) + ->method('getFirstLogin') + ->willReturn(1511191471); + $targetUser + ->expects($this->once()) ->method('getBackendClassName') ->willReturn('Database'); $targetUser ->expects($this->once()) ->method('getBackend') ->willReturn($backend); - $this->accountManager->expects($this->any())->method('getUser') - ->with($targetUser) - ->willReturn( - [ - IAccountManager::PROPERTY_ADDRESS => ['value' => 'address'], - IAccountManager::PROPERTY_PHONE => ['value' => 'phone'], - IAccountManager::PROPERTY_TWITTER => ['value' => 'twitter'], - IAccountManager::PROPERTY_WEBSITE => ['value' => 'website'], - ] - ); + $this->mockAccount($targetUser, [ + IAccountManager::PROPERTY_ADDRESS => ['value' => 'address'], + IAccountManager::PROPERTY_PHONE => ['value' => 'phone'], + IAccountManager::PROPERTY_TWITTER => ['value' => 'twitter'], + IAccountManager::PROPERTY_BLUESKY => ['value' => 'bluesky'], + IAccountManager::PROPERTY_FEDIVERSE => ['value' => 'fediverse'], + IAccountManager::PROPERTY_WEBSITE => ['value' => 'website'], + IAccountManager::PROPERTY_ORGANISATION => ['value' => 'organisation'], + IAccountManager::PROPERTY_ROLE => ['value' => 'role'], + IAccountManager::PROPERTY_HEADLINE => ['value' => 'headline'], + IAccountManager::PROPERTY_BIOGRAPHY => ['value' => 'biography'], + IAccountManager::PROPERTY_PROFILE_ENABLED => ['value' => '1'], + IAccountManager::PROPERTY_PRONOUNS => ['value' => 'they/them'], + ]); $this->l10nFactory ->expects($this->once()) @@ -1356,29 +1539,42 @@ class UsersControllerTest extends TestCase { $expected = [ 'id' => 'UID', - 'storageLocation' => '/var/www/newtcloud/data/UID', + 'firstLoginTimestamp' => 1511191471, + 'lastLoginTimestamp' => 1521191471, 'lastLogin' => 1521191471000, 'backend' => 'Database', 'subadmin' => [], 'quota' => ['DummyValue'], 'email' => 'subadmin@nextcloud.com', 'displayname' => 'Subadmin User', + 'display-name' => 'Subadmin User', 'phone' => 'phone', 'address' => 'address', 'website' => 'website', 'twitter' => 'twitter', + 'bluesky' => 'bluesky', + 'fediverse' => 'fediverse', 'groups' => [], 'language' => 'ru', 'locale' => null, 'backendCapabilities' => [ 'setDisplayName' => false, 'setPassword' => false, - ] + ], + 'additional_mail' => [], + 'organisation' => 'organisation', + 'role' => 'role', + 'headline' => 'headline', + 'biography' => 'biography', + 'profile_enabled' => '1', + 'notify_email' => null, + 'manager' => '', + 'pronouns' => 'they/them', ]; $this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID'])); } - public function dataSearchByPhoneNumbers(): array { + public static function dataSearchByPhoneNumbers(): array { return [ 'Invalid country' => ['Not a country code', ['12345' => ['NaN']], 400, null, null, []], 'No number to search' => ['DE', ['12345' => ['NaN']], 200, null, null, []], @@ -1391,14 +1587,15 @@ class UsersControllerTest extends TestCase { ]; } - /** - * @dataProvider dataSearchByPhoneNumbers - * @param string $location - * @param array $search - * @param int $status - * @param array $expected - */ - public function testSearchByPhoneNumbers(string $location, array $search, int $status, ?array $searchUsers, ?array $userMatches, array $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSearchByPhoneNumbers')] + public function testSearchByPhoneNumbers(string $location, array $search, int $status, ?array $searchUsers, ?array $userMatches, array $expected): void { + $knownTo = 'knownTo'; + $user = $this->createMock(IUser::class); + $user->method('getUID') + ->willReturn($knownTo); + $this->userSession->method('getUser') + ->willReturn($user); + if ($searchUsers === null) { $this->accountManager->expects($this->never()) ->method('searchUsers'); @@ -1407,6 +1604,14 @@ class UsersControllerTest extends TestCase { ->method('searchUsers') ->with(IAccountManager::PROPERTY_PHONE, $searchUsers) ->willReturn($userMatches); + + $this->knownUserService->expects($this->once()) + ->method('deleteKnownTo') + ->with($knownTo); + + $this->knownUserService->expects($this->exactly(count($expected))) + ->method('storeIsKnownToUser') + ->with($knownTo, $this->anything()); } $this->urlGenerator->method('getAbsoluteURL') @@ -1419,7 +1624,7 @@ class UsersControllerTest extends TestCase { self::assertEquals($expected, $response->getData()); } - public function testEditUserRegularUserSelfEditChangeDisplayName() { + public function testEditUserRegularUserSelfEditChangeDisplayName(): void { $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); @@ -1441,8 +1646,13 @@ class UsersControllerTest extends TestCase { ->willReturn($targetUser); $targetUser ->expects($this->once()) + ->method('getBackend') + ->willReturn($this->createMock(ISetDisplayNameBackend::class)); + $targetUser + ->expects($this->once()) ->method('setDisplayName') - ->with('NewDisplayName'); + ->with('NewDisplayName') + ->willReturn(true); $targetUser ->expects($this->any()) ->method('getUID') @@ -1451,7 +1661,7 @@ class UsersControllerTest extends TestCase { $this->assertEquals([], $this->api->editUser('UserToEdit', 'display', 'NewDisplayName')->getData()); } - public function testEditUserRegularUserSelfEditChangeEmailValid() { + public function testEditUserRegularUserSelfEditChangeEmailValid(): void { $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); @@ -1473,21 +1683,184 @@ class UsersControllerTest extends TestCase { ->willReturn($targetUser); $targetUser ->expects($this->once()) - ->method('setEMailAddress') + ->method('setSystemEMailAddress') ->with('demo@nextcloud.com'); $targetUser ->expects($this->any()) ->method('getUID') ->willReturn('UID'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + + $this->config->method('getSystemValue')->willReturnCallback(fn (string $key, mixed $default) => $default); + $this->assertEquals([], $this->api->editUser('UserToEdit', 'email', 'demo@nextcloud.com')->getData()); } + public function testEditUserRegularUserSelfEditAddAdditionalEmailValid(): void { + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->willReturn('UID'); + $targetUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->willReturn($loggedInUser); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->willReturn($targetUser); + $targetUser + ->expects($this->any()) + ->method('getUID') + ->willReturn('UID'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); - public function testEditUserRegularUserSelfEditChangeEmailInvalid() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionCode(102); + $userAccount = $this->createMock(IAccount::class); + + $this->accountManager + ->expects($this->once()) + ->method('getAccount') + ->with($targetUser) + ->willReturn($userAccount); + $this->accountManager + ->expects($this->once()) + ->method('updateAccount') + ->with($userAccount); + + $this->assertEquals([], $this->api->editUser('UserToEdit', 'additional_mail', 'demo1@nextcloud.com')->getData()); + } + + public function testEditUserRegularUserSelfEditAddAdditionalEmailMainAddress(): void { + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->willReturn('UID'); + $targetUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->willReturn($loggedInUser); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->willReturn($targetUser); + $targetUser + ->expects($this->any()) + ->method('getUID') + ->willReturn('UID'); + + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $targetUser + ->expects($this->any()) + ->method('getSystemEMailAddress') + ->willReturn('demo@nextcloud.com'); + + $userAccount = $this->createMock(IAccount::class); + + $this->accountManager + ->expects($this->never()) + ->method('getAccount') + ->with($targetUser) + ->willReturn($userAccount); + $this->accountManager + ->expects($this->never()) + ->method('updateAccount') + ->with($userAccount); + + $this->expectException(OCSException::class); + $this->expectExceptionCode(101); + $this->api->editUser('UserToEdit', 'additional_mail', 'demo@nextcloud.com')->getData(); + } + + public function testEditUserRegularUserSelfEditAddAdditionalEmailDuplicate(): void { + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->willReturn('UID'); + $targetUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->willReturn($loggedInUser); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->willReturn($targetUser); + $targetUser + ->expects($this->any()) + ->method('getUID') + ->willReturn('UID'); + + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + + $property = $this->createMock(IAccountProperty::class); + $property->method('getValue') + ->willReturn('demo1@nextcloud.com'); + $collection = $this->createMock(IAccountPropertyCollection::class); + $collection->method('getPropertyByValue') + ->with('demo1@nextcloud.com') + ->willReturn($property); + + $userAccount = $this->createMock(IAccount::class); + $userAccount->method('getPropertyCollection') + ->with(IAccountManager::COLLECTION_EMAIL) + ->willReturn($collection); + + $this->accountManager + ->expects($this->once()) + ->method('getAccount') + ->with($targetUser) + ->willReturn($userAccount); + $this->accountManager + ->expects($this->never()) + ->method('updateAccount') + ->with($userAccount); + + $this->expectException(OCSException::class); + $this->expectExceptionCode(101); + $this->api->editUser('UserToEdit', 'additional_mail', 'demo1@nextcloud.com')->getData(); + } + + public function testEditUserRegularUserSelfEditChangeEmailInvalid(): void { + $this->expectException(OCSException::class); + $this->expectExceptionCode(101); $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() @@ -1513,10 +1886,169 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UID'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + + $this->config->method('getSystemValue')->willReturnCallback(fn (string $key, mixed $default) => $default); + $this->api->editUser('UserToEdit', 'email', 'demo.org'); } - public function testEditUserRegularUserSelfEditChangePassword() { + public static function selfEditChangePropertyProvider(): array { + return [ + [IAccountManager::PROPERTY_TWITTER, '@oldtwitter', '@newtwitter'], + [IAccountManager::PROPERTY_BLUESKY, 'old.bluesky', 'new.bluesky'], + [IAccountManager::PROPERTY_FEDIVERSE, '@oldFediverse@floss.social', '@newFediverse@floss.social'], + [IAccountManager::PROPERTY_PHONE, '1234', '12345'], + [IAccountManager::PROPERTY_ADDRESS, 'Something street 2', 'Another street 3'], + [IAccountManager::PROPERTY_WEBSITE, 'https://examplesite1', 'https://examplesite2'], + [IAccountManager::PROPERTY_ORGANISATION, 'Organisation A', 'Organisation B'], + [IAccountManager::PROPERTY_ROLE, 'Human', 'Alien'], + [IAccountManager::PROPERTY_HEADLINE, 'Hi', 'Hello'], + [IAccountManager::PROPERTY_BIOGRAPHY, 'A biography', 'Another biography'], + [IAccountManager::PROPERTY_PROFILE_ENABLED, '1', '0'], + [IAccountManager::PROPERTY_PRONOUNS, 'they/them', 'he/him'], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('selfEditChangePropertyProvider')] + public function testEditUserRegularUserSelfEditChangeProperty($propertyName, $oldValue, $newValue): void { + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->willReturn('UID'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->willReturn($loggedInUser); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->willReturn($loggedInUser); + + $backend = $this->createMock(UserInterface::class); + $loggedInUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + + $propertyMock = $this->createMock(IAccountProperty::class); + $propertyMock->expects($this->any()) + ->method('getName') + ->willReturn($propertyName); + $propertyMock->expects($this->any()) + ->method('getValue') + ->willReturn($oldValue); + $propertyMock->expects($this->once()) + ->method('setValue') + ->with($newValue) + ->willReturnSelf(); + $propertyMock->expects($this->any()) + ->method('getScope') + ->willReturn(IAccountManager::SCOPE_LOCAL); + + $accountMock = $this->createMock(IAccount::class); + $accountMock->expects($this->any()) + ->method('getProperty') + ->with($propertyName) + ->willReturn($propertyMock); + + $this->accountManager->expects($this->atLeastOnce()) + ->method('getAccount') + ->with($loggedInUser) + ->willReturn($accountMock); + $this->accountManager->expects($this->once()) + ->method('updateAccount') + ->with($accountMock); + + $this->assertEquals([], $this->api->editUser('UserToEdit', $propertyName, $newValue)->getData()); + } + + public function selfEditChangePropertyScopeProvider() { + return [ + [IAccountManager::PROPERTY_AVATAR, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_DISPLAYNAME, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_EMAIL, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_TWITTER, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_BLUESKY, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_FEDIVERSE, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_PHONE, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_ADDRESS, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_WEBSITE, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_ORGANISATION, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_ROLE, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_HEADLINE, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_BIOGRAPHY, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_PROFILE_ENABLED, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + [IAccountManager::PROPERTY_PRONOUNS, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('selfEditChangePropertyProvider')] + public function testEditUserRegularUserSelfEditChangePropertyScope($propertyName, $oldScope, $newScope): void { + $loggedInUser = $this->getMockBuilder(IUser::class) + ->disableOriginalConstructor() + ->getMock(); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->willReturn('UID'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->willReturn($loggedInUser); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->willReturn($loggedInUser); + + $backend = $this->createMock(UserInterface::class); + $loggedInUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + + $propertyMock = $this->createMock(IAccountProperty::class); + $propertyMock->expects($this->any()) + ->method('getName') + ->willReturn($propertyName); + $propertyMock->expects($this->any()) + ->method('getValue') + ->willReturn('somevalue'); + $propertyMock->expects($this->any()) + ->method('getScope') + ->willReturn($oldScope); + $propertyMock->expects($this->atLeastOnce()) + ->method('setScope') + ->with($newScope) + ->willReturnSelf(); + + $accountMock = $this->createMock(IAccount::class); + $accountMock->expects($this->any()) + ->method('getProperty') + ->with($propertyName) + ->willReturn($propertyMock); + + $this->accountManager->expects($this->atLeastOnce()) + ->method('getAccount') + ->with($loggedInUser) + ->willReturn($accountMock); + $this->accountManager->expects($this->once()) + ->method('updateAccount') + ->with($accountMock); + + $this->assertEquals([], $this->api->editUser('UserToEdit', $propertyName . 'Scope', $newScope)->getData()); + } + + public function testEditUserRegularUserSelfEditChangePassword(): void { $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); @@ -1549,14 +2081,20 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UID'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->assertEquals([], $this->api->editUser('UserToEdit', 'password', 'NewPassword')->getData()); } - public function testEditUserRegularUserSelfEditChangeQuota() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionCode(997); + public function testEditUserRegularUserSelfEditChangeQuota(): void { + $this->expectException(OCSException::class); + $this->expectExceptionCode(113); $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() @@ -1582,10 +2120,25 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UID'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->api->editUser('UserToEdit', 'quota', 'NewQuota'); } - public function testEditUserAdminUserSelfEditChangeValidQuota() { + public function testEditUserAdminUserSelfEditChangeValidQuota(): void { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->willReturnCallback(function ($appid, $key, $default) { + if ($key === 'max_quota') { + return '-1'; + } + return null; + }); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser ->expects($this->any()) @@ -1614,15 +2167,21 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UID'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->assertEquals([], $this->api->editUser('UserToEdit', 'quota', '3042824')->getData()); } - public function testEditUserAdminUserSelfEditChangeInvalidQuota() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('Invalid quota value ABC'); - $this->expectExceptionCode(103); + public function testEditUserAdminUserSelfEditChangeInvalidQuota(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('Invalid quota value: ABC'); + $this->expectExceptionCode(101); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser @@ -1649,10 +2208,25 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UID'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->api->editUser('UserToEdit', 'quota', 'ABC'); } - public function testEditUserAdminUserEditChangeValidQuota() { + public function testEditUserAdminUserEditChangeValidQuota(): void { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->willReturnCallback(function ($appid, $key, $default) { + if ($key === 'max_quota') { + return '-1'; + } + return null; + }); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser ->expects($this->any()) @@ -1688,10 +2262,16 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UID'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->assertEquals([], $this->api->editUser('UserToEdit', 'quota', '3042824')->getData()); } - public function testEditUserSelfEditChangeLanguage() { + public function testEditUserSelfEditChangeLanguage(): void { $this->l10nFactory->expects($this->once()) ->method('findAvailableLanguages') ->willReturn(['en', 'de', 'sv']); @@ -1730,21 +2310,25 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UserToEdit'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->assertEquals([], $this->api->editUser('UserToEdit', 'language', 'de')->getData()); } - public function dataEditUserSelfEditChangeLanguageButForced() { + public static function dataEditUserSelfEditChangeLanguageButForced(): array { return [ ['de'], [true], ]; } - /** - * @dataProvider dataEditUserSelfEditChangeLanguageButForced - */ - public function testEditUserSelfEditChangeLanguageButForced($forced) { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + #[\PHPUnit\Framework\Attributes\DataProvider('dataEditUserSelfEditChangeLanguageButForced')] + public function testEditUserSelfEditChangeLanguageButForced($forced): void { + $this->expectException(OCSException::class); $this->config->expects($this->any()) ->method('getSystemValue') @@ -1780,10 +2364,16 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UserToEdit'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->assertEquals([], $this->api->editUser('UserToEdit', 'language', 'de')->getData()); } - public function testEditUserAdminEditChangeLanguage() { + public function testEditUserAdminEditChangeLanguage(): void { $this->l10nFactory->expects($this->once()) ->method('findAvailableLanguages') ->willReturn(['en', 'de', 'sv']); @@ -1821,14 +2411,18 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UserToEdit'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->assertEquals([], $this->api->editUser('UserToEdit', 'language', 'de')->getData()); } - /** - * @dataProvider dataEditUserSelfEditChangeLanguageButForced - */ - public function testEditUserAdminEditChangeLanguageInvalidLanguage() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + #[\PHPUnit\Framework\Attributes\DataProvider('dataEditUserSelfEditChangeLanguageButForced')] + public function testEditUserAdminEditChangeLanguageInvalidLanguage(): void { + $this->expectException(OCSException::class); $this->l10nFactory->expects($this->once()) @@ -1867,10 +2461,25 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UserToEdit'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->assertEquals([], $this->api->editUser('UserToEdit', 'language', 'ru')->getData()); } - public function testEditUserSubadminUserAccessible() { + public function testEditUserSubadminUserAccessible(): void { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->willReturnCallback(function ($appid, $key, $default) { + if ($key === 'max_quota') { + return '-1'; + } + return null; + }); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser ->expects($this->any()) @@ -1906,13 +2515,19 @@ class UsersControllerTest extends TestCase { ->method('getUID') ->willReturn('UID'); + $backend = $this->createMock(UserInterface::class); + $targetUser + ->expects($this->any()) + ->method('getBackend') + ->willReturn($backend); + $this->assertEquals([], $this->api->editUser('UserToEdit', 'quota', '3042824')->getData()); } - public function testEditUserSubadminUserInaccessible() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionCode(997); + public function testEditUserSubadminUserInaccessible(): void { + $this->expectException(OCSException::class); + $this->expectExceptionCode(998); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser @@ -1950,9 +2565,9 @@ class UsersControllerTest extends TestCase { } - public function testDeleteUserNotExistingUser() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionCode(101); + public function testDeleteUserNotExistingUser(): void { + $this->expectException(OCSException::class); + $this->expectExceptionCode(998); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser @@ -1973,8 +2588,8 @@ class UsersControllerTest extends TestCase { } - public function testDeleteUserSelf() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testDeleteUserSelf(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(101); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2000,7 +2615,7 @@ class UsersControllerTest extends TestCase { $this->api->deleteUser('UserToDelete'); } - public function testDeleteSuccessfulUserAsAdmin() { + public function testDeleteSuccessfulUserAsAdmin(): void { $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser ->expects($this->any()) @@ -2034,8 +2649,8 @@ class UsersControllerTest extends TestCase { } - public function testDeleteUnsuccessfulUserAsAdmin() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testDeleteUnsuccessfulUserAsAdmin(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(101); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2070,7 +2685,7 @@ class UsersControllerTest extends TestCase { $this->api->deleteUser('UserToDelete'); } - public function testDeleteSuccessfulUserAsSubadmin() { + public function testDeleteSuccessfulUserAsSubadmin(): void { $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser ->expects($this->any()) @@ -2115,8 +2730,8 @@ class UsersControllerTest extends TestCase { } - public function testDeleteUnsuccessfulUserAsSubadmin() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testDeleteUnsuccessfulUserAsSubadmin(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(101); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2163,9 +2778,9 @@ class UsersControllerTest extends TestCase { } - public function testDeleteUserAsSubAdminAndUserIsNotAccessible() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionCode(997); + public function testDeleteUserAsSubAdminAndUserIsNotAccessible(): void { + $this->expectException(OCSException::class); + $this->expectExceptionCode(998); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser @@ -2207,8 +2822,8 @@ class UsersControllerTest extends TestCase { } - public function testGetUsersGroupsTargetUserNotExisting() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testGetUsersGroupsTargetUserNotExisting(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(998); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2220,10 +2835,10 @@ class UsersControllerTest extends TestCase { $this->api->getUsersGroups('UserToLookup'); } - public function testGetUsersGroupsSelfTargetted() { + public function testGetUsersGroupsSelfTargetted(): void { $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(3)) ->method('getUID') ->willReturn('UserToLookup'); $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2249,10 +2864,10 @@ class UsersControllerTest extends TestCase { $this->assertEquals(['groups' => ['DummyValue']], $this->api->getUsersGroups('UserToLookup')->getData()); } - public function testGetUsersGroupsForAdminUser() { + public function testGetUsersGroupsForAdminUser(): void { $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser - ->expects($this->exactly(2)) + ->expects($this->exactly(3)) ->method('getUID') ->willReturn('admin'); $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2283,10 +2898,10 @@ class UsersControllerTest extends TestCase { $this->assertEquals(['groups' => ['DummyValue']], $this->api->getUsersGroups('UserToLookup')->getData()); } - public function testGetUsersGroupsForSubAdminUserAndUserIsAccessible() { + public function testGetUsersGroupsForSubAdminUserAndUserIsAccessible(): void { $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser - ->expects($this->exactly(2)) + ->expects($this->exactly(3)) ->method('getUID') ->willReturn('subadmin'); $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2344,13 +2959,13 @@ class UsersControllerTest extends TestCase { } - public function testGetUsersGroupsForSubAdminUserAndUserIsInaccessible() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionCode(997); + public function testGetUsersGroupsForSubAdminUserAndUserIsInaccessible(): void { + $this->expectException(OCSException::class); + $this->expectExceptionCode(998); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser - ->expects($this->exactly(2)) + ->expects($this->exactly(3)) ->method('getUID') ->willReturn('subadmin'); $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2393,8 +3008,8 @@ class UsersControllerTest extends TestCase { } - public function testAddToGroupWithTargetGroupNotExisting() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddToGroupWithTargetGroupNotExisting(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(102); $this->groupManager->expects($this->once()) @@ -2406,16 +3021,16 @@ class UsersControllerTest extends TestCase { } - public function testAddToGroupWithNoGroupSpecified() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddToGroupWithNoGroupSpecified(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(101); $this->api->addToGroup('TargetUser'); } - public function testAddToGroupWithTargetUserNotExisting() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddToGroupWithTargetUserNotExisting(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(103); $targetGroup = $this->createMock(IGroup::class); @@ -2428,13 +3043,13 @@ class UsersControllerTest extends TestCase { } - public function testAddToGroupNoSubadmin() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddToGroupNoSubadmin(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(104); $targetUser = $this->createMock(IUser::class); $loggedInUser = $this->createMock(IUser::class); - $loggedInUser->expects($this->once()) + $loggedInUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('subadmin'); @@ -2475,10 +3090,10 @@ class UsersControllerTest extends TestCase { $this->api->addToGroup('TargetUser', 'GroupToAddTo'); } - public function testAddToGroupSuccessAsSubadmin() { + public function testAddToGroupSuccessAsSubadmin(): void { $targetUser = $this->createMock(IUser::class); $loggedInUser = $this->createMock(IUser::class); - $loggedInUser->expects($this->once()) + $loggedInUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('subadmin'); @@ -2519,10 +3134,10 @@ class UsersControllerTest extends TestCase { $this->assertEquals(new DataResponse(), $this->api->addToGroup('TargetUser', 'GroupToAddTo')); } - public function testAddToGroupSuccessAsAdmin() { + public function testAddToGroupSuccessAsAdmin(): void { $targetUser = $this->createMock(IUser::class); $loggedInUser = $this->createMock(IUser::class); - $loggedInUser->expects($this->once()) + $loggedInUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('admin'); @@ -2562,8 +3177,8 @@ class UsersControllerTest extends TestCase { } - public function testRemoveFromGroupWithNoTargetGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testRemoveFromGroupWithNoTargetGroup(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(101); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2576,8 +3191,8 @@ class UsersControllerTest extends TestCase { } - public function testRemoveFromGroupWithEmptyTargetGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testRemoveFromGroupWithEmptyTargetGroup(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(101); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2590,8 +3205,8 @@ class UsersControllerTest extends TestCase { } - public function testRemoveFromGroupWithNotExistingTargetGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testRemoveFromGroupWithNotExistingTargetGroup(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(102); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2609,8 +3224,8 @@ class UsersControllerTest extends TestCase { } - public function testRemoveFromGroupWithNotExistingTargetUser() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testRemoveFromGroupWithNotExistingTargetUser(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(103); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2634,13 +3249,13 @@ class UsersControllerTest extends TestCase { } - public function testRemoveFromGroupWithoutPermission() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testRemoveFromGroupWithoutPermission(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(104); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('unauthorizedUser'); $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2675,8 +3290,8 @@ class UsersControllerTest extends TestCase { } - public function testRemoveFromGroupAsAdminFromAdmin() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testRemoveFromGroupAsAdminFromAdmin(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Cannot remove yourself from the admin group'); $this->expectExceptionCode(105); @@ -2725,9 +3340,9 @@ class UsersControllerTest extends TestCase { } - public function testRemoveFromGroupAsSubAdminFromSubAdmin() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('Cannot remove yourself from this group as you are a SubAdmin'); + public function testRemoveFromGroupAsSubAdminFromSubAdmin(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('Cannot remove yourself from this group as you are a sub-admin'); $this->expectExceptionCode(105); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2780,9 +3395,9 @@ class UsersControllerTest extends TestCase { } - public function testRemoveFromGroupAsSubAdminFromLastSubAdminGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('Not viable to remove user from the last group you are SubAdmin of'); + public function testRemoveFromGroupAsSubAdminFromLastSubAdminGroup(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('Not viable to remove user from the last group you are sub-admin of'); $this->expectExceptionCode(105); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2841,7 +3456,7 @@ class UsersControllerTest extends TestCase { $this->api->removeFromGroup('AnotherUser', 'subadmin'); } - public function testRemoveFromGroupSuccessful() { + public function testRemoveFromGroupSuccessful(): void { $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser ->expects($this->any()) @@ -2883,8 +3498,8 @@ class UsersControllerTest extends TestCase { } - public function testAddSubAdminWithNotExistingTargetUser() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddSubAdminWithNotExistingTargetUser(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('User does not exist'); $this->expectExceptionCode(101); @@ -2898,8 +3513,8 @@ class UsersControllerTest extends TestCase { } - public function testAddSubAdminWithNotExistingTargetGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testAddSubAdminWithNotExistingTargetGroup(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Group does not exist'); $this->expectExceptionCode(102); @@ -2920,9 +3535,9 @@ class UsersControllerTest extends TestCase { } - public function testAddSubAdminToAdminGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('Cannot create subadmins for admin group'); + public function testAddSubAdminToAdminGroup(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('Cannot create sub-admins for admin group'); $this->expectExceptionCode(103); $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -2945,7 +3560,7 @@ class UsersControllerTest extends TestCase { $this->api->addSubAdmin('ExistingUser', 'ADmiN'); } - public function testAddSubAdminTwice() { + public function testAddSubAdminTwice(): void { $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $targetGroup = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock(); $this->userManager @@ -2973,7 +3588,7 @@ class UsersControllerTest extends TestCase { $this->assertEquals([], $this->api->addSubAdmin('ExistingUser', 'TargetGroup')->getData()); } - public function testAddSubAdminSuccessful() { + public function testAddSubAdminSuccessful(): void { $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $targetGroup = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock(); $this->userManager @@ -3006,8 +3621,8 @@ class UsersControllerTest extends TestCase { } - public function testRemoveSubAdminNotExistingTargetUser() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testRemoveSubAdminNotExistingTargetUser(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('User does not exist'); $this->expectExceptionCode(101); @@ -3021,8 +3636,8 @@ class UsersControllerTest extends TestCase { } - public function testRemoveSubAdminNotExistingTargetGroup() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testRemoveSubAdminNotExistingTargetGroup(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Group does not exist'); $this->expectExceptionCode(101); @@ -3043,9 +3658,9 @@ class UsersControllerTest extends TestCase { - public function testRemoveSubAdminFromNotASubadmin() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionMessage('User is not a subadmin of this group'); + public function testRemoveSubAdminFromNotASubadmin(): void { + $this->expectException(OCSException::class); + $this->expectExceptionMessage('User is not a sub-admin of this group'); $this->expectExceptionCode(102); $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); @@ -3075,7 +3690,7 @@ class UsersControllerTest extends TestCase { $this->api->removeSubAdmin('ExistingUser', 'GroupToDeleteFrom'); } - public function testRemoveSubAdminSuccessful() { + public function testRemoveSubAdminSuccessful(): void { $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $targetGroup = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock(); $this->userManager @@ -3108,8 +3723,8 @@ class UsersControllerTest extends TestCase { } - public function testGetUserSubAdminGroupsNotExistingTargetUser() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testGetUserSubAdminGroupsNotExistingTargetUser(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('User does not exist'); $this->expectExceptionCode(404); @@ -3122,7 +3737,7 @@ class UsersControllerTest extends TestCase { $this->api->getUserSubAdminGroups('RequestedUser'); } - public function testGetUserSubAdminGroupsWithGroups() { + public function testGetUserSubAdminGroupsWithGroups(): void { $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $targetGroup = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock(); $targetGroup @@ -3149,7 +3764,7 @@ class UsersControllerTest extends TestCase { $this->assertEquals(['TargetGroup'], $this->api->getUserSubAdminGroups('RequestedUser')->getData()); } - public function testEnableUser() { + public function testEnableUser(): void { $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $targetUser->expects($this->once()) ->method('setEnabled') @@ -3161,7 +3776,7 @@ class UsersControllerTest extends TestCase { ->willReturn($targetUser); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser - ->expects($this->exactly(2)) + ->expects($this->exactly(3)) ->method('getUID') ->willReturn('admin'); $this->userSession @@ -3176,7 +3791,7 @@ class UsersControllerTest extends TestCase { $this->assertEquals([], $this->api->enableUser('RequestedUser')->getData()); } - public function testDisableUser() { + public function testDisableUser(): void { $targetUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $targetUser->expects($this->once()) ->method('setEnabled') @@ -3188,7 +3803,7 @@ class UsersControllerTest extends TestCase { ->willReturn($targetUser); $loggedInUser = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $loggedInUser - ->expects($this->exactly(2)) + ->expects($this->exactly(3)) ->method('getUID') ->willReturn('admin'); $this->userSession @@ -3203,7 +3818,7 @@ class UsersControllerTest extends TestCase { $this->assertEquals([], $this->api->disableUser('RequestedUser')->getData()); } - public function testGetCurrentUserLoggedIn() { + public function testGetCurrentUserLoggedIn(): void { $user = $this->createMock(IUser::class); $user->expects($this->once())->method('getUID')->willReturn('UID'); @@ -3217,23 +3832,26 @@ class UsersControllerTest extends TestCase { $this->request, $this->userManager, $this->config, - $this->appManager, $this->groupManager, $this->userSession, $this->accountManager, + $this->subAdminManager, + $this->l10nFactory, + $this->rootFolder, $this->urlGenerator, $this->logger, - $this->l10nFactory, $this->newUserMailHelper, - $this->federatedShareProviderFactory, $this->secureRandom, $this->remoteWipe, + $this->knownUserService, $this->eventDispatcher, + $this->phoneNumberUtil, + $this->appManager, ]) - ->setMethods(['getUserData']) + ->onlyMethods(['getUserData']) ->getMock(); - $api->expects($this->once())->method('getUserData')->with('UID') + $api->expects($this->once())->method('getUserData')->with('UID', true) ->willReturn( [ 'id' => 'UID', @@ -3241,10 +3859,19 @@ class UsersControllerTest extends TestCase { 'quota' => ['DummyValue'], 'email' => 'demo@nextcloud.com', 'displayname' => 'Demo User', + 'display-name' => 'Demo User', 'phone' => 'phone', 'address' => 'address', 'website' => 'website', - 'twitter' => 'twitter' + 'twitter' => 'twitter', + 'bluesky' => 'bluesky', + 'fediverse' => 'fediverse', + 'organisation' => 'organisation', + 'role' => 'role', + 'headline' => 'headline', + 'biography' => 'biography', + 'profile_enabled' => '1', + 'pronouns' => 'they/them', ] ); @@ -3253,19 +3880,28 @@ class UsersControllerTest extends TestCase { 'enabled' => 'true', 'quota' => ['DummyValue'], 'email' => 'demo@nextcloud.com', + 'displayname' => 'Demo User', + 'display-name' => 'Demo User', 'phone' => 'phone', 'address' => 'address', 'website' => 'website', 'twitter' => 'twitter', - 'display-name' => 'Demo User' + 'bluesky' => 'bluesky', + 'fediverse' => 'fediverse', + 'organisation' => 'organisation', + 'role' => 'role', + 'headline' => 'headline', + 'biography' => 'biography', + 'profile_enabled' => '1', + 'pronouns' => 'they/them', ]; $this->assertSame($expected, $api->getCurrentUser()->getData()); } - public function testGetCurrentUserNotLoggedIn() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testGetCurrentUserNotLoggedIn(): void { + $this->expectException(OCSException::class); $this->userSession->expects($this->once())->method('getUser') @@ -3274,8 +3910,15 @@ class UsersControllerTest extends TestCase { $this->api->getCurrentUser(); } + public function testGetUser(): void { + $loggedInUser = $this->createMock(IUser::class); + $loggedInUser + ->method('getUID') + ->willReturn('currentuser'); + $this->userSession + ->method('getUser') + ->willReturn($loggedInUser); - public function testGetUser() { /** @var UsersController | MockObject $api */ $api = $this->getMockBuilder(UsersController::class) ->setConstructorArgs([ @@ -3283,20 +3926,23 @@ class UsersControllerTest extends TestCase { $this->request, $this->userManager, $this->config, - $this->appManager, $this->groupManager, $this->userSession, $this->accountManager, + $this->subAdminManager, + $this->l10nFactory, + $this->rootFolder, $this->urlGenerator, $this->logger, - $this->l10nFactory, $this->newUserMailHelper, - $this->federatedShareProviderFactory, $this->secureRandom, $this->remoteWipe, + $this->knownUserService, $this->eventDispatcher, + $this->phoneNumberUtil, + $this->appManager, ]) - ->setMethods(['getUserData']) + ->onlyMethods(['getUserData']) ->getMock(); $expected = [ @@ -3308,19 +3954,33 @@ class UsersControllerTest extends TestCase { 'address' => 'address', 'website' => 'website', 'twitter' => 'twitter', - 'displayname' => 'Demo User' + 'bluesky' => 'bluesky', + 'fediverse' => 'fediverse', + 'displayname' => 'Demo User', + 'display-name' => 'Demo User', + 'organisation' => 'organisation', + 'role' => 'role', + 'headline' => 'headline', + 'biography' => 'biography', + 'profile_enabled' => '1', + 'pronouns' => 'they/them', ]; - $api->expects($this->once())->method('getUserData') - ->with('uid') - ->willReturn($expected); + $api->expects($this->exactly(2)) + ->method('getUserData') + ->willReturnMap([ + ['uid', false, $expected], + ['currentuser', true, $expected], + ]); $this->assertSame($expected, $api->getUser('uid')->getData()); + + $this->assertSame($expected, $api->getUser('currentuser')->getData()); } - public function testResendWelcomeMessageWithNotExistingTargetUser() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testResendWelcomeMessageWithNotExistingTargetUser(): void { + $this->expectException(OCSException::class); $this->expectExceptionCode(998); $this->userManager @@ -3333,15 +3993,15 @@ class UsersControllerTest extends TestCase { } - public function testResendWelcomeMessageAsSubAdminAndUserIsNotAccessible() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); - $this->expectExceptionCode(997); + public function testResendWelcomeMessageAsSubAdminAndUserIsNotAccessible(): void { + $this->expectException(OCSException::class); + $this->expectExceptionCode(998); $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $loggedInUser - ->expects($this->exactly(1)) + ->expects($this->exactly(2)) ->method('getUID') ->willReturn('subadmin'); $targetUser = $this->getMockBuilder(IUser::class) @@ -3378,8 +4038,8 @@ class UsersControllerTest extends TestCase { } - public function testResendWelcomeMessageNoEmail() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testResendWelcomeMessageNoEmail(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Email address not available'); $this->expectExceptionCode(101); @@ -3410,6 +4070,10 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('getSubAdmin') ->willReturn($subAdminManager); + $loggedInUser + ->expects($this->exactly(2)) + ->method('getUID') + ->willReturn('logged-user-id'); $targetUser ->expects($this->once()) ->method('getEmailAddress') @@ -3419,8 +4083,8 @@ class UsersControllerTest extends TestCase { } - public function testResendWelcomeMessageNullEmail() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testResendWelcomeMessageNullEmail(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Email address not available'); $this->expectExceptionCode(101); @@ -3451,6 +4115,10 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('getSubAdmin') ->willReturn($subAdminManager); + $loggedInUser + ->expects($this->exactly(2)) + ->method('getUID') + ->willReturn('logged-user-id'); $targetUser ->expects($this->once()) ->method('getEmailAddress') @@ -3459,13 +4127,16 @@ class UsersControllerTest extends TestCase { $this->api->resendWelcomeMessage('UserToGet'); } - public function testResendWelcomeMessageSuccess() { + public function testResendWelcomeMessageSuccess(): void { $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $targetUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); + $loggedInUser + ->method('getUID') + ->willReturn('logged-user-id'); $targetUser ->method('getUID') ->willReturn('user-id'); @@ -3496,24 +4167,27 @@ class UsersControllerTest extends TestCase { ->willReturn('abc@example.org'); $emailTemplate = $this->createMock(IEMailTemplate::class); $this->newUserMailHelper - ->expects($this->at(0)) + ->expects($this->once()) ->method('generateTemplate') ->willReturn($emailTemplate); $this->newUserMailHelper - ->expects($this->at(1)) + ->expects($this->once()) ->method('sendMail') ->with($targetUser, $emailTemplate); $this->api->resendWelcomeMessage('UserToGet'); } - public function testResendWelcomeMessageSuccessWithFallbackLanguage() { + public function testResendWelcomeMessageSuccessWithFallbackLanguage(): void { $loggedInUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); $targetUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); + $loggedInUser + ->method('getUID') + ->willReturn('logged-user-id'); $targetUser ->method('getUID') ->willReturn('user-id'); @@ -3542,16 +4216,13 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('getEmailAddress') ->willReturn('abc@example.org'); - $l10n = $this->getMockBuilder(IL10N::class) - ->disableOriginalConstructor() - ->getMock(); $emailTemplate = $this->createMock(IEMailTemplate::class); $this->newUserMailHelper - ->expects($this->at(0)) + ->expects($this->once()) ->method('generateTemplate') ->willReturn($emailTemplate); $this->newUserMailHelper - ->expects($this->at(1)) + ->expects($this->once()) ->method('sendMail') ->with($targetUser, $emailTemplate); @@ -3559,8 +4230,8 @@ class UsersControllerTest extends TestCase { } - public function testResendWelcomeMessageFailed() { - $this->expectException(\OCP\AppFramework\OCS\OCSException::class); + public function testResendWelcomeMessageFailed(): void { + $this->expectException(OCSException::class); $this->expectExceptionMessage('Sending email failed'); $this->expectExceptionCode(102); @@ -3570,6 +4241,10 @@ class UsersControllerTest extends TestCase { $targetUser = $this->getMockBuilder(IUser::class) ->disableOriginalConstructor() ->getMock(); + $loggedInUser + ->expects($this->exactly(2)) + ->method('getUID') + ->willReturn('logged-user-id'); $targetUser ->method('getUID') ->willReturn('user-id'); @@ -3600,11 +4275,11 @@ class UsersControllerTest extends TestCase { ->willReturn('abc@example.org'); $emailTemplate = $this->createMock(IEMailTemplate::class); $this->newUserMailHelper - ->expects($this->at(0)) + ->expects($this->once()) ->method('generateTemplate') ->willReturn($emailTemplate); $this->newUserMailHelper - ->expects($this->at(1)) + ->expects($this->once()) ->method('sendMail') ->with($targetUser, $emailTemplate) ->willThrowException(new \Exception()); @@ -3613,57 +4288,176 @@ class UsersControllerTest extends TestCase { } - public function dataGetEditableFields() { + public static function dataGetEditableFields(): array { return [ - [false, false, []], - [false, true, [ + [false, true, ISetDisplayNameBackend::class, [ + IAccountManager::PROPERTY_EMAIL, + IAccountManager::COLLECTION_EMAIL, IAccountManager::PROPERTY_PHONE, IAccountManager::PROPERTY_ADDRESS, IAccountManager::PROPERTY_WEBSITE, IAccountManager::PROPERTY_TWITTER, + IAccountManager::PROPERTY_BLUESKY, + IAccountManager::PROPERTY_FEDIVERSE, + IAccountManager::PROPERTY_ORGANISATION, + IAccountManager::PROPERTY_ROLE, + IAccountManager::PROPERTY_HEADLINE, + IAccountManager::PROPERTY_BIOGRAPHY, + IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, ]], - [ true, false, [ + [true, false, ISetDisplayNameBackend::class, [ IAccountManager::PROPERTY_DISPLAYNAME, - IAccountManager::PROPERTY_EMAIL, + IAccountManager::COLLECTION_EMAIL, + IAccountManager::PROPERTY_PHONE, + IAccountManager::PROPERTY_ADDRESS, + IAccountManager::PROPERTY_WEBSITE, + IAccountManager::PROPERTY_TWITTER, + IAccountManager::PROPERTY_BLUESKY, + IAccountManager::PROPERTY_FEDIVERSE, + IAccountManager::PROPERTY_ORGANISATION, + IAccountManager::PROPERTY_ROLE, + IAccountManager::PROPERTY_HEADLINE, + IAccountManager::PROPERTY_BIOGRAPHY, + IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, ]], - [ true, true ,[ + [true, true, ISetDisplayNameBackend::class, [ IAccountManager::PROPERTY_DISPLAYNAME, IAccountManager::PROPERTY_EMAIL, + IAccountManager::COLLECTION_EMAIL, IAccountManager::PROPERTY_PHONE, IAccountManager::PROPERTY_ADDRESS, IAccountManager::PROPERTY_WEBSITE, IAccountManager::PROPERTY_TWITTER, - ]] + IAccountManager::PROPERTY_BLUESKY, + IAccountManager::PROPERTY_FEDIVERSE, + IAccountManager::PROPERTY_ORGANISATION, + IAccountManager::PROPERTY_ROLE, + IAccountManager::PROPERTY_HEADLINE, + IAccountManager::PROPERTY_BIOGRAPHY, + IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, + ]], + [false, false, ISetDisplayNameBackend::class, [ + IAccountManager::COLLECTION_EMAIL, + IAccountManager::PROPERTY_PHONE, + IAccountManager::PROPERTY_ADDRESS, + IAccountManager::PROPERTY_WEBSITE, + IAccountManager::PROPERTY_TWITTER, + IAccountManager::PROPERTY_BLUESKY, + IAccountManager::PROPERTY_FEDIVERSE, + IAccountManager::PROPERTY_ORGANISATION, + IAccountManager::PROPERTY_ROLE, + IAccountManager::PROPERTY_HEADLINE, + IAccountManager::PROPERTY_BIOGRAPHY, + IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, + ]], + [false, true, UserInterface::class, [ + IAccountManager::PROPERTY_EMAIL, + IAccountManager::COLLECTION_EMAIL, + IAccountManager::PROPERTY_PHONE, + IAccountManager::PROPERTY_ADDRESS, + IAccountManager::PROPERTY_WEBSITE, + IAccountManager::PROPERTY_TWITTER, + IAccountManager::PROPERTY_BLUESKY, + IAccountManager::PROPERTY_FEDIVERSE, + IAccountManager::PROPERTY_ORGANISATION, + IAccountManager::PROPERTY_ROLE, + IAccountManager::PROPERTY_HEADLINE, + IAccountManager::PROPERTY_BIOGRAPHY, + IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, + ]], + [true, false, UserInterface::class, [ + IAccountManager::COLLECTION_EMAIL, + IAccountManager::PROPERTY_PHONE, + IAccountManager::PROPERTY_ADDRESS, + IAccountManager::PROPERTY_WEBSITE, + IAccountManager::PROPERTY_TWITTER, + IAccountManager::PROPERTY_BLUESKY, + IAccountManager::PROPERTY_FEDIVERSE, + IAccountManager::PROPERTY_ORGANISATION, + IAccountManager::PROPERTY_ROLE, + IAccountManager::PROPERTY_HEADLINE, + IAccountManager::PROPERTY_BIOGRAPHY, + IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, + ]], + [true, true, UserInterface::class, [ + IAccountManager::PROPERTY_EMAIL, + IAccountManager::COLLECTION_EMAIL, + IAccountManager::PROPERTY_PHONE, + IAccountManager::PROPERTY_ADDRESS, + IAccountManager::PROPERTY_WEBSITE, + IAccountManager::PROPERTY_TWITTER, + IAccountManager::PROPERTY_BLUESKY, + IAccountManager::PROPERTY_FEDIVERSE, + IAccountManager::PROPERTY_ORGANISATION, + IAccountManager::PROPERTY_ROLE, + IAccountManager::PROPERTY_HEADLINE, + IAccountManager::PROPERTY_BIOGRAPHY, + IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, + ]], + [false, false, UserInterface::class, [ + IAccountManager::COLLECTION_EMAIL, + IAccountManager::PROPERTY_PHONE, + IAccountManager::PROPERTY_ADDRESS, + IAccountManager::PROPERTY_WEBSITE, + IAccountManager::PROPERTY_TWITTER, + IAccountManager::PROPERTY_BLUESKY, + IAccountManager::PROPERTY_FEDIVERSE, + IAccountManager::PROPERTY_ORGANISATION, + IAccountManager::PROPERTY_ROLE, + IAccountManager::PROPERTY_HEADLINE, + IAccountManager::PROPERTY_BIOGRAPHY, + IAccountManager::PROPERTY_PROFILE_ENABLED, + IAccountManager::PROPERTY_PRONOUNS, + ]], ]; } - /** - * @dataProvider dataGetEditableFields - * - * @param bool $allowedToChangeDisplayName - * @param bool $federatedSharingEnabled - * @param array $expected - */ - public function testGetEditableFields(bool $allowedToChangeDisplayName, bool $federatedSharingEnabled, array $expected) { - $this->config - ->method('getSystemValue') - ->with( - $this->equalTo('allow_user_to_change_display_name'), - $this->anything() - )->willReturn($allowedToChangeDisplayName); - $this->appManager - ->method('isEnabledForUser') - ->with($this->equalTo('federatedfilesharing')) - ->willReturn($federatedSharingEnabled); + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetEditableFields')] + public function testGetEditableFields(bool $allowedToChangeDisplayName, bool $allowedToChangeEmail, string $userBackend, array $expected): void { + $this->config->method('getSystemValue')->willReturnCallback(fn (string $key, mixed $default) => match ($key) { + 'allow_user_to_change_display_name' => $allowedToChangeDisplayName, + 'allow_user_to_change_email' => $allowedToChangeEmail, + default => throw new RuntimeException('Unexpected system config key: ' . $key), + }); + + $user = $this->createMock(IUser::class); + $this->userSession->method('getUser') + ->willReturn($user); - $shareprovider = $this->createMock(FederatedShareProvider::class); - $shareprovider->method('isLookupServerUploadEnabled')->willReturn(true); + $backend = $this->createMock($userBackend); - $this->federatedShareProviderFactory - ->method('get') - ->willReturn($shareprovider); + $user->method('getUID') + ->willReturn('userId'); + $user->method('getBackend') + ->willReturn($backend); $expectedResp = new DataResponse($expected); - $this->assertEquals($expectedResp, $this->api->getEditableFields()); + $this->assertEquals($expectedResp, $this->api->getEditableFields('userId')); + } + + private function mockAccount($targetUser, $accountProperties) { + $mockedProperties = []; + + foreach ($accountProperties as $propertyName => $data) { + $mockedProperty = $this->createMock(IAccountProperty::class); + $mockedProperty->method('getValue')->willReturn($data['value'] ?? ''); + $mockedProperty->method('getScope')->willReturn($data['scope'] ?? ''); + $mockedProperties[] = [$propertyName, $mockedProperty]; + } + + $account = $this->createMock(IAccount::class); + $account->method('getProperty') + ->willReturnMap($mockedProperties); + + $this->accountManager->expects($this->any())->method('getAccount') + ->with($targetUser) + ->willReturn($account); } } diff --git a/apps/provisioning_api/tests/Middleware/ProvisioningApiMiddlewareTest.php b/apps/provisioning_api/tests/Middleware/ProvisioningApiMiddlewareTest.php index 1b4bb6e81a2..c027e518a3d 100644 --- a/apps/provisioning_api/tests/Middleware/ProvisioningApiMiddlewareTest.php +++ b/apps/provisioning_api/tests/Middleware/ProvisioningApiMiddlewareTest.php @@ -1,32 +1,15 @@ <?php + /** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Provisioning_API\Tests\Middleware; use OCA\Provisioning_API\Middleware\Exceptions\NotSubAdminException; use OCA\Provisioning_API\Middleware\ProvisioningApiMiddleware; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\Utility\IControllerMethodReflector; use Test\TestCase; @@ -42,27 +25,27 @@ class ProvisioningApiMiddlewareTest extends TestCase { $this->reflector = $this->createMock(IControllerMethodReflector::class); } - public function dataAnnotation() { + public static function dataAnnotation(): array { return [ - [false, false, false, false], - [false, false, true, false], - [false, true, true, false], - [ true, false, false, true], - [ true, false, true, false], - [ true, true, false, false], - [ true, true, true, false], + [false, false, false, false, false], + [false, false, true, false, false], + [false, true, true, false, false], + [true, false, false, false, true], + [true, false, true, false, false], + [true, true, false, false, false], + [true, true, true, false, false], + [false, false, false, true, false], + [false, false, true, true, false], + [false, true, true, true, false], + [true, false, false, true, false], + [true, false, true, true, false], + [true, true, false, true, false], + [true, true, true, true, false], ]; } - /** - * @dataProvider dataAnnotation - * - * @param bool $subadminRequired - * @param bool $isAdmin - * @param bool $isSubAdmin - * @param bool $shouldThrowException - */ - public function testBeforeController($subadminRequired, $isAdmin, $isSubAdmin, $shouldThrowException) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataAnnotation')] + public function testBeforeController(bool $subadminRequired, bool $isAdmin, bool $isSubAdmin, bool $hasSettingAuthorizationAnnotation, bool $shouldThrowException): void { $middleware = new ProvisioningApiMiddleware( $this->reflector, $isAdmin, @@ -70,8 +53,15 @@ class ProvisioningApiMiddlewareTest extends TestCase { ); $this->reflector->method('hasAnnotation') - ->with('NoSubAdminRequired') - ->willReturn(!$subadminRequired); + ->willReturnCallback(function ($annotation) use ($subadminRequired, $hasSettingAuthorizationAnnotation) { + if ($annotation === 'NoSubAdminRequired') { + return !$subadminRequired; + } + if ($annotation === 'AuthorizedAdminSetting') { + return $hasSettingAuthorizationAnnotation; + } + return false; + }); try { $middleware->beforeController( @@ -84,20 +74,15 @@ class ProvisioningApiMiddlewareTest extends TestCase { } } - public function dataAfterException() { + public static function dataAfterException(): array { return [ [new NotSubAdminException(), false], [new \Exception('test', 42), true], ]; } - /** - * @dataProvider dataAfterException - * - * @param \Exception $e - * @param bool $forwared - */ - public function testAfterException(\Exception $exception, $forwared) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataAfterException')] + public function testAfterException(\Exception $exception, bool $forwared): void { $middleware = new ProvisioningApiMiddleware( $this->reflector, false, @@ -114,7 +99,7 @@ class ProvisioningApiMiddlewareTest extends TestCase { } catch (OCSException $e) { $this->assertFalse($forwared); $this->assertSame($exception->getMessage(), $e->getMessage()); - $this->assertSame(\OCP\API::RESPOND_UNAUTHORISED, $e->getCode()); + $this->assertSame(Http::STATUS_FORBIDDEN, $e->getCode()); } catch (\Exception $e) { $this->assertTrue($forwared); $this->assertSame($exception, $e); diff --git a/apps/provisioning_api/tests/TestCase.php b/apps/provisioning_api/tests/TestCase.php index 7ddebfcf322..30e7f3a4ecf 100644 --- a/apps/provisioning_api/tests/TestCase.php +++ b/apps/provisioning_api/tests/TestCase.php @@ -1,34 +1,16 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @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/> - * + * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Provisioning_API\Tests; use OCP\IGroupManager; use OCP\IUser; use OCP\IUserManager; +use OCP\Server; abstract class TestCase extends \Test\TestCase { @@ -44,8 +26,8 @@ abstract class TestCase extends \Test\TestCase { protected function setUp(): void { parent::setUp(); - $this->userManager = \OC::$server->getUserManager(); - $this->groupManager = \OC::$server->getGroupManager(); + $this->userManager = Server::get(IUserManager::class); + $this->groupManager = Server::get(IGroupManager::class); $this->groupManager->createGroup('admin'); } |