Kaynağa Gözat

Adds license to files. Updates the branch.

Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
Michael Weimann 5 yıl önce
ebeveyn
işleme
2bab916c53

+ 4 - 21
apps/files_sharing/js/sharedfilelist.js

@@ -166,24 +166,7 @@
 		},
 
 		updateRow: function($tr, fileInfo, options) {
-			if(!fileInfo instanceof OCA.Sharing.SharedFileInfo) {
-				// recycle SharedFileInfo values if something tries to overwrite it
-				var oldModel = this.getModelForFile($tr);
-
-				if(_.isUndefined(fileInfo.recipientData) && oldModel.recipientData) {
-					fileInfo.recipientData = oldModel.recipientData;
-				}
-				if(_.isUndefined(fileInfo.recipients) && oldModel.recipientData) {
-					fileInfo.recipientData = oldModel.recipientData;
-				}
-				if(_.isUndefined(fileInfo.shares) && oldModel.shares) {
-					fileInfo.shares = oldModel.shares;
-				}
-				if(_.isUndefined(fileInfo.shareOwner) && oldModel.shareOwner) {
-					fileInfo.shareOwner = oldModel.shareOwner;
-				}
-			}
-			OCA.Files.FileList.prototype._createRow.updateRow(this, arguments);
+			// no-op, suppress re-rendering
 		},
 
 		reload: function() {
@@ -328,11 +311,11 @@
 		 * Converts the OCS API share response data to a file info
 		 * list
 		 * @param {Array} data OCS API share array
+		 * @param {bool} sharedWithUser
 		 * @return {Array.<OCA.Sharing.SharedFileInfo>} array of shared file info
 		 */
 		_makeFilesFromShares: function(data, sharedWithUser) {
 			/* jshint camelcase: false */
-			var self = this;
 			var files = data;
 
 			if (this._linksOnly) {
@@ -447,8 +430,8 @@
 					// array of sorted names
 					data.mountType = 'shared';
 					delete data.recipientsCount;
-					if (self._sharedWithUser) {
-						// only for outgoing shres
+					if (sharedWithUser) {
+						// only for outgoing shares
 						delete data.shareTypes;
 					} else {
 						data.shareTypes = _.keys(data.shareTypes);

+ 1 - 1
build/integration/composer.json

@@ -1,7 +1,7 @@
 {
   "require-dev": {
     "phpunit/phpunit": "~6.5",
-    "behat/behat": "~3.3.0",
+    "behat/behat": "~3.5.0",
     "guzzlehttp/guzzle": "6.3.3",
     "jarnaiz/behat-junit-formatter": "^1.3",
     "sabre/dav": "3.2.2"

+ 17 - 0
core/js/setupchecks.js

@@ -325,6 +325,23 @@
 							type: OC.SetupChecks.MESSAGE_TYPE_WARNING
 						})
 					}
+
+					if(data.appDirsWithDifferentOwner && data.appDirsWithDifferentOwner.length > 0) {
+						var appDirsWithDifferentOwner = data.appDirsWithDifferentOwner.reduce(
+							function(appDirsWithDifferentOwner, directory) {
+								return appDirsWithDifferentOwner + '<li>' + directory + '</li>';
+							},
+							''
+						);
+						messages.push({
+							msg: t('core', 'Some app directories are owned by a different user than the web server one. ' +
+									'This may be the case if apps have been installed manually. ' +
+									'Check the permissions of the following app directories:')
+									+ '<ul>' + appDirsWithDifferentOwner + '</ul>',
+							type: OC.SetupChecks.MESSAGE_TYPE_WARNING
+						});
+					}
+
 				} else {
 					messages.push({
 						msg: t('core', 'Error occurred while checking server setup'),

+ 1 - 1
core/js/shareitemmodel.js

@@ -777,7 +777,7 @@
 				return {};
 			}
 
-			var permissions = this.get('possiblePermissions');
+			var permissions = this.fileInfoModel.get('permissions');
 			if(!_.isUndefined(data.reshare) && !_.isUndefined(data.reshare.permissions) && data.reshare.uid_owner !== OC.currentUser) {
 				permissions = permissions & data.reshare.permissions;
 			}

+ 71 - 11
core/js/tests/specs/setupchecksSpec.js

@@ -171,7 +171,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -219,7 +220,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -268,7 +270,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -315,7 +318,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -360,7 +364,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -373,6 +378,54 @@ describe('OC.SetupChecks tests', function() {
 			});
 		});
 
+		it('should return a warning if there are app directories with wrong permissions', function(done) {
+			var async = OC.SetupChecks.checkSetup();
+
+			suite.server.requests[0].respond(
+				200,
+				{
+					'Content-Type': 'application/json',
+				},
+				JSON.stringify({
+					hasFileinfoInstalled: true,
+					isGetenvServerWorking: true,
+					isReadOnlyConfig: false,
+					hasWorkingFileLocking: true,
+					hasValidTransactionIsolationLevel: true,
+					suggestedOverwriteCliURL: '',
+					isUrandomAvailable: true,
+					securityDocs: 'https://docs.owncloud.org/myDocs.html',
+					serverHasInternetConnection: true,
+					isMemcacheConfigured: true,
+					forwardedForHeadersWorking: true,
+					isCorrectMemcachedPHPModuleInstalled: true,
+					hasPassedCodeIntegrityCheck: true,
+					isOpcacheProperlySetup: true,
+					hasOpcacheLoaded: true,
+					isSettimelimitAvailable: true,
+					hasFreeTypeSupport: true,
+					missingIndexes: [],
+					outdatedCaches: [],
+					cronErrors: [],
+					cronInfo: {
+						diffInSeconds: 0
+					},
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: [
+						'/some/path'
+					]
+				})
+			);
+
+			async.done(function( data, s, x ){
+				expect(data).toEqual([{
+					msg: 'Some app directories are owned by a different user than the web server one. This may be the case if apps have been installed manually. Check the permissions of the following app directories:<ul><li>/some/path</li></ul>',
+					type: OC.SetupChecks.MESSAGE_TYPE_WARNING
+				}]);
+				done();
+			});
+		});
+
 		it('should return an error if the forwarded for headers are not working', function(done) {
 			var async = OC.SetupChecks.checkSetup();
 
@@ -405,7 +458,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -450,7 +504,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -495,6 +550,7 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
+					appDirsWithDifferentOwner: [],
 					isMemoryLimitSufficient: false
 				})
 			);
@@ -561,7 +617,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -607,7 +664,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -653,7 +711,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 
@@ -699,7 +758,8 @@ describe('OC.SetupChecks tests', function() {
 					cronInfo: {
 						diffInSeconds: 0
 					},
-					isMemoryLimitSufficient: true
+					isMemoryLimitSufficient: true,
+					appDirsWithDifferentOwner: []
 				})
 			);
 

+ 1 - 1
core/js/tests/specs/shareitemmodelSpec.js

@@ -345,7 +345,7 @@ describe('OC.Share.ShareItemModel', function() {
 			}]));
 			fetchSharesDeferred.resolve(makeOcsResponse([]));
 
-			model.set('possiblePermissions', OC.PERMISSION_READ);
+			model.fileInfoModel.set('permissions', OC.PERMISSION_READ);
 			model.fetch();
 
 			// no resharing allowed

+ 21 - 0
lib/private/MemoryInfo.php

@@ -1,4 +1,25 @@
 <?php
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright (c) 2018, Michael Weimann (<mail@michael-weimann.eu>)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
 
 namespace OC;
 

+ 51 - 0
settings/Controller/CheckSetupController.php

@@ -31,9 +31,11 @@
 namespace OC\Settings\Controller;
 
 use bantu\IniGetWrapper\IniGetWrapper;
+use DirectoryIterator;
 use Doctrine\DBAL\DBALException;
 use Doctrine\DBAL\Platforms\SqlitePlatform;
 use GuzzleHttp\Exception\ClientException;
+use OC;
 use OC\AppFramework\Http;
 use OC\DB\Connection;
 use OC\DB\MissingIndexInformation;
@@ -534,6 +536,54 @@ Raw output
 		return function_exists('opcache_get_status');
 	}
 
+	/**
+	 * Iterates through the configured app roots and
+	 * tests if the subdirectories are owned by the same user than the current user.
+	 *
+	 * @return array
+	 */
+	protected function getAppDirsWithDifferentOwner(): array {
+		$currentUser = posix_getpwuid(posix_getuid());
+		$appDirsWithDifferentOwner = [];
+
+		foreach (OC::$APPSROOTS as $appRoot) {
+			if ($appRoot['writable'] === true) {
+				$appDirsWithDifferentOwner = array_merge(
+					$appDirsWithDifferentOwner,
+					$this->getAppDirsWithDifferentOwnerForAppRoot($currentUser, $appRoot)
+				);
+			}
+		}
+
+		sort($appDirsWithDifferentOwner);
+		return $appDirsWithDifferentOwner;
+	}
+
+	/**
+	 * Tests if the directories for one apps directory are writable by the current user.
+	 *
+	 * @param array $currentUser The current user
+	 * @param array $appRoot The app root config
+	 * @return string[] The none writable directory paths inside the app root
+	 */
+	private function getAppDirsWithDifferentOwnerForAppRoot(array $currentUser, array $appRoot): array {
+		$appDirsWithDifferentOwner = [];
+		$appsPath = $appRoot['path'];
+		$appsDir = new DirectoryIterator($appRoot['path']);
+
+		foreach ($appsDir as $fileInfo) {
+			if ($fileInfo->isDir() && !$fileInfo->isDot()) {
+				$absAppPath = $appsPath . DIRECTORY_SEPARATOR . $fileInfo->getFilename();
+				$appDirUser = posix_getpwuid(fileowner($absAppPath));
+				if ($appDirUser !== $currentUser) {
+					$appDirsWithDifferentOwner[] = $absAppPath . DIRECTORY_SEPARATOR . $fileInfo->getFilename();
+				}
+			}
+		}
+
+		return $appDirsWithDifferentOwner;
+	}
+
 	/**
 	 * @return DataResponse
 	 */
@@ -572,6 +622,7 @@ Raw output
 				'isPhpMailerUsed' => $this->isPhpMailerUsed(),
 				'mailSettingsDocumentation' => $this->urlGenerator->getAbsoluteURL('index.php/settings/admin'),
 				'isMemoryLimitSufficient' => $this->memoryInfo->isMemoryLimitSufficient(),
+				'appDirsWithDifferentOwner' => $this->getAppDirsWithDifferentOwner(),
 			]
 		);
 	}

+ 79 - 0
tests/Settings/Controller/CheckSetupControllerTest.php

@@ -21,6 +21,7 @@
 
 namespace Tests\Settings\Controller;
 
+use OC;
 use OC\DB\Connection;
 use OC\MemoryInfo;
 use OC\Settings\Controller\CheckSetupController;
@@ -46,6 +47,7 @@ use OC\IntegrityCheck\Checker;
 /**
  * Class CheckSetupControllerTest
  *
+ * @backupStaticAttributes
  * @package Tests\Settings\Controller
  */
 class CheckSetupControllerTest extends TestCase {
@@ -78,6 +80,13 @@ class CheckSetupControllerTest extends TestCase {
 	/** @var MemoryInfo|MockObject */
 	private $memoryInfo;
 
+	/**
+	 * Holds a list of directories created during tests.
+	 *
+	 * @var array
+	 */
+	private $dirsToRemove = [];
+
 	public function setUp() {
 		parent::setUp();
 
@@ -143,9 +152,23 @@ class CheckSetupControllerTest extends TestCase {
 				'isSqliteUsed',
 				'isPhpMailerUsed',
 				'hasOpcacheLoaded',
+				'getAppDirsWithDifferentOwner',
 			])->getMock();
 	}
 
+	/**
+	 * Removes directories created during tests.
+	 *
+	 * @after
+	 * @return void
+	 */
+	public function removeTestDirectories() {
+		foreach ($this->dirsToRemove as $dirToRemove) {
+			rmdir($dirToRemove);
+		}
+		$this->dirsToRemove = [];
+	}
+
 	public function testIsInternetConnectionWorkingDisabledViaConfig() {
 		$this->config->expects($this->once())
 			->method('getSystemValue')
@@ -436,6 +459,11 @@ class CheckSetupControllerTest extends TestCase {
 			->method('isMemoryLimitSufficient')
 			->willReturn(true);
 
+		$this->checkSetupController
+			->expects($this->once())
+			->method('getAppDirsWithDifferentOwner')
+			->willReturn([]);
+
 		$expected = new DataResponse(
 			[
 				'isGetenvServerWorking' => true,
@@ -477,6 +505,7 @@ class CheckSetupControllerTest extends TestCase {
 				'isPhpMailerUsed' => false,
 				'mailSettingsDocumentation' => 'https://server/index.php/settings/admin',
 				'isMemoryLimitSufficient' => true,
+				'appDirsWithDifferentOwner' => [],
 			]
 		);
 		$this->assertEquals($expected, $this->checkSetupController->check());
@@ -584,6 +613,56 @@ class CheckSetupControllerTest extends TestCase {
 		$this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
 	}
 
+	/**
+	 * Setups a temp directory and some subdirectories.
+	 * Then calls the 'getAppDirsWithDifferentOwner' method.
+	 * The result is expected to be empty since
+	 * there are no directories with different owners than the current user.
+	 *
+	 * @return void
+	 */
+	public function testAppDirectoryOwnersOk() {
+		$tempDir = tempnam(sys_get_temp_dir(), 'apps') . 'dir';
+		mkdir($tempDir);
+		mkdir($tempDir . DIRECTORY_SEPARATOR . 'app1');
+		mkdir($tempDir . DIRECTORY_SEPARATOR . 'app2');
+		$this->dirsToRemove[] = $tempDir . DIRECTORY_SEPARATOR . 'app1';
+		$this->dirsToRemove[] = $tempDir . DIRECTORY_SEPARATOR . 'app2';
+		$this->dirsToRemove[] = $tempDir;
+		OC::$APPSROOTS = [
+			[
+				'path' => $tempDir,
+				'url' => '/apps',
+				'writable' => true,
+			],
+		];
+		$this->assertSame(
+			[],
+			$this->invokePrivate($this->checkSetupController, 'getAppDirsWithDifferentOwner')
+		);
+	}
+
+	/**
+	 * Calls the check for a none existing app root that is marked as not writable.
+	 * It's expected that no error happens since the check shouldn't apply.
+	 *
+	 * @return void
+	 */
+	public function testAppDirectoryOwnersNotWritable() {
+		$tempDir = tempnam(sys_get_temp_dir(), 'apps') . 'dir';
+		OC::$APPSROOTS = [
+			[
+				'path' => $tempDir,
+				'url' => '/apps',
+				'writable' => false,
+			],
+		];
+		$this->assertSame(
+			[],
+			$this->invokePrivate($this->checkSetupController, 'getAppDirsWithDifferentOwner')
+		);
+	}
+
 	public function testIsBuggyNss400() {
 		$this->config->expects($this->any())
 			->method('getSystemValue')

+ 21 - 0
tests/lib/MemoryInfoTest.php

@@ -1,4 +1,25 @@
 <?php
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright (c) 2018, Michael Weimann (<mail@michael-weimann.eu>)
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
 
 namespace Test;