diff options
-rw-r--r-- | .github/workflows/node.yml | 7 | ||||
-rw-r--r-- | apps/files_sharing/lib/External/Scanner.php | 71 | ||||
-rw-r--r-- | apps/files_sharing/tests/External/ScannerTest.php | 12 | ||||
-rw-r--r-- | apps/oauth2/tests/Controller/SettingsControllerTest.php | 11 | ||||
-rw-r--r-- | lib/private/AppFramework/Http/Request.php | 33 | ||||
-rw-r--r-- | tests/Test/Repair/Owncloud/CleanPreviewsBackgroundJobTest.php | 50 | ||||
-rw-r--r-- | tests/Test/Repair/Owncloud/CleanPreviewsTest.php | 21 | ||||
-rw-r--r-- | tests/Test/Repair/Owncloud/UpdateLanguageCodesTest.php | 30 | ||||
-rw-r--r-- | tests/lib/AppFramework/Http/RequestTest.php | 77 |
9 files changed, 138 insertions, 174 deletions
diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml index a0ecd45b149..7173a224c24 100644 --- a/.github/workflows/node.yml +++ b/.github/workflows/node.yml @@ -13,6 +13,9 @@ on: - master - stable* +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest @@ -50,10 +53,12 @@ jobs: - name: Check webpack build changes run: | - bash -c "[[ ! \"`git status --porcelain `\" ]] || exit 1" + bash -c "[[ ! \"`git status --porcelain `\" ]] || (echo 'Please recompile and commit the assets, see the section \"Show changes on failure\" for details' && exit 1)" - name: Show changes on failure if: failure() run: | git status git --no-pager diff + exit 1 # make it red to grab attention + diff --git a/apps/files_sharing/lib/External/Scanner.php b/apps/files_sharing/lib/External/Scanner.php index cfde56103da..e3336c69a05 100644 --- a/apps/files_sharing/lib/External/Scanner.php +++ b/apps/files_sharing/lib/External/Scanner.php @@ -29,27 +29,14 @@ use OC\ForbiddenException; use OCP\Files\NotFoundException; use OCP\Files\StorageInvalidException; use OCP\Files\StorageNotAvailableException; -use OCP\Http\Client\LocalServerException; -use Psr\Log\LoggerInterface; class Scanner extends \OC\Files\Cache\Scanner { /** @var \OCA\Files_Sharing\External\Storage */ protected $storage; - /** {@inheritDoc} */ public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true) { - try { - if (!$this->storage->remoteIsOwnCloud()) { - return parent::scan($path, $recursive, $reuse, $lock); - } - } catch (LocalServerException $e) { - // Scanner doesn't have dependency injection - \OC::$server->get(LoggerInterface::class) - ->warning('Trying to scan files inside invalid external storage: ' . $this->storage->getRemote() . ' for mountpoint ' . $this->storage->getMountPoint() . ' and id ' . $this->storage->getId()); - return; - } - - $this->scanAll(); + // Disable locking for federated shares + parent::scan($path, $recursive, $reuse, false); } /** @@ -67,7 +54,7 @@ class Scanner extends \OC\Files\Cache\Scanner { */ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true, $data = null) { try { - return parent::scanFile($file, $reuseExisting); + return parent::scanFile($file, $reuseExisting, $parentId, $cacheData, $lock, $data); } catch (ForbiddenException $e) { $this->storage->checkStorageAvailability(); } catch (NotFoundException $e) { @@ -81,56 +68,4 @@ class Scanner extends \OC\Files\Cache\Scanner { $this->storage->checkStorageAvailability(); } } - - /** - * Checks the remote share for changes. - * If changes are available, scan them and update - * the cache. - * @throws NotFoundException - * @throws StorageInvalidException - * @throws \Exception - */ - public function scanAll() { - try { - $data = $this->storage->getShareInfo(); - } catch (\Exception $e) { - $this->storage->checkStorageAvailability(); - throw new \Exception( - 'Error while scanning remote share: "' . - $this->storage->getRemote() . '" ' . - $e->getMessage() - ); - } - if ($data['status'] === 'success') { - $this->addResult($data['data'], ''); - } else { - throw new \Exception( - 'Error while scanning remote share: "' . - $this->storage->getRemote() . '"' - ); - } - } - - /** - * @param array $data - * @param string $path - */ - private function addResult($data, $path) { - $id = $this->cache->put($path, $data); - if (isset($data['children'])) { - $children = []; - foreach ($data['children'] as $child) { - $children[$child['name']] = true; - $this->addResult($child, ltrim($path . '/' . $child['name'], '/')); - } - - $existingCache = $this->cache->getFolderContentsById($id); - foreach ($existingCache as $existingChild) { - // if an existing child is not in the new data, remove it - if (!isset($children[$existingChild['name']])) { - $this->cache->remove(ltrim($path . '/' . $existingChild['name'], '/')); - } - } - } - } } diff --git a/apps/files_sharing/tests/External/ScannerTest.php b/apps/files_sharing/tests/External/ScannerTest.php index 57696a697eb..2d2486737dc 100644 --- a/apps/files_sharing/tests/External/ScannerTest.php +++ b/apps/files_sharing/tests/External/ScannerTest.php @@ -50,18 +50,6 @@ class ScannerTest extends TestCase { $this->scanner = new Scanner($this->storage); } - public function testScanAll() { - $this->storage->expects($this->any()) - ->method('getShareInfo') - ->willReturn(['status' => 'success', 'data' => []]); - - // FIXME add real tests, we are currently only checking for - // Declaration of OCA\Files_Sharing\External\Scanner::*() should be - // compatible with OC\Files\Cache\Scanner::*() - $this->scanner->scanAll(); - $this->addToAssertionCount(1); - } - public function testScan() { $this->storage->expects($this->any()) ->method('getShareInfo') diff --git a/apps/oauth2/tests/Controller/SettingsControllerTest.php b/apps/oauth2/tests/Controller/SettingsControllerTest.php index 4954d379f9d..216655190ae 100644 --- a/apps/oauth2/tests/Controller/SettingsControllerTest.php +++ b/apps/oauth2/tests/Controller/SettingsControllerTest.php @@ -72,15 +72,12 @@ class SettingsControllerTest extends TestCase { public function testAddClient() { $this->secureRandom - ->expects($this->at(0)) + ->expects($this->exactly(2)) ->method('generate') ->with(64, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') - ->willReturn('MySecret'); - $this->secureRandom - ->expects($this->at(1)) - ->method('generate') - ->with(64, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') - ->willReturn('MyClientIdentifier'); + ->willReturnOnConsecutiveCalls( + 'MySecret', + 'MyClientIdentifier'); $client = new Client(); $client->setName('My Client Name'); diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index 35cd46bf68a..496a845dd4a 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -25,6 +25,7 @@ declare(strict_types=1); * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Thomas Tanghus <thomas@tanghus.net> * @author Vincent Petry <vincent@nextcloud.com> + * @author Simon Leiner <simon@leiner.me> * * @license AGPL-3.0 * @@ -50,6 +51,7 @@ use OCP\IConfig; use OCP\IRequest; use OCP\IRequestId; use OCP\Security\ICrypto; +use Symfony\Component\HttpFoundation\IpUtils; /** * Class for accessing variables in the request. @@ -573,41 +575,12 @@ class Request implements \ArrayAccess, \Countable, IRequest { } /** - * Checks if given $remoteAddress matches given $trustedProxy. - * If $trustedProxy is an IPv4 IP range given in CIDR notation, true will be returned if - * $remoteAddress is an IPv4 address within that IP range. - * Otherwise $remoteAddress will be compared to $trustedProxy literally and the result - * will be returned. - * @return boolean true if $remoteAddress matches $trustedProxy, false otherwise - */ - protected function matchesTrustedProxy($trustedProxy, $remoteAddress) { - $cidrre = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\/([0-9]{1,2})$/'; - - if (preg_match($cidrre, $trustedProxy, $match)) { - $net = $match[1]; - $shiftbits = min(32, max(0, 32 - intval($match[2]))); - $netnum = ip2long($net) >> $shiftbits; - $ipnum = ip2long($remoteAddress) >> $shiftbits; - - return $ipnum === $netnum; - } - - return $trustedProxy === $remoteAddress; - } - - /** * Checks if given $remoteAddress matches any entry in the given array $trustedProxies. * For details regarding what "match" means, refer to `matchesTrustedProxy`. * @return boolean true if $remoteAddress matches any entry in $trustedProxies, false otherwise */ protected function isTrustedProxy($trustedProxies, $remoteAddress) { - foreach ($trustedProxies as $tp) { - if ($this->matchesTrustedProxy($tp, $remoteAddress)) { - return true; - } - } - - return false; + return IpUtils::checkIp($remoteAddress, $trustedProxies); } /** diff --git a/tests/Test/Repair/Owncloud/CleanPreviewsBackgroundJobTest.php b/tests/Test/Repair/Owncloud/CleanPreviewsBackgroundJobTest.php index 8ecef60c35d..3c15d51fd61 100644 --- a/tests/Test/Repair/Owncloud/CleanPreviewsBackgroundJobTest.php +++ b/tests/Test/Repair/Owncloud/CleanPreviewsBackgroundJobTest.php @@ -107,12 +107,12 @@ class CleanPreviewsBackgroundJobTest extends TestCase { $this->equalTo(['uid' => 'myuid']) ); - $this->logger->expects($this->at(0)) + $this->logger->expects($this->exactly(2)) ->method('info') - ->with($this->equalTo('Started preview cleanup for myuid')); - $this->logger->expects($this->at(1)) - ->method('info') - ->with($this->equalTo('New preview cleanup scheduled for myuid')); + ->withConsecutive( + [$this->equalTo('Started preview cleanup for myuid')], + [$this->equalTo('New preview cleanup scheduled for myuid')], + ); $this->job->run(['uid' => 'myuid']); } @@ -146,12 +146,12 @@ class CleanPreviewsBackgroundJobTest extends TestCase { $this->jobList->expects($this->never()) ->method('add'); - $this->logger->expects($this->at(0)) - ->method('info') - ->with($this->equalTo('Started preview cleanup for myuid')); - $this->logger->expects($this->at(1)) + $this->logger->expects($this->exactly(2)) ->method('info') - ->with($this->equalTo('Preview cleanup done for myuid')); + ->withConsecutive( + [$this->equalTo('Started preview cleanup for myuid')], + [$this->equalTo('Preview cleanup done for myuid')], + ); $thumbnailFolder->expects($this->once()) ->method('delete'); @@ -165,12 +165,12 @@ class CleanPreviewsBackgroundJobTest extends TestCase { ->with($this->equalTo('myuid')) ->willThrowException(new NotFoundException()); - $this->logger->expects($this->at(0)) - ->method('info') - ->with($this->equalTo('Started preview cleanup for myuid')); - $this->logger->expects($this->at(1)) + $this->logger->expects($this->exactly(2)) ->method('info') - ->with($this->equalTo('Preview cleanup done for myuid')); + ->withConsecutive( + [$this->equalTo('Started preview cleanup for myuid')], + [$this->equalTo('Preview cleanup done for myuid')], + ); $this->job->run(['uid' => 'myuid']); } @@ -189,12 +189,12 @@ class CleanPreviewsBackgroundJobTest extends TestCase { ->with($this->equalTo('thumbnails')) ->willThrowException(new NotFoundException()); - $this->logger->expects($this->at(0)) - ->method('info') - ->with($this->equalTo('Started preview cleanup for myuid')); - $this->logger->expects($this->at(1)) + $this->logger->expects($this->exactly(2)) ->method('info') - ->with($this->equalTo('Preview cleanup done for myuid')); + ->withConsecutive( + [$this->equalTo('Started preview cleanup for myuid')], + [$this->equalTo('Preview cleanup done for myuid')], + ); $this->job->run(['uid' => 'myuid']); } @@ -229,12 +229,12 @@ class CleanPreviewsBackgroundJobTest extends TestCase { $this->jobList->expects($this->never()) ->method('add'); - $this->logger->expects($this->at(0)) + $this->logger->expects($this->exactly(2)) ->method('info') - ->with($this->equalTo('Started preview cleanup for myuid')); - $this->logger->expects($this->at(1)) - ->method('info') - ->with($this->equalTo('Preview cleanup done for myuid')); + ->withConsecutive( + [$this->equalTo('Started preview cleanup for myuid')], + [$this->equalTo('Preview cleanup done for myuid')], + ); $thumbnailFolder->expects($this->once()) ->method('delete') diff --git a/tests/Test/Repair/Owncloud/CleanPreviewsTest.php b/tests/Test/Repair/Owncloud/CleanPreviewsTest.php index abd166057be..7a6c374a2d7 100644 --- a/tests/Test/Repair/Owncloud/CleanPreviewsTest.php +++ b/tests/Test/Repair/Owncloud/CleanPreviewsTest.php @@ -79,18 +79,17 @@ class CleanPreviewsTest extends TestCase { $function($user2); })); - $this->jobList->expects($this->at(0)) + $this->jobList->expects($this->exactly(2)) ->method('add') - ->with( - $this->equalTo(CleanPreviewsBackgroundJob::class), - $this->equalTo(['uid' => 'user1']) - ); - - $this->jobList->expects($this->at(1)) - ->method('add') - ->with( - $this->equalTo(CleanPreviewsBackgroundJob::class), - $this->equalTo(['uid' => 'user2']) + ->withConsecutive( + [ + $this->equalTo(CleanPreviewsBackgroundJob::class), + $this->equalTo(['uid' => 'user1']) + ], + [ + $this->equalTo(CleanPreviewsBackgroundJob::class), + $this->equalTo(['uid' => 'user2']) + ], ); $this->config->expects($this->once()) diff --git a/tests/Test/Repair/Owncloud/UpdateLanguageCodesTest.php b/tests/Test/Repair/Owncloud/UpdateLanguageCodesTest.php index 3b0b2f57f5f..b5d339eef2f 100644 --- a/tests/Test/Repair/Owncloud/UpdateLanguageCodesTest.php +++ b/tests/Test/Repair/Owncloud/UpdateLanguageCodesTest.php @@ -96,27 +96,17 @@ class UpdateLanguageCodesTest extends TestCase { /** @var IOutput|\PHPUnit_Framework_MockObject_MockObject $outputMock */ $outputMock = $this->createMock(IOutput::class); - $outputMock->expects($this->at(0)) + $outputMock->expects($this->exactly(7)) ->method('info') - ->with('Changed 1 setting(s) from "bg_BG" to "bg" in preferences table.'); - $outputMock->expects($this->at(1)) - ->method('info') - ->with('Changed 0 setting(s) from "cs_CZ" to "cs" in preferences table.'); - $outputMock->expects($this->at(2)) - ->method('info') - ->with('Changed 1 setting(s) from "fi_FI" to "fi" in preferences table.'); - $outputMock->expects($this->at(3)) - ->method('info') - ->with('Changed 0 setting(s) from "hu_HU" to "hu" in preferences table.'); - $outputMock->expects($this->at(4)) - ->method('info') - ->with('Changed 0 setting(s) from "nb_NO" to "nb" in preferences table.'); - $outputMock->expects($this->at(5)) - ->method('info') - ->with('Changed 0 setting(s) from "sk_SK" to "sk" in preferences table.'); - $outputMock->expects($this->at(6)) - ->method('info') - ->with('Changed 2 setting(s) from "th_TH" to "th" in preferences table.'); + ->withConsecutive( + ['Changed 1 setting(s) from "bg_BG" to "bg" in preferences table.'], + ['Changed 0 setting(s) from "cs_CZ" to "cs" in preferences table.'], + ['Changed 1 setting(s) from "fi_FI" to "fi" in preferences table.'], + ['Changed 0 setting(s) from "hu_HU" to "hu" in preferences table.'], + ['Changed 0 setting(s) from "nb_NO" to "nb" in preferences table.'], + ['Changed 0 setting(s) from "sk_SK" to "sk" in preferences table.'], + ['Changed 2 setting(s) from "th_TH" to "th" in preferences table.'], + ); $this->config->expects($this->once()) ->method('getSystemValue') diff --git a/tests/lib/AppFramework/Http/RequestTest.php b/tests/lib/AppFramework/Http/RequestTest.php index 3289a373a12..cf5ebdca2f0 100644 --- a/tests/lib/AppFramework/Http/RequestTest.php +++ b/tests/lib/AppFramework/Http/RequestTest.php @@ -585,6 +585,83 @@ class RequestTest extends \Test\TestCase { $this->assertSame('192.168.3.99', $request->getRemoteAddress()); } + public function testGetRemoteIpv6AddressWithMatchingIpv6CidrTrustedRemote() { + $this->config + ->expects($this->exactly(2)) + ->method('getSystemValue') + ->withConsecutive( + ['trusted_proxies'], + ['forwarded_for_headers'] + )->willReturnOnConsecutiveCalls( + ['2001:db8:85a3:8d3:1319:8a20::/95'], + ['HTTP_X_FORWARDED_FOR'] + ); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '2001:db8:85a3:8d3:1319:8a21:370:7348', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->requestId, + $this->config, + $this->csrfTokenManager, + $this->stream + ); + + $this->assertSame('192.168.0.233', $request->getRemoteAddress()); + } + + public function testGetRemoteAddressIpv6WithNotMatchingCidrTrustedRemote() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('trusted_proxies') + ->willReturn(['fd::/8']); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '2001:db8:85a3:8d3:1319:8a2e:370:7348', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->requestId, + $this->config, + $this->csrfTokenManager, + $this->stream + ); + + $this->assertSame('2001:db8:85a3:8d3:1319:8a2e:370:7348', $request->getRemoteAddress()); + } + + public function testGetRemoteAddressIpv6WithInvalidTrustedProxy() { + $this->config + ->expects($this->once()) + ->method('getSystemValue') + ->with('trusted_proxies') + ->willReturn(['fx::/8']); + + $request = new Request( + [ + 'server' => [ + 'REMOTE_ADDR' => '2001:db8:85a3:8d3:1319:8a2e:370:7348', + 'HTTP_X_FORWARDED' => '10.4.0.5, 10.4.0.4', + 'HTTP_X_FORWARDED_FOR' => '192.168.0.233' + ], + ], + $this->requestId, + $this->config, + $this->csrfTokenManager, + $this->stream + ); + + $this->assertSame('2001:db8:85a3:8d3:1319:8a2e:370:7348', $request->getRemoteAddress()); + } + public function testGetRemoteAddressWithXForwardedForIPv6() { $this->config ->expects($this->exactly(2)) |