diff options
-rw-r--r-- | apps/files_sharing/tests/CapabilitiesTest.php | 12 | ||||
-rw-r--r-- | apps/settings/js/admin.js | 6 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Sharing.php | 9 | ||||
-rw-r--r-- | apps/settings/templates/settings/admin/sharing.php | 10 | ||||
-rw-r--r-- | apps/settings/tests/Settings/Admin/SharingTest.php | 4 | ||||
-rw-r--r-- | config/config.sample.php | 5 | ||||
-rw-r--r-- | lib/private/Share20/Manager.php | 14 | ||||
-rw-r--r-- | lib/private/legacy/OC_Util.php | 7 | ||||
-rw-r--r-- | lib/public/Share/IManager.php | 4 | ||||
-rw-r--r-- | lib/public/Util.php | 8 | ||||
-rw-r--r-- | tests/lib/Share20/ManagerTest.php | 34 |
11 files changed, 103 insertions, 10 deletions
diff --git a/apps/files_sharing/tests/CapabilitiesTest.php b/apps/files_sharing/tests/CapabilitiesTest.php index eb10c927140..f52ebf9909c 100644 --- a/apps/files_sharing/tests/CapabilitiesTest.php +++ b/apps/files_sharing/tests/CapabilitiesTest.php @@ -137,6 +137,7 @@ class CapabilitiesTest extends \Test\TestCase { $map = [ ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertIsArray($result['public']); @@ -147,6 +148,7 @@ class CapabilitiesTest extends \Test\TestCase { $map = [ ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ['core', 'shareapi_enforce_links_password', 'no', 'yes'], ]; $result = $this->getResults($map); @@ -159,6 +161,7 @@ class CapabilitiesTest extends \Test\TestCase { $map = [ ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ['core', 'shareapi_enforce_links_password', 'no', 'no'], ]; $result = $this->getResults($map); @@ -172,6 +175,7 @@ class CapabilitiesTest extends \Test\TestCase { ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_links', 'yes', 'yes'], ['core', 'shareapi_default_expire_date', 'no', 'no'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertArrayHasKey('expire_date', $result['public']); @@ -186,6 +190,7 @@ class CapabilitiesTest extends \Test\TestCase { ['core', 'shareapi_default_expire_date', 'no', 'yes'], ['core', 'shareapi_expire_after_n_days', '7', '7'], ['core', 'shareapi_enforce_expire_date', 'no', 'no'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertArrayHasKey('expire_date', $result['public']); @@ -201,6 +206,7 @@ class CapabilitiesTest extends \Test\TestCase { ['core', 'shareapi_allow_links', 'yes', 'yes'], ['core', 'shareapi_default_expire_date', 'no', 'yes'], ['core', 'shareapi_enforce_expire_date', 'no', 'yes'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertArrayHasKey('expire_date', $result['public']); @@ -213,6 +219,7 @@ class CapabilitiesTest extends \Test\TestCase { ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_links', 'yes', 'yes'], ['core', 'shareapi_allow_public_notification', 'no', 'yes'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertTrue($result['public']['send_mail']); @@ -223,6 +230,7 @@ class CapabilitiesTest extends \Test\TestCase { ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_links', 'yes', 'yes'], ['core', 'shareapi_allow_public_notification', 'no', 'no'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertFalse($result['public']['send_mail']); @@ -232,6 +240,7 @@ class CapabilitiesTest extends \Test\TestCase { $map = [ ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_resharing', 'yes', 'yes'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertTrue($result['resharing']); @@ -241,6 +250,7 @@ class CapabilitiesTest extends \Test\TestCase { $map = [ ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_resharing', 'yes', 'no'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertFalse($result['resharing']); @@ -251,6 +261,7 @@ class CapabilitiesTest extends \Test\TestCase { ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_links', 'yes', 'yes'], ['core', 'shareapi_allow_public_upload', 'yes', 'yes'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertTrue($result['public']['upload']); @@ -262,6 +273,7 @@ class CapabilitiesTest extends \Test\TestCase { ['core', 'shareapi_enabled', 'yes', 'yes'], ['core', 'shareapi_allow_links', 'yes', 'yes'], ['core', 'shareapi_allow_public_upload', 'yes', 'no'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ]; $result = $this->getResults($map); $this->assertFalse($result['public']['upload']); diff --git a/apps/settings/js/admin.js b/apps/settings/js/admin.js index 20d9843fe14..5e3580c0760 100644 --- a/apps/settings/js/admin.js +++ b/apps/settings/js/admin.js @@ -1,5 +1,5 @@ window.addEventListener('DOMContentLoaded', function(){ - $('#excludedGroups,#linksExcludedGroups').each(function (index, element) { + $('#excludedGroups,#linksExcludedGroups,#passwordsExcludedGroups').each(function(index, element) { OC.Settings.setupGroupsSelect($(element)); $(element).change(function(ev) { var groups = ev.val || []; @@ -94,6 +94,10 @@ window.addEventListener('DOMContentLoaded', function(){ $("#setDefaultRemoteExpireDate").toggleClass('hidden', !this.checked); }); + $('#enforceLinkPassword').change(function() { + $('#selectPasswordsExcludedGroups').toggleClass('hidden', !this.checked) + }) + $('#publicShareDisclaimer').change(function() { $("#publicShareDisclaimerText").toggleClass('hidden', !this.checked); if(!this.checked) { diff --git a/apps/settings/lib/Settings/Admin/Sharing.php b/apps/settings/lib/Settings/Admin/Sharing.php index 85d3e4d8d40..f4c44d49ef8 100644 --- a/apps/settings/lib/Settings/Admin/Sharing.php +++ b/apps/settings/lib/Settings/Admin/Sharing.php @@ -70,6 +70,11 @@ class Sharing implements ISettings { $linksExcludeGroupsList = !is_null(json_decode($linksExcludedGroups)) ? implode('|', json_decode($linksExcludedGroups, true)) : ''; + $excludedPasswordGroups = $this->config->getAppValue('core', 'shareapi_enforce_links_password_excluded_groups', ''); + $excludedPasswordGroupsList = !is_null(json_decode($excludedPasswordGroups)) + ? implode('|', json_decode($excludedPasswordGroups, true)) : ''; + + $parameters = [ // Built-In Sharing 'allowGroupSharing' => $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes'), @@ -81,7 +86,9 @@ class Sharing implements ISettings { 'restrictUserEnumerationToGroup' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no'), 'restrictUserEnumerationToPhone' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no'), 'restrictUserEnumerationFullMatch' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes'), - 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(), + 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(false), + 'passwordExcludedGroups' => $excludedPasswordGroupsList, + 'passwordExcludedGroupsFeatureEnabled' => $this->config->getSystemValueBool('sharing.allow_disabled_password_enforcement_groups', false), 'onlyShareWithGroupMembers' => $this->shareManager->shareWithGroupMembersOnly(), 'shareAPIEnabled' => $this->config->getAppValue('core', 'shareapi_enabled', 'yes'), 'shareDefaultExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no'), diff --git a/apps/settings/templates/settings/admin/sharing.php b/apps/settings/templates/settings/admin/sharing.php index e85047b7037..917c20ea2d8 100644 --- a/apps/settings/templates/settings/admin/sharing.php +++ b/apps/settings/templates/settings/admin/sharing.php @@ -115,6 +115,16 @@ } ?> /> <label for="enforceLinkPassword"><?php p($l->t('Enforce password protection'));?></label><br/> +<?php if ($_['passwordExcludedGroupsFeatureEnabled']) { ?> + <div id="selectPasswordsExcludedGroups" class="indent <?php if (!$_['enforceLinkPassword']) { p('hidden'); } ?>"> + <div class="indent"> + <label for="shareapi_enforce_links_password_excluded_groups"><?php p($l->t('Exclude groups from password requirements:'));?> + <br /> + <input name="shareapi_enforce_links_password_excluded_groups" id="passwordsExcludedGroups" value="<?php p($_['passwordExcludedGroups']) ?>" style="width: 400px" class="noJSAutoUpdate"/> + </div> + </div> +<?php } ?> + <input type="checkbox" name="shareapi_default_expire_date" id="shareapiDefaultExpireDate" class="checkbox" value="1" <?php if ($_['shareDefaultExpireDateSet'] === 'yes') { print_unescaped('checked="checked"'); diff --git a/apps/settings/tests/Settings/Admin/SharingTest.php b/apps/settings/tests/Settings/Admin/SharingTest.php index ff25c717498..983fc04022e 100644 --- a/apps/settings/tests/Settings/Admin/SharingTest.php +++ b/apps/settings/tests/Settings/Admin/SharingTest.php @@ -125,6 +125,8 @@ class SharingTest extends TestCase { 'shareRemoteExpireAfterNDays' => '7', 'shareRemoteEnforceExpireDate' => 'no', 'allowLinksExcludeGroups' => '', + 'passwordExcludedGroups' => '', + 'passwordExcludedGroupsFeatureEnabled' => false, ], '' ); @@ -194,6 +196,8 @@ class SharingTest extends TestCase { 'shareRemoteExpireAfterNDays' => '7', 'shareRemoteEnforceExpireDate' => 'no', 'allowLinksExcludeGroups' => '', + 'passwordExcludedGroups' => '', + 'passwordExcludedGroupsFeatureEnabled' => false, ], '' ); diff --git a/config/config.sample.php b/config/config.sample.php index 4bb976fbcad..cffb3fa8f89 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1554,6 +1554,11 @@ $CONFIG = [ 'sharing.enable_share_mail' => true, /** + * Set to true to enable the feature to add exceptions for share password enforcement + */ +'sharing.allow_disabled_password_enforcement_groups' => false, + +/** * Set to true to always transfer incoming shares by default * when running "occ files:transfer-ownership". * Defaults to false, so incoming shares are not transferred if not specifically requested diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 84d23e1b087..e17bb7ee79d 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -1763,9 +1763,21 @@ class Manager implements IManager { /** * Is password on public link requires * + * @param bool Check group membership exclusion * @return bool */ - public function shareApiLinkEnforcePassword() { + public function shareApiLinkEnforcePassword(bool $checkGroupMembership = true) { + $excludedGroups = $this->config->getAppValue('core', 'shareapi_enforce_links_password_excluded_groups', ''); + if ($excludedGroups !== '' && $checkGroupMembership) { + $excludedGroups = json_decode($excludedGroups); + $user = $this->userSession->getUser(); + if ($user) { + $userGroups = $this->groupManager->getUserGroupIds($user); + if ((bool)array_intersect($excludedGroups, $userGroups)) { + return false; + } + } + } return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes'; } diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php index 9892faf6032..7e0fd45e054 100644 --- a/lib/private/legacy/OC_Util.php +++ b/lib/private/legacy/OC_Util.php @@ -347,15 +347,16 @@ class OC_Util { } /** - * check if a password is required for each public link + * Check if a password is required for each public link * + * @param bool $checkGroupMembership Check group membership exclusion * @return boolean * @suppress PhanDeprecatedFunction */ - public static function isPublicLinkPasswordRequired() { + public static function isPublicLinkPasswordRequired(bool $checkGroupMembership = true) { /** @var IManager $shareManager */ $shareManager = \OC::$server->get(IManager::class); - return $shareManager->shareApiLinkEnforcePassword(); + return $shareManager->shareApiLinkEnforcePassword($checkGroupMembership); } /** diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php index 77a9980a894..bad3af6837f 100644 --- a/lib/public/Share/IManager.php +++ b/lib/public/Share/IManager.php @@ -316,10 +316,12 @@ interface IManager { /** * Is password on public link requires * + * @param bool $checkGroupMembership Check group membership exclusion * @return bool * @since 9.0.0 + * @since 24.0.0 Added optional $checkGroupMembership parameter */ - public function shareApiLinkEnforcePassword(); + public function shareApiLinkEnforcePassword(bool $checkGroupMembership = true); /** * Is default expire date enabled diff --git a/lib/public/Util.php b/lib/public/Util.php index 5165846707a..b0937a5bb52 100644 --- a/lib/public/Util.php +++ b/lib/public/Util.php @@ -482,12 +482,14 @@ class Util { } /** - * check if a password is required for each public link + * Check if a password is required for each public link + * + * @param bool $checkGroupMembership Check group membership exclusion * @return boolean * @since 7.0.0 */ - public static function isPublicLinkPasswordRequired() { - return \OC_Util::isPublicLinkPasswordRequired(); + public static function isPublicLinkPasswordRequired(bool $checkGroupMembership = true) { + return \OC_Util::isPublicLinkPasswordRequired($checkGroupMembership); } /** diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php index a6320fe305b..1aaf1144c03 100644 --- a/tests/lib/Share20/ManagerTest.php +++ b/tests/lib/Share20/ManagerTest.php @@ -497,14 +497,46 @@ class ManagerTest extends \Test\TestCase { $this->expectExceptionMessage('Passwords are enforced for link and mail shares'); $this->config->method('getAppValue')->willReturnMap([ + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ['core', 'shareapi_enforce_links_password', 'no', 'yes'], ]); self::invokePrivate($this->manager, 'verifyPassword', [null]); } + public function testVerifyPasswordNotEnforcedGroup() { + $this->config->method('getAppValue')->willReturnMap([ + ['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin"]'], + ['core', 'shareapi_enforce_links_password', 'no', 'yes'], + ]); + + // Create admin user + $user = $this->createMock(IUser::class); + $this->userSession->method('getUser')->willReturn($user); + $this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['admin']); + + $result = self::invokePrivate($this->manager, 'verifyPassword', [null]); + $this->assertNull($result); + } + + public function testVerifyPasswordNotEnforcedMultipleGroups() { + $this->config->method('getAppValue')->willReturnMap([ + ['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin", "special"]'], + ['core', 'shareapi_enforce_links_password', 'no', 'yes'], + ]); + + // Create admin user + $user = $this->createMock(IUser::class); + $this->userSession->method('getUser')->willReturn($user); + $this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['special']); + + $result = self::invokePrivate($this->manager, 'verifyPassword', [null]); + $this->assertNull($result); + } + public function testVerifyPasswordNull() { $this->config->method('getAppValue')->willReturnMap([ + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ['core', 'shareapi_enforce_links_password', 'no', 'no'], ]); @@ -514,6 +546,7 @@ class ManagerTest extends \Test\TestCase { public function testVerifyPasswordHook() { $this->config->method('getAppValue')->willReturnMap([ + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ['core', 'shareapi_enforce_links_password', 'no', 'no'], ]); @@ -535,6 +568,7 @@ class ManagerTest extends \Test\TestCase { $this->expectExceptionMessage('password not accepted'); $this->config->method('getAppValue')->willReturnMap([ + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ['core', 'shareapi_enforce_links_password', 'no', 'no'], ]); |