diff --git a/composer.lock b/composer.lock index 86af6a6b..74a5d2bf 100644 --- a/composer.lock +++ b/composer.lock @@ -912,12 +912,12 @@ "source": { "type": "git", "url": "https://github.com/nextcloud-deps/ocp.git", - "reference": "6e597101481226c5d2518d98596301f2efc692d1" + "reference": "76e366bf801150029d17a516fa496b5b89a772ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/6e597101481226c5d2518d98596301f2efc692d1", - "reference": "6e597101481226c5d2518d98596301f2efc692d1", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/76e366bf801150029d17a516fa496b5b89a772ac", + "reference": "76e366bf801150029d17a516fa496b5b89a772ac", "shasum": "" }, "require": { @@ -953,7 +953,7 @@ "issues": "https://github.com/nextcloud-deps/ocp/issues", "source": "https://github.com/nextcloud-deps/ocp/tree/master" }, - "time": "2025-02-14T00:43:30+00:00" + "time": "2025-08-01T01:04:13+00:00" }, { "name": "nikic/php-parser", diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 2310631e..f357328c 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -9,6 +9,7 @@ use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\Guests\Capabilities; +use OCA\Guests\ConfigLexicon; use OCA\Guests\GroupBackend; use OCA\Guests\Hooks; use OCA\Guests\Listener\BeforeUserManagementRenderedListener; @@ -47,6 +48,7 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(ShareCreatedEvent::class, ShareAutoAcceptListener::class); $context->registerEventListener(BeforeTemplateRenderedEvent::class, TalkIntegrationListener::class); $context->registerEventListener(BeforeUserManagementRenderedEvent::class, BeforeUserManagementRenderedListener::class); + $context->registerConfigLexicon(ConfigLexicon::class); } public function boot(IBootContext $context): void { diff --git a/lib/Config.php b/lib/Config.php index 8b82427c..e8db2b94 100644 --- a/lib/Config.php +++ b/lib/Config.php @@ -10,6 +10,7 @@ use OCP\AppFramework\Services\IAppConfig; use OCP\Group\ISubAdmin; +use OCP\IAppConfig as IGlobalAppConfig; use OCP\IConfig; use OCP\IGroupManager; use OCP\IUserSession; @@ -17,6 +18,7 @@ class Config { public function __construct( private IConfig $config, + private IGlobalAppConfig $globalAppConfig, private IAppConfig $appConfig, private ISubAdmin $subAdmin, private IUserSession $userSession, @@ -25,25 +27,19 @@ public function __construct( } public function allowExternalStorage(): bool { - return $this->appConfig->getAppValueBool('allow_external_storage', false); + return $this->appConfig->getAppValueBool(ConfigLexicon::EXTERNAL_STORAGE_ENABLED); } - /** - * @param string|bool $allow - */ - public function setAllowExternalStorage($allow) { - $this->appConfig->setAppValueBool('allow_external_storage', $allow === true || $allow === 'true') ; + public function setAllowExternalStorage(bool $allow): void { + $this->appConfig->setAppValueBool(ConfigLexicon::EXTERNAL_STORAGE_ENABLED, $allow); } public function hideOtherUsers(): bool { - return $this->appConfig->getAppValueBool('hide_users', true); + return $this->appConfig->getAppValueBool(ConfigLexicon::HIDE_OTHER_ACCOUNTS); } - /** - * @param string|bool $hide - */ - public function setHideOtherUsers($hide): void { - $this->appConfig->setAppValueBool('hide_users', $hide === true || $hide === 'true') ; + public function setHideOtherUsers(bool $hide): void { + $this->appConfig->setAppValueBool(ConfigLexicon::HIDE_OTHER_ACCOUNTS, $hide); } public function getHome(string $uid): string { @@ -51,36 +47,26 @@ public function getHome(string $uid): string { } public function useWhitelist(): bool { - return $this->appConfig->getAppValueBool('usewhitelist', true); + return $this->appConfig->getAppValueBool(ConfigLexicon::WHITE_LIST_ENABLED); } - /** - * @param string|bool $use - */ - public function setUseWhitelist($use) { - $this->appConfig->setAppValueBool('usewhitelist', $use === true || $use === 'true') ; + public function setUseWhitelist(bool $use): void { + $this->appConfig->setAppValueBool(ConfigLexicon::WHITE_LIST_ENABLED, $use); } /** * @return string[] */ public function getAppWhitelist(): array { - $whitelist = $this->appConfig->getAppValueString('whitelist', AppWhitelist::DEFAULT_WHITELIST); - return explode(',', $whitelist); + return explode(',', $this->appConfig->getAppValueString(ConfigLexicon::WHITE_LIST)); } - /** - * @param array|string $whitelist - */ - public function setAppWhitelist($whitelist): void { - if (is_array($whitelist)) { - $whitelist = implode(',', $whitelist); - } - $this->appConfig->setAppValueString('whitelist', $whitelist); + public function setAppWhitelist(array $whitelist): void { + $this->appConfig->setAppValueString(ConfigLexicon::WHITE_LIST, implode(',', $whitelist)); } public function isSharingRestrictedToGroup(): bool { - return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; + return $this->globalAppConfig->getValueBool('core', 'shareapi_only_share_with_group_members'); } public function canCreateGuests(): bool { @@ -114,7 +100,7 @@ public function canCreateGuests(): bool { * @return string[] */ public function getCreateRestrictedToGroup(): array { - $groups = $this->appConfig->getAppValueArray('create_restricted_to_group', []); + $groups = $this->appConfig->getAppValueArray(ConfigLexicon::GROUP_LIMITATION); // If empty, it means there is no restriction if (empty($groups)) { return []; @@ -123,7 +109,7 @@ public function getCreateRestrictedToGroup(): array { // It does not matter at this point if the admin // group is in the list or not. We are checking it // anyway in the canCreateGuests method. - return array_values(array_unique($this->appConfig->getAppValueArray('create_restricted_to_group', []))); + return array_values(array_unique($this->appConfig->getAppValueArray(ConfigLexicon::GROUP_LIMITATION))); } /** diff --git a/lib/ConfigLexicon.php b/lib/ConfigLexicon.php new file mode 100644 index 00000000..64d964e6 --- /dev/null +++ b/lib/ConfigLexicon.php @@ -0,0 +1,57 @@ + match ($p) { + Preset::PRIVATE, Preset::FAMILY => '1 GB', + Preset::SMALL, Preset::MEDIUM, Preset::LARGE => '10 GB', + default => '0 B', + }, definition: 'set default disk quota assigned to guest account at its creation'), + new Entry(self::GROUP_LIMITATION, ValueType::ARRAY, []), + ]; + } + + public function getUserConfigs(): array { + return [ + new Entry(self::USER_CREATED_BY, ValueType::STRING, null, 'user that generated this guest account'), + ]; + } +} diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 2a6613c6..d62d3c55 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -11,8 +11,10 @@ use OCA\Guests\AppInfo\Application; use OCA\Guests\AppWhitelist; use OCA\Guests\Config; +use OCA\Guests\ConfigLexicon; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Services\IAppConfig; use OCP\IRequest; /** @@ -22,11 +24,11 @@ * @package OCA\Guests\Controller */ class SettingsController extends Controller { - public function __construct( IRequest $request, - private Config $config, - private AppWhitelist $appWhitelist, + private readonly Config $config, + private readonly IAppConfig $appConfig, + private readonly AppWhitelist $appWhitelist, ) { parent::__construct(Application::APP_ID, $request); } @@ -94,9 +96,9 @@ public function getWhitelist(): DataResponse { * @return DataResponse with the reset whitelist */ public function resetWhitelist(): DataResponse { - $this->config->setAppWhitelist(AppWhitelist::DEFAULT_WHITELIST); + $this->appConfig->deleteAppValue(ConfigLexicon::WHITE_LIST); return new DataResponse([ - 'whitelist' => explode(',', AppWhitelist::DEFAULT_WHITELIST), + 'whitelist' => $this->config->getAppWhitelist(), ]); } } diff --git a/lib/GuestManager.php b/lib/GuestManager.php index 5db7917a..aa8aabf6 100644 --- a/lib/GuestManager.php +++ b/lib/GuestManager.php @@ -7,6 +7,10 @@ namespace OCA\Guests; +use OCA\Guests\AppInfo\Application; +use OCP\AppFramework\Services\IAppConfig; +use OCP\Config\IUserConfig; +use OCP\Config\ValueType; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; @@ -23,6 +27,8 @@ class GuestManager { public function __construct( private IConfig $config, + private readonly IAppConfig $appConfig, + private readonly IUserConfig $userConfig, private UserBackend $userBackend, private ISecureRandom $secureRandom, private ICrypto $crypto, @@ -69,7 +75,7 @@ public function createGuest(?IUser $createdBy, string $userId, string $email, st $user->setSystemEMailAddress($email); if ($createdBy) { - $this->config->setUserValue($userId, 'guests', 'created_by', $createdBy->getUID()); + $this->userConfig->setValueString($userId, Application::APP_ID, ConfigLexicon::USER_CREATED_BY, $createdBy->getUID()); } if ($displayName) { @@ -101,7 +107,7 @@ public function createGuest(?IUser $createdBy, string $userId, string $email, st ); } - $user->setQuota('0 B'); + $user->setQuota($this->appConfig->getAppValueString(ConfigLexicon::GUEST_DISK_QUOTA)); return $user; } @@ -114,7 +120,8 @@ public function getGuestsInfo(): array { $displayNames = $this->userBackend->getDisplayNames(); $guests = array_keys($displayNames); $shareCounts = $this->getShareCountForUsers($guests); - $createdBy = $this->config->getUserValueForUsers('guests', 'created_by', $guests); + $createdBy = $this->userConfig->getValuesByUsers(Application::APP_ID, ConfigLexicon::USER_CREATED_BY, ValueType::STRING, $guests); + return array_map(function ($uid) use ($createdBy, $displayNames, $shareCounts) { $allSharesCount = count(array_merge( $this->shareManager->getSharedWith($uid, IShare::TYPE_USER, null, -1, 0), @@ -127,7 +134,7 @@ public function getGuestsInfo(): array { 'email' => $uid, 'display_name' => $displayNames[$uid] ?? $uid, 'created_by' => $createdBy[$uid] ?? '', - 'share_count' => isset($shareCounts[$uid]) ? $shareCounts[$uid] : 0, + 'share_count' => $shareCounts[$uid] ?? 0, 'share_count_with_circles' => $allSharesCount, ]; }, $guests); diff --git a/tests/unit/ConfigTest.php b/tests/unit/ConfigTest.php index d0c0116c..819e1248 100644 --- a/tests/unit/ConfigTest.php +++ b/tests/unit/ConfigTest.php @@ -9,10 +9,10 @@ namespace OCA\Guests\Test\Unit; -use OCA\Guests\AppWhitelist; use OCA\Guests\Config; use OCP\AppFramework\Services\IAppConfig; use OCP\Group\ISubAdmin; +use OCP\IAppConfig as IGlobalAppConfig; use OCP\IConfig; use OCP\IGroupManager; use OCP\IUser; @@ -23,6 +23,8 @@ class ConfigTest extends TestCase { /** @var IConfig|MockObject */ private $config; + /** @var IGlobalAppConfig|MockObject */ + private $globalAppConfig; /** @var IAppConfig|MockObject */ private $appConfig; /** @var ISubAdmin|MockObject */ @@ -39,6 +41,7 @@ protected function setUp(): void { parent::setUp(); $this->config = $this->createMock(IConfig::class); + $this->globalAppConfig = $this->createMock(IGlobalAppConfig::class); $this->appConfig = $this->createMock(IAppConfig::class); $this->subAdmin = $this->createMock(ISubAdmin::class); $this->userSession = $this->createMock(IUserSession::class); @@ -46,6 +49,7 @@ protected function setUp(): void { $this->guestConfig = new Config( $this->config, + $this->globalAppConfig, $this->appConfig, $this->subAdmin, $this->userSession, @@ -62,29 +66,27 @@ public function testAllowExternalStorage() { } public function testSetAllowExternalStorage() { - $this->appConfig->expects($this->exactly(2)) + $this->appConfig->expects($this->once()) ->method('setAppValueBool') ->with('allow_external_storage', true); $this->guestConfig->setAllowExternalStorage(true); - $this->guestConfig->setAllowExternalStorage('true'); } public function testHideOtherUsers() { $this->appConfig->method('getAppValueBool') - ->with('hide_users', true) + ->with('hide_users') ->willReturn(false); $this->assertFalse($this->guestConfig->hideOtherUsers()); } public function testSetHideOtherUsers() { - $this->appConfig->expects($this->exactly(2)) + $this->appConfig->expects($this->once()) ->method('setAppValueBool') ->with('hide_users', true); $this->guestConfig->setHideOtherUsers(true); - $this->guestConfig->setHideOtherUsers('true'); } public function testGetHome() { @@ -97,42 +99,40 @@ public function testGetHome() { public function testUseWhitelist() { $this->appConfig->method('getAppValueBool') - ->with('usewhitelist', true) + ->with('usewhitelist') ->willReturn(false); $this->assertFalse($this->guestConfig->useWhitelist()); } public function testSetUseWhitelist() { - $this->appConfig->expects($this->exactly(2)) + $this->appConfig->expects($this->once()) ->method('setAppValueBool') ->with('usewhitelist', true); $this->guestConfig->setUseWhitelist(true); - $this->guestConfig->setUseWhitelist('true'); } public function testGetAppWhitelist() { $this->appConfig->method('getAppValueString') - ->with('whitelist', AppWhitelist::DEFAULT_WHITELIST) + ->with('whitelist') ->willReturn('app1,app2,app3'); $this->assertEquals(['app1', 'app2', 'app3'], $this->guestConfig->getAppWhitelist()); } public function testSetAppWhitelistArray() { - $this->appConfig->expects($this->exactly(2)) + $this->appConfig->expects($this->once()) ->method('setAppValueString') ->with('whitelist', 'app1,app2,app3'); $this->guestConfig->setAppWhitelist(['app1', 'app2', 'app3']); - $this->guestConfig->setAppWhitelist('app1,app2,app3'); } public function testIsSharingRestrictedToGroup() { - $this->config->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn('yes'); + $this->globalAppConfig->method('getValueBool') + ->with('core', 'shareapi_only_share_with_group_members') + ->willReturn(true); $this->assertTrue($this->guestConfig->isSharingRestrictedToGroup()); } @@ -197,9 +197,9 @@ public function testCanCreateGuestsWithSharingRestrictedButIsSubAdmin() { ->with('create_restricted_to_group', []) ->willReturn([]); - $this->config->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn('yes'); + $this->globalAppConfig->method('getValueBool') + ->with('core', 'shareapi_only_share_with_group_members') + ->willReturn(true); $this->subAdmin->method('isSubAdmin') ->with($user) @@ -217,9 +217,9 @@ public function testCanCreateGuestsWithSharingRestrictedNotSubAdmin() { ->with('create_restricted_to_group', []) ->willReturn([]); - $this->config->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn('yes'); + $this->globalAppConfig->method('getValueBool') + ->with('core', 'shareapi_only_share_with_group_members') + ->willReturn(true); $this->subAdmin->method('isSubAdmin') ->with($user) diff --git a/tests/unit/Controller/UsersControllerTest.php b/tests/unit/Controller/UsersControllerTest.php index 84d9110c..e910518b 100644 --- a/tests/unit/Controller/UsersControllerTest.php +++ b/tests/unit/Controller/UsersControllerTest.php @@ -17,6 +17,7 @@ use OCP\AppFramework\Http; use OCP\AppFramework\Services\IAppConfig; use OCP\Group\ISubAdmin; +use OCP\IAppConfig as IGlobalAppConfig; use OCP\IConfig; use OCP\IGroup; use OCP\IGroupManager; @@ -52,6 +53,8 @@ class UsersControllerTest extends TestCase { private $transferService; /** @var TransferMapper|MockObject */ private $transferMapper; + /** @var IGlobalAppConfig|MockObject */ + private $globalAppConfig; /** @var IAppConfig|MockObject */ private $appConfig; /** @var IConfig|MockObject */ @@ -73,11 +76,13 @@ protected function setUp(): void { $this->groupManager = $this->createMock(IGroupManager::class); $this->transferService = $this->createMock(TransferService::class); $this->transferMapper = $this->createMock(TransferMapper::class); + $this->globalAppConfig = $this->createMock(IGlobalAppConfig::class); $this->appConfig = $this->createMock(IAppConfig::class); $this->config = $this->createMock(IConfig::class); $this->guestsConfig = new Config( $this->config, + $this->globalAppConfig, $this->appConfig, $this->subAdmin, $this->userSession, @@ -300,9 +305,9 @@ public function testCreateSucceedsForSubAdminWhenSharingIsRestricted() { ->willReturn([]); // Sharing is restricted to group - $this->config->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn('yes'); + $this->globalAppConfig->method('getValueBool') + ->with('core', 'shareapi_only_share_with_group_members') + ->willReturn(true); // User is a subadmin $this->subAdmin->method('isSubAdmin') @@ -358,10 +363,10 @@ public function testCreateFailsForNonSubAdminWhenSharingIsRestricted() { ->willReturn([]); // Sharing is restricted to group - $this->config->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn('yes'); - + $this->globalAppConfig->method('getValueBool') + ->with('core', 'shareapi_only_share_with_group_members') + ->willReturn(true); + // User is NOT a subadmin $this->subAdmin->method('isSubAdmin') ->with($currentUser) @@ -439,9 +444,9 @@ public function testCreateWhenSharingRestrictedToGroupButNoGroups() { ->willReturn([]); // Sharing is restricted to group - $this->config->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn('yes'); + $this->globalAppConfig->method('getValueBool') + ->with('core', 'shareapi_only_share_with_group_members') + ->willReturn(true); // User is an admin // so they are allowed to create guests @@ -478,9 +483,9 @@ public function testCreateWithNonExistentGroup() { ->willReturn(true); // Sharing is restricted to group - $this->config->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn('yes'); + $this->globalAppConfig->method('getValueBool') + ->with('core', 'shareapi_only_share_with_group_members') + ->willReturn(true); $this->assertTrue($this->guestsConfig->canCreateGuests()); $this->assertTrue($this->guestsConfig->isSharingRestrictedToGroup()); @@ -526,9 +531,9 @@ public function testCreateWithGroupButNotSubAdmin() { ->willReturn(false); // Sharing is restricted to group - $this->config->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn('yes'); + $this->globalAppConfig->method('getValueBool') + ->with('core', 'shareapi_only_share_with_group_members') + ->willReturn(true); // There is no group restriction in place $this->appConfig->method('getAppValueArray') @@ -709,10 +714,10 @@ public function testCreateSuccessWithGroupsAsSubadmin() { ->willReturn(['other_group1', 'other_group2']); // Sharing is restricted to group - $this->config->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn('yes'); - + $this->globalAppConfig->method('getValueBool') + ->with('core', 'shareapi_only_share_with_group_members') + ->willReturn(true); + $this->assertTrue($this->guestsConfig->canCreateGuests()); $this->assertTrue($this->guestsConfig->isSharingRestrictedToGroup()); diff --git a/tests/unit/GuestManagerTest.php b/tests/unit/GuestManagerTest.php index 696958a1..7dcead32 100644 --- a/tests/unit/GuestManagerTest.php +++ b/tests/unit/GuestManagerTest.php @@ -8,8 +8,11 @@ namespace OCA\Guests\Test\Unit; +use OCA\Guests\ConfigLexicon; use OCA\Guests\GuestManager; use OCA\Guests\UserBackend; +use OCP\AppFramework\Services\IAppConfig; +use OCP\Config\IUserConfig; use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; use OCP\IDBConnection; @@ -31,7 +34,12 @@ class GuestManagerTest extends TestCase { private $userManager; /** @var IConfig|MockObject */ private $config; + /** @var IAppConfig|MockObject */ + private $appConfig; + /** @var IUserConfig|MockObject */ + private $userConfig; /** @var ISecureRandom|MockObject */ + private $random; /** @var ICrypto|MockObject */ private $crypto; @@ -52,6 +60,8 @@ protected function setUp(): void { $this->userSession = $this->createMock(IUserSession::class); $this->userManager = $this->createMock(IUserManager::class); $this->config = $this->createMock(IConfig::class); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->userConfig = $this->createMock(IUserConfig::class); $this->random = $this->createMock(ISecureRandom::class); $this->random->method('generate') ->willReturnCallback(function ($count) { @@ -68,6 +78,8 @@ protected function setUp(): void { $this->guestManager = new GuestManager( $this->config, + $this->appConfig, + $this->userConfig, $this->userBackend, $this->random, $this->crypto, @@ -137,13 +149,18 @@ public function testIsGuestNull() { public function testCreateGuest() { $setValues = []; + $fnSetValues = function ($user, $app, $key, $value) use (&$setValues): bool { + if (!isset($setValues[$app])) { + $setValues[$app] = []; + } + $setValues[$app][$key] = $value; + return true; + }; + $this->config->method('setUserValue') - ->willReturnCallback(function ($user, $app, $key, $value) use (&$setValues) { - if (!isset($setValues[$app])) { - $setValues[$app] = []; - } - $setValues[$app][$key] = $value; - }); + ->willReturnCallback($fnSetValues); + $this->userConfig->method('setValueString') + ->willReturnCallback($fnSetValues); $createdByUser = $this->createMock(IUser::class); $createdByUser->method('getUID') @@ -156,6 +173,11 @@ public function testCreateGuest() { ->with('guest@example.com', str_repeat('4', 20), $this->userBackend) ->willReturn($guestUser); + $this->appConfig->expects($this->once()) + ->method('getAppValueString') + ->with(ConfigLexicon::GUEST_DISK_QUOTA) + ->willReturn('0 B'); + $guestUser->expects($this->once()) ->method('setDisplayName') ->with('Example Guest');