diff options
51 files changed, 620 insertions, 172 deletions
diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 99f888ce0f7..5b345a45b67 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -101,7 +101,10 @@ throw t('files', '"{name}" is an invalid file name.', {name: name}); } else if (trimmedName.length === 0) { throw t('files', 'File name cannot be empty.'); + } else if (OC.fileIsBlacklisted(trimmedName)) { + throw t('files', '"{name}" is not an allowed filetype', {name: name}); } + return true; }, displayStorageWarnings: function() { diff --git a/apps/files/lib/Command/Scan.php b/apps/files/lib/Command/Scan.php index 0234fb435a7..24b47aca9a4 100644 --- a/apps/files/lib/Command/Scan.php +++ b/apps/files/lib/Command/Scan.php @@ -30,6 +30,7 @@ namespace OCA\Files\Command; use Doctrine\DBAL\Connection; use OC\Core\Command\Base; +use OC\Core\Command\InterruptedException; use OC\ForbiddenException; use OCP\Files\StorageNotAvailableException; use OCP\IDBConnection; @@ -117,14 +118,14 @@ class Scan extends Base { $output->writeln("\tFile <info>$path</info>"); $this->filesCounter += 1; if ($this->hasBeenInterrupted()) { - throw new \Exception('ctrl-c'); + throw new InterruptedException(); } }); $scanner->listen('\OC\Files\Utils\Scanner', 'scanFolder', function ($path) use ($output) { $output->writeln("\tFolder <info>$path</info>"); $this->foldersCounter += 1; if ($this->hasBeenInterrupted()) { - throw new \Exception('ctrl-c'); + throw new InterruptedException(); } }); $scanner->listen('\OC\Files\Utils\Scanner', 'StorageNotAvailable', function (StorageNotAvailableException $e) use ($output) { @@ -135,13 +136,13 @@ class Scan extends Base { $scanner->listen('\OC\Files\Utils\Scanner', 'scanFile', function () use ($output) { $this->filesCounter += 1; if ($this->hasBeenInterrupted()) { - throw new \Exception('ctrl-c'); + throw new InterruptedException(); } }); $scanner->listen('\OC\Files\Utils\Scanner', 'scanFolder', function () use ($output) { $this->foldersCounter += 1; if ($this->hasBeenInterrupted()) { - throw new \Exception('ctrl-c'); + throw new InterruptedException(); } }); } @@ -161,11 +162,12 @@ class Scan extends Base { } catch (ForbiddenException $e) { $output->writeln("<error>Home storage for user $user not writable</error>"); $output->writeln("Make sure you're running the scan command only as the user the web server runs as"); + } catch (InterruptedException $e) { + # exit the function if ctrl-c has been pressed + $output->writeln('Interrupted by user'); } catch (\Exception $e) { - if ($e->getMessage() !== 'ctrl-c') { - $output->writeln('<error>Exception while scanning: ' . $e->getMessage() . "\n" . $e->getTraceAsString() . '</error>'); - } - return; + $output->writeln('<error>Exception during scan: ' . $e->getMessage() . '</error>'); + $output->writeln('<error>' . $e->getTraceAsString() . '</error>'); } } diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js index b7627d59fdf..5c3f68b2ba4 100644 --- a/apps/files/tests/js/filesSpec.js +++ b/apps/files/tests/js/filesSpec.js @@ -58,7 +58,9 @@ describe('OCA.Files.Files tests', function() { ' ..', '.. ', '. ', - ' .' + ' .', + 'foo.part', + 'bar.filepart' ]; for ( var i = 0; i < fileNames.length; i++ ) { var threwException = false; diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index 711970d0c84..78eef6c26bb 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -804,7 +804,7 @@ class ShareAPIController extends OCSController { if ($checkGroups && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { $sharedWith = $this->groupManager->get($share->getSharedWith()); $user = $this->userManager->get($this->currentUser); - if ($user !== null && $sharedWith->inGroup($user)) { + if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) { return true; } } diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php index f474190fc98..a02d6350499 100644 --- a/apps/files_sharing/lib/MountProvider.php +++ b/apps/files_sharing/lib/MountProvider.php @@ -173,7 +173,23 @@ class MountProvider implements IMountProvider { if ($share->getTarget() !== $superShare->getTarget()) { // adjust target, for database consistency $share->setTarget($superShare->getTarget()); - $this->shareManager->moveShare($share, $user->getUID()); + try { + $this->shareManager->moveShare($share, $user->getUID()); + } catch (\InvalidArgumentException $e) { + // ignore as it is not important and we don't want to + // block FS setup + + // the subsequent code anyway only uses the target of the + // super share + + // such issue can usually happen when dealing with + // null groups which usually appear with group backend + // caching inconsistencies + $this->logger->debug( + 'Could not adjust share target for share ' . $share->getId() . ' to make it consistent: ' . $e->getMessage(), + ['app' => 'files_sharing'] + ); + } } if (!is_null($share->getNodeCacheEntry())) { $superShare->setNodeCacheEntry($share->getNodeCacheEntry()); diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index dd2ea855b0b..123a5cb4f53 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -120,7 +120,7 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size); <input type="hidden" name="dir" id="dir" value="" /> <div class="hiddenuploadfield"> <input type="file" id="file_upload_start" class="hiddenuploadfield" name="files[]" - data-url="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" /> + data-url="<?php p(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" /> </div> <?php endif; ?> <footer> diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 97774081b6a..2bf9a40b2cc 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -544,14 +544,19 @@ class ShareAPIControllerTest extends \Test\TestCase { $this->groupManager->method('get')->will($this->returnValueMap([ ['group', $group], ['group2', $group2], + ['groupnull', null], ])); $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); $share = $this->getMockBuilder('OCP\Share\IShare')->getMock(); $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP); $share->method('getSharedWith')->willReturn('group2'); + $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); - $this->groupManager->method('get')->with('group2')->willReturn($group); + // null group + $share = $this->getMock('OCP\Share\IShare'); + $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP); + $share->method('getSharedWith')->willReturn('groupnull'); $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); $share = $this->getMockBuilder('OCP\Share\IShare')->getMock(); diff --git a/apps/files_sharing/tests/MountProviderTest.php b/apps/files_sharing/tests/MountProviderTest.php index 1c83d91d08f..b700d417ad4 100644 --- a/apps/files_sharing/tests/MountProviderTest.php +++ b/apps/files_sharing/tests/MountProviderTest.php @@ -269,6 +269,20 @@ class MountProviderTest extends \Test\TestCase { ['1', 100, 'user2', '/share2-renamed', 31], ], ], + // #9: share as outsider with "nullgroup" and "user1" where recipient renamed in between + [ + [ + [2, 100, 'user2', '/share2', 31], + ], + [ + [1, 100, 'nullgroup', '/share2-renamed', 31], + ], + [ + // use target of least recent share + ['1', 100, 'nullgroup', '/share2-renamed', 31], + ], + true + ], ]; } @@ -284,7 +298,7 @@ class MountProviderTest extends \Test\TestCase { * @param array $groupShares array of group share specs * @param array $expectedShares array of expected supershare specs */ - public function testMergeShares($userShares, $groupShares, $expectedShares) { + public function testMergeShares($userShares, $groupShares, $expectedShares, $moveFails = false) { $rootFolder = $this->createMock(IRootFolder::class); $userManager = $this->createMock(IUserManager::class); @@ -319,6 +333,12 @@ class MountProviderTest extends \Test\TestCase { return new \OC\Share20\Share($rootFolder, $userManager); })); + if ($moveFails) { + $this->shareManager->expects($this->any()) + ->method('moveShare') + ->will($this->throwException(new \InvalidArgumentException())); + } + $mounts = $this->provider->getMountsForUser($this->user, $this->loader); $this->assertCount(count($expectedShares), $mounts); diff --git a/apps/files_sharing/tests/js/publicAppSpec.js b/apps/files_sharing/tests/js/publicAppSpec.js index e8ec9899ecc..8ea339fd9de 100644 --- a/apps/files_sharing/tests/js/publicAppSpec.js +++ b/apps/files_sharing/tests/js/publicAppSpec.js @@ -125,6 +125,10 @@ describe('OCA.Sharing.PublicApp tests', function() { expect(fileList.getAjaxUrl('test', {a:1, b:'x y'})) .toEqual(OC.webroot + '/index.php/apps/files_sharing/ajax/test.php?a=1&b=x%20y&t=sh4tok'); }); + it('returns correct download URL for downloading everything', function() { + expect(fileList.getDownloadUrl()) + .toEqual(OC.webroot + '/index.php/s/sh4tok/download?path=%2Fsubdir'); + }); }); describe('Upload Url', function() { var fileList; diff --git a/apps/theming/lib/ThemingDefaults.php b/apps/theming/lib/ThemingDefaults.php index 36f19157637..20625116213 100644 --- a/apps/theming/lib/ThemingDefaults.php +++ b/apps/theming/lib/ThemingDefaults.php @@ -28,6 +28,7 @@ use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\Files\IRootFolder; +use OCP\Util; class ThemingDefaults extends \OC_Defaults { @@ -81,7 +82,7 @@ class ThemingDefaults extends \OC_Defaults { } public function getName() { - return $this->config->getAppValue('theming', 'name', $this->name); + return strip_tags($this->config->getAppValue('theming', 'name', $this->name)); } public function getHTMLName() { @@ -89,11 +90,11 @@ class ThemingDefaults extends \OC_Defaults { } public function getTitle() { - return $this->config->getAppValue('theming', 'name', $this->name); + return $this->getName(); } public function getEntity() { - return $this->config->getAppValue('theming', 'name', $this->name); + return $this->getName(); } public function getBaseUrl() { @@ -101,7 +102,7 @@ class ThemingDefaults extends \OC_Defaults { } public function getSlogan() { - return $this->config->getAppValue('theming', 'slogan', $this->slogan); + return Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', $this->slogan)); } public function getShortFooter() { diff --git a/build/integration/features/bootstrap/BasicStructure.php b/build/integration/features/bootstrap/BasicStructure.php index 8e1fcf86ba1..8961efc6f31 100644 --- a/build/integration/features/bootstrap/BasicStructure.php +++ b/build/integration/features/bootstrap/BasicStructure.php @@ -353,6 +353,30 @@ trait BasicStructure { fclose($file); } + public function createFileWithText($name, $text){ + $file = fopen("work/" . "$name", 'w'); + fwrite($file, $text); + fclose($file); + } + + /** + * @Given file :filename of size :size is created in local storage + * @param string $filename + * @param string $size + */ + public function fileIsCreatedInLocalStorageWithSize($filename, $size) { + $this->createFileSpecificSize("local_storage/$filename", $size); + } + + /** + * @Given file :filename with text :text is created in local storage + * @param string $filename + * @param string $text + */ + public function fileIsCreatedInLocalStorageWithText($filename, $text) { + $this->createFileWithText("local_storage/$filename", $text); + } + /** * @When User :user empties trashbin * @param string $user diff --git a/build/integration/features/bootstrap/WebDav.php b/build/integration/features/bootstrap/WebDav.php index 680d8f96e7c..0a75ff96732 100644 --- a/build/integration/features/bootstrap/WebDav.php +++ b/build/integration/features/bootstrap/WebDav.php @@ -729,4 +729,23 @@ trait WebDav { } } + /** + * @When /^User "([^"]*)" deletes everything from folder "([^"]*)"$/ + * @param string $user + * @param string $folder + */ + public function userDeletesEverythingInFolder($user, $folder) { + $elementList = $this->listFolder($user, $folder, 1); + $elementListKeys = array_keys($elementList); + array_shift($elementListKeys); + $davPrefix = "/" . $this->getDavFilesPath($user); + foreach($elementListKeys as $element) { + if (substr($element, 0, strlen($davPrefix)) == $davPrefix) { + $element = substr($element, strlen($davPrefix)); + } + $this->userDeletesFile($user, "element", $element); + } + } + + } diff --git a/build/integration/features/webdav-related.feature b/build/integration/features/webdav-related.feature index c3aa6145527..775bf2ca882 100644 --- a/build/integration/features/webdav-related.feature +++ b/build/integration/features/webdav-related.feature @@ -479,3 +479,41 @@ Feature: webdav-related When as "user0" gets properties of folder "/test_folder:5" with |{DAV:}resourcetype| Then the single response should contain a property "{DAV:}resourcetype" with value "{DAV:}collection" + + Scenario: Removing everything of a folder + Given using old dav path + And As an "admin" + And user "user0" exists + And As an "user0" + And User "user0" moves file "/welcome.txt" to "/FOLDER/welcome.txt" + And user "user0" created a folder "/FOLDER/SUBFOLDER" + And User "user0" copies file "/textfile0.txt" to "/FOLDER/SUBFOLDER/testfile0.txt" + When User "user0" deletes everything from folder "/FOLDER/" + Then user "user0" should see following elements + | /FOLDER/ | + | /PARENT/ | + | /PARENT/parent.txt | + | /textfile0.txt | + | /textfile1.txt | + | /textfile2.txt | + | /textfile3.txt | + | /textfile4.txt | + + Scenario: Removing everything of a folder using new dav path + Given using new dav path + And As an "admin" + And user "user0" exists + And As an "user0" + And User "user0" moves file "/welcome.txt" to "/FOLDER/welcome.txt" + And user "user0" created a folder "/FOLDER/SUBFOLDER" + And User "user0" copies file "/textfile0.txt" to "/FOLDER/SUBFOLDER/testfile0.txt" + When User "user0" deletes everything from folder "/FOLDER/" + Then user "user0" should see following elements + | /FOLDER/ | + | /PARENT/ | + | /PARENT/parent.txt | + | /textfile0.txt | + | /textfile1.txt | + | /textfile2.txt | + | /textfile3.txt | + | /textfile4.txt | diff --git a/core/Command/Encryption/EncryptAll.php b/core/Command/Encryption/EncryptAll.php index 3a0c88c0798..584bc8a70c7 100644 --- a/core/Command/Encryption/EncryptAll.php +++ b/core/Command/Encryption/EncryptAll.php @@ -109,10 +109,10 @@ class EncryptAll extends Command { } $output->writeln("\n"); - $output->writeln('You are about to start to encrypt all files stored in your ownCloud.'); - $output->writeln('It will depend on the encryption module you use which files get encrypted.'); - $output->writeln('Depending on the number and size of your files this can take some time'); - $output->writeln('Please make sure that no user access his files during this process!'); + $output->writeln('You are about to encrypt all files stored in your Nextcloud installation.'); + $output->writeln('Depending on the number of available files, and their size, this may take quite some time.'); + $output->writeln('Please ensure that no user accesses their files during this time!'); + $output->writeln('Note: The encryption module you use determines which files get encrypted.'); $output->writeln(''); $question = new ConfirmationQuestion('Do you really want to continue? (y/n) ', false); if ($this->questionHelper->ask($input, $output, $question)) { diff --git a/core/Command/InterruptedException.php b/core/Command/InterruptedException.php new file mode 100644 index 00000000000..ef81b5d9393 --- /dev/null +++ b/core/Command/InterruptedException.php @@ -0,0 +1,26 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2017, ownCloud, Inc. + * @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/> + * + */ +namespace OC\Core\Command; + +/** + * Exception for when the user hit ctrl-c + */ +class InterruptedException extends \Exception {} diff --git a/core/Command/User/ResetPassword.php b/core/Command/User/ResetPassword.php index 3388ef6a1bd..56260e9714a 100644 --- a/core/Command/User/ResetPassword.php +++ b/core/Command/User/ResetPassword.php @@ -100,6 +100,11 @@ class ResetPassword extends Command { $question->setHidden(true); $password = $helper->ask($input, $output, $question); + if ($password === null) { + $output->writeln("<error>Password cannot be empty!</error>"); + return 1; + } + $question = new Question('Confirm the new password: '); $question->setHidden(true); $confirm = $helper->ask($input, $output, $question); diff --git a/core/css/header.scss b/core/css/header.scss index b04d7e917e2..fd2da104c38 100644 --- a/core/css/header.scss +++ b/core/css/header.scss @@ -323,7 +323,7 @@ nav { } /* Apps management */ -#apps-management { +.apps-management { min-height: initial; height: initial; margin: 0; diff --git a/core/js/js.js b/core/js/js.js index 5c737d41793..8c6fc0d9c07 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -225,6 +225,14 @@ var OCP = {}, }, /** + * Check if a user file is allowed to be handled. + * @param {string} file to check + */ + fileIsBlacklisted: function(file) { + return !!(file.match(oc_config.blacklist_files_regex)); + }, + + /** * Redirect to the target URL, can also be used for downloads. * @param {string} targetURL URL to redirect to */ diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js index 58dd706fb1f..47471955563 100644 --- a/core/js/sharedialogview.js +++ b/core/js/sharedialogview.js @@ -120,6 +120,8 @@ '_onSelectRecipient', 'onShareWithFieldChanged' ); + + OC.Plugins.attach('OCA.Share.ShareDialogView', this); }, onShareWithFieldChanged: function() { diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js index 7897a2f2842..a411ade7dea 100644 --- a/core/js/tests/specHelper.js +++ b/core/js/tests/specHelper.js @@ -94,7 +94,8 @@ window.oc_appswebroots = { }; window.oc_config = { session_lifetime: 600 * 1000, - session_keepalive: false + session_keepalive: false, + blacklist_files_regex: '\.(part|filepart)$', }; window.oc_appconfig = { core: {} diff --git a/core/templates/installation.php b/core/templates/installation.php index 058049d8946..6a0e3f93857 100644 --- a/core/templates/installation.php +++ b/core/templates/installation.php @@ -41,14 +41,14 @@ script('core', [ <input type="text" name="adminlogin" id="adminlogin" placeholder="<?php p($l->t( 'Username' )); ?>" value="<?php p($_['adminlogin']); ?>" - autocomplete="off" autocapitalize="off" autocorrect="off" autofocus required> + autocomplete="off" autocapitalize="none" autocorrect="off" autofocus required> <label for="adminlogin" class="infield"><?php p($l->t( 'Username' )); ?></label> </p> <p class="groupbottom"> <input type="password" name="adminpass" data-typetoggle="#show" id="adminpass" placeholder="<?php p($l->t( 'Password' )); ?>" value="<?php p($_['adminpass']); ?>" - autocomplete="off" autocapitalize="off" autocorrect="off" required> + autocomplete="off" autocapitalize="none" autocorrect="off" required> <label for="adminpass" class="infield"><?php p($l->t( 'Password' )); ?></label> <input type="checkbox" id="show" name="show"> <label for="show"></label> @@ -68,7 +68,7 @@ script('core', [ <input type="text" name="directory" id="directory" placeholder="<?php p(OC::$SERVERROOT.'/data'); ?>" value="<?php p($_['directory']); ?>" - autocomplete="off" autocapitalize="off" autocorrect="off"> + autocomplete="off" autocapitalize="none" autocorrect="off"> </div> </fieldset> <?php endif; ?> @@ -105,13 +105,13 @@ script('core', [ <input type="text" name="dbuser" id="dbuser" placeholder="<?php p($l->t( 'Database user' )); ?>" value="<?php p($_['dbuser']); ?>" - autocomplete="off" autocapitalize="off" autocorrect="off"> + autocomplete="off" autocapitalize="none" autocorrect="off"> </p> <p class="groupmiddle"> <input type="password" name="dbpass" id="dbpass" data-typetoggle="#dbpassword-toggle" placeholder="<?php p($l->t( 'Database password' )); ?>" value="<?php p($_['dbpass']); ?>" - autocomplete="off" autocapitalize="off" autocorrect="off"> + autocomplete="off" autocapitalize="none" autocorrect="off"> <label for="dbpass" class="infield"><?php p($l->t( 'Database password' )); ?></label> <input type="checkbox" id="dbpassword-toggle" name="dbpassword-toggle"> <label for="dbpassword-toggle"></label> @@ -121,7 +121,7 @@ script('core', [ <input type="text" name="dbname" id="dbname" placeholder="<?php p($l->t( 'Database name' )); ?>" value="<?php p($_['dbname']); ?>" - autocomplete="off" autocapitalize="off" autocorrect="off" + autocomplete="off" autocapitalize="none" autocorrect="off" pattern="[0-9a-zA-Z$_-]+"> </p> <?php if($_['hasOracle']): ?> @@ -131,7 +131,7 @@ script('core', [ <input type="text" name="dbtablespace" id="dbtablespace" placeholder="<?php p($l->t( 'Database tablespace' )); ?>" value="<?php p($_['dbtablespace']); ?>" - autocomplete="off" autocapitalize="off" autocorrect="off"> + autocomplete="off" autocapitalize="none" autocorrect="off"> </p> </div> <?php endif; ?> @@ -140,7 +140,7 @@ script('core', [ <input type="text" name="dbhost" id="dbhost" placeholder="<?php p($l->t( 'Database host' )); ?>" value="<?php p($_['dbhost']); ?>" - autocomplete="off" autocapitalize="off" autocorrect="off"> + autocomplete="off" autocapitalize="none" autocorrect="off"> </p> <p class="info"> <?php p($l->t( 'Please specify the port number along with the host name (e.g., localhost:5432).' )); ?> diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php index 1abb263edf8..adeeaf03797 100644 --- a/core/templates/layout.user.php +++ b/core/templates/layout.user.php @@ -81,7 +81,7 @@ </a> </li> <?php if(OC_User::isAdminUser(OC_User::getUser())): ?> - <li id="apps-management" <?php if(count($_['navigation'])>$headerIconCount-1): ?>class="hidden"<?php endif; ?>> + <li <?php if(count($_['navigation'])>$headerIconCount-1): ?> class="hidden apps-management"<?php else: ?> class="apps-management" <?php endif; ?>> <a href="<?php print_unescaped(\OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')); ?>" tabindex="4" <?php if( $_['appsmanagement_active'] ): ?> class="active"<?php endif; ?>> <img src="<?php print_unescaped(image_path('settings', 'apps.svg') . '?v=' . $_['versionHash']); ?>" /> @@ -119,7 +119,7 @@ /* show "More apps" link to app administration directly in app navigation, as last entry */ if(OC_User::isAdminUser(OC_User::getUser())): ?> - <li id="apps-management"> + <li class="apps-management"> <a href="<?php print_unescaped(\OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')); ?>" tabindex="4" <?php if( $_['appsmanagement_active'] ): ?> class="active"<?php endif; ?>> <svg width="32" height="32" viewBox="0 0 32 32" class="app-icon"> diff --git a/core/templates/login.php b/core/templates/login.php index 221242c0dcb..352893bd0dc 100644 --- a/core/templates/login.php +++ b/core/templates/login.php @@ -43,7 +43,7 @@ script('core', [ placeholder="<?php p($l->t('Username or email')); ?>" value="<?php p($_['loginName']); ?>" <?php p($_['user_autofocus'] ? 'autofocus' : ''); ?> - autocomplete="on" autocapitalize="off" autocorrect="off" required> + autocomplete="on" autocapitalize="none" autocorrect="off" required> <label for="user" class="infield"><?php p($l->t('Username or email')); ?></label> </p> @@ -51,7 +51,7 @@ script('core', [ <input type="password" name="password" id="password" value="" placeholder="<?php p($l->t('Password')); ?>" <?php p($_['user_autofocus'] ? '' : 'autofocus'); ?> - autocomplete="on" autocapitalize="off" autocorrect="off" required> + autocomplete="on" autocapitalize="off" autocorrect="none" required> <label for="password" class="infield"><?php p($l->t('Password')); ?></label> </p> diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index c87bcce194f..d0d0898d0bd 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -407,6 +407,7 @@ return array( 'OC\\Core\\Command\\Integrity\\CheckCore' => $baseDir . '/core/Command/Integrity/CheckCore.php', 'OC\\Core\\Command\\Integrity\\SignApp' => $baseDir . '/core/Command/Integrity/SignApp.php', 'OC\\Core\\Command\\Integrity\\SignCore' => $baseDir . '/core/Command/Integrity/SignCore.php', + 'OC\\Core\\Command\\InterruptedException' => $baseDir . '/core/Command/InterruptedException.php', 'OC\\Core\\Command\\L10n\\CreateJs' => $baseDir . '/core/Command/L10n/CreateJs.php', 'OC\\Core\\Command\\Log\\File' => $baseDir . '/core/Command/Log/File.php', 'OC\\Core\\Command\\Log\\Manage' => $baseDir . '/core/Command/Log/Manage.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index eb7188b69b3..7b937bd132c 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -437,6 +437,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Command\\Integrity\\CheckCore' => __DIR__ . '/../../..' . '/core/Command/Integrity/CheckCore.php', 'OC\\Core\\Command\\Integrity\\SignApp' => __DIR__ . '/../../..' . '/core/Command/Integrity/SignApp.php', 'OC\\Core\\Command\\Integrity\\SignCore' => __DIR__ . '/../../..' . '/core/Command/Integrity/SignCore.php', + 'OC\\Core\\Command\\InterruptedException' => __DIR__ . '/../../..' . '/core/Command/InterruptedException.php', 'OC\\Core\\Command\\L10n\\CreateJs' => __DIR__ . '/../../..' . '/core/Command/L10n/CreateJs.php', 'OC\\Core\\Command\\Log\\File' => __DIR__ . '/../../..' . '/core/Command/Log/File.php', 'OC\\Core\\Command\\Log\\Manage' => __DIR__ . '/../../..' . '/core/Command/Log/Manage.php', diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 6b819ef7ac1..6c1f5ba6940 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -32,6 +32,7 @@ namespace OC\App; use OCP\App\AppPathNotFoundException; +use OC_App; use OCP\App\IAppManager; use OCP\App\ManagerEvent; use OCP\IAppConfig; @@ -210,8 +211,12 @@ class AppManager implements IAppManager { * Enable an app for every user * * @param string $appId + * @throws \Exception */ public function enableApp($appId) { + if(OC_App::getAppPath($appId) === false) { + throw new \Exception("$appId can't be enabled since it is not installed."); + } $this->installedAppsCache[$appId] = 'yes'; $this->appConfig->setValue($appId, 'enabled', 'yes'); $this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE, new ManagerEvent( diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php index 7d2f03d593e..693381ea2b4 100644 --- a/lib/private/Console/Application.php +++ b/lib/private/Console/Application.php @@ -37,6 +37,7 @@ use Symfony\Component\Console\Application as SymfonyApplication; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class Application { @@ -97,7 +98,8 @@ class Application { throw new NeedsUpdateException(); } elseif ($this->config->getSystemValue('maintenance', false)) { if ($input->getArgument('command') !== '_completion') { - $output->writeln("Nextcloud is in maintenance mode - no apps have been loaded"); + $errOutput = $output->getErrorOutput(); + $errOutput->writeln('<comment>Nextcloud is in maintenance mode - no app have been loaded</comment>' . PHP_EOL); } } else { OC_App::loadApps(); diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index 6ffb5edff3e..506128d7fcd 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -96,8 +96,12 @@ class View { private $updaterEnabled = true; + /** @var \OC\User\Manager */ private $userManager; + /** @var \OCP\ILogger */ + private $logger; + /** * @param string $root * @throws \Exception If $root contains an invalid path @@ -114,6 +118,7 @@ class View { $this->lockingProvider = \OC::$server->getLockingProvider(); $this->lockingEnabled = !($this->lockingProvider instanceof \OC\Lock\NoopLockingProvider); $this->userManager = \OC::$server->getUserManager(); + $this->logger = \OC::$server->getLogger(); } public function getAbsolutePath($path = '/') { @@ -2068,6 +2073,12 @@ class View { $parts = explode('/', trim($path, '/'), 3); // "$user", "files", "path/to/dir" if (!isset($parts[1]) || $parts[1] !== 'files') { + $this->logger->error( + '$absolutePath must be relative to "files", value is "%s"', + [ + $absolutePath + ] + ); throw new \InvalidArgumentException('$absolutePath must be relative to "files"'); } if (isset($parts[2])) { diff --git a/lib/private/Group/Manager.php b/lib/private/Group/Manager.php index 944598a8296..40009dbfd80 100644 --- a/lib/private/Group/Manager.php +++ b/lib/private/Group/Manager.php @@ -37,7 +37,10 @@ namespace OC\Group; use OC\Hooks\PublicEmitter; use OCP\GroupInterface; +use OCP\IGroup; use OCP\IGroupManager; +use OCP\ILogger; +use OCP\IUser; /** * Class Manager @@ -78,11 +81,16 @@ class Manager extends PublicEmitter implements IGroupManager { /** @var \OC\SubAdmin */ private $subAdmin = null; + /** @var ILogger */ + private $logger; + /** * @param \OC\User\Manager $userManager + * @param ILogger $logger */ - public function __construct(\OC\User\Manager $userManager) { + public function __construct(\OC\User\Manager $userManager, ILogger $logger) { $this->userManager = $userManager; + $this->logger = $logger; $cachedGroups = & $this->cachedGroups; $cachedUserGroups = & $this->cachedUserGroups; $this->listen('\OC\Group', 'postDelete', function ($group) use (&$cachedGroups, &$cachedUserGroups) { @@ -186,7 +194,7 @@ class Manager extends PublicEmitter implements IGroupManager { * @return bool */ public function groupExists($gid) { - return !is_null($this->get($gid)); + return $this->get($gid) instanceof IGroup; } /** @@ -194,7 +202,7 @@ class Manager extends PublicEmitter implements IGroupManager { * @return \OC\Group\Group */ public function createGroup($gid) { - if ($gid === '' || is_null($gid)) { + if ($gid === '' || $gid === null) { return false; } else if ($group = $this->get($gid)) { return $group; @@ -223,7 +231,12 @@ class Manager extends PublicEmitter implements IGroupManager { foreach ($this->backends as $backend) { $groupIds = $backend->getGroups($search, $limit, $offset); foreach ($groupIds as $groupId) { - $groups[$groupId] = $this->get($groupId); + $aGroup = $this->get($groupId); + if ($aGroup instanceof IGroup) { + $groups[$groupId] = $aGroup; + } else { + $this->logger->debug('Group "' . $groupId . '" was returned by search but not found through direct access', ['app' => 'core']); + } } if (!is_null($limit) and $limit <= 0) { return array_values($groups); @@ -237,7 +250,7 @@ class Manager extends PublicEmitter implements IGroupManager { * @return \OC\Group\Group[] */ public function getUserGroups($user) { - if (is_null($user)) { + if (!$user instanceof IUser) { return []; } return $this->getUserIdGroups($user->getUID()); @@ -256,7 +269,12 @@ class Manager extends PublicEmitter implements IGroupManager { $groupIds = $backend->getUserGroups($uid); if (is_array($groupIds)) { foreach ($groupIds as $groupId) { - $groups[$groupId] = $this->get($groupId); + $aGroup = $this->get($groupId); + if ($aGroup instanceof IGroup) { + $groups[$groupId] = $aGroup; + } else { + $this->logger->debug('User "' . $uid . '" belongs to deleted group: "' . $groupId . '"', ['app' => 'core']); + } } } } diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php index 32a732d8580..fd75e51b638 100644 --- a/lib/private/Preview/Generator.php +++ b/lib/private/Preview/Generator.php @@ -26,6 +26,7 @@ namespace OC\Preview; use OCP\Files\File; use OCP\Files\IAppData; use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; use OCP\Files\SimpleFS\ISimpleFile; use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IConfig; @@ -111,6 +112,11 @@ class Generator { // Calculate the preview size list($width, $height) = $this->calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight); + // No need to generate a preview that is just the max preview + if ($width === $maxWidth && $height === $maxHeight) { + return $maxPreview; + } + // Try to get a cached preview. Else generate (and store) one try { $file = $this->getCachedPreview($previewFolder, $width, $height, $crop); @@ -158,9 +164,13 @@ class Generator { continue; } - $path = strval($preview->width()) . '-' . strval($preview->height()) . '-max.png'; - $file = $previewFolder->newFile($path); - $file->putContent($preview->data()); + $path = (string)$preview->width() . '-' . (string)$preview->height() . '-max.png'; + try { + $file = $previewFolder->newFile($path); + $file->putContent($preview->data()); + } catch (NotPermittedException $e) { + throw new NotFoundException(); + } return $file; } @@ -185,7 +195,7 @@ class Generator { * @return string */ private function generatePath($width, $height, $crop) { - $path = strval($width) . '-' . strval($height); + $path = (string)$width . '-' . (string)$height; if ($crop) { $path .= '-crop'; } @@ -246,18 +256,18 @@ class Generator { /* * Scale to the nearest power of two */ - $pow2height = pow(2, ceil(log($height) / log(2))); - $pow2width = pow(2, ceil(log($width) / log(2))); + $pow2height = 2 ** ceil(log($height) / log(2)); + $pow2width = 2 ** ceil(log($width) / log(2)); $ratioH = $height / $pow2height; $ratioW = $width / $pow2width; if ($ratioH < $ratioW) { $width = $pow2width; - $height = $height / $ratioW; + $height /= $ratioW; } else { $height = $pow2height; - $width = $width / $ratioH; + $width /= $ratioH; } } @@ -268,12 +278,12 @@ class Generator { if ($height > $maxHeight) { $ratio = $height / $maxHeight; $height = $maxHeight; - $width = $width / $ratio; + $width /= $ratio; } if ($width > $maxWidth) { $ratio = $width / $maxWidth; $width = $maxWidth; - $height = $height / $ratio; + $height /= $ratio; } return [(int)round($width), (int)round($height)]; @@ -316,8 +326,12 @@ class Generator { } $path = $this->generatePath($width, $height, $crop); - $file = $previewFolder->newFile($path); - $file->putContent($preview->data()); + try { + $file = $previewFolder->newFile($path); + $file->putContent($preview->data()); + } catch (NotPermittedException $e) { + throw new NotFoundException(); + } return $file; } diff --git a/lib/private/Server.php b/lib/private/Server.php index 24cd8b38684..dbec71457ef 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -227,7 +227,7 @@ class Server extends ServerContainer implements IServerContainer { return new \OC\User\Manager($config); }); $this->registerService('GroupManager', function (Server $c) { - $groupManager = new \OC\Group\Manager($this->getUserManager()); + $groupManager = new \OC\Group\Manager($this->getUserManager(), $this->getLogger()); $groupManager->listen('\OC\Group', 'preCreate', function ($gid) { \OC_Hook::emit('OC_Group', 'pre_createGroup', array('run' => true, 'gid' => $gid)); }); diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index fe6472c31a0..e4ae26be13d 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -329,6 +329,10 @@ class DefaultShareProvider implements IShareProvider { $group = $this->groupManager->get($share->getSharedWith()); $user = $this->userManager->get($recipient); + if (is_null($group)) { + throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist'); + } + if (!$group->inGroup($user)) { throw new ProviderException('Recipient not in receiving group'); } diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 3b565d1ba8c..e0457bba437 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -398,10 +398,12 @@ class Manager implements IManager { // The share is already shared with this user via a group share if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { $group = $this->groupManager->get($existingShare->getSharedWith()); - $user = $this->userManager->get($share->getSharedWith()); + if (!is_null($group)) { + $user = $this->userManager->get($share->getSharedWith()); - if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) { - throw new \Exception('Path already shared with this user'); + if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) { + throw new \Exception('Path already shared with this user'); + } } } } @@ -423,7 +425,7 @@ class Manager implements IManager { if ($this->shareWithGroupMembersOnly()) { $sharedBy = $this->userManager->get($share->getSharedBy()); $sharedWith = $this->groupManager->get($share->getSharedWith()); - if (!$sharedWith->inGroup($sharedBy)) { + if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) { throw new \Exception('Only sharing within your own groups is allowed'); } } @@ -891,6 +893,9 @@ class Manager implements IManager { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { $sharedWith = $this->groupManager->get($share->getSharedWith()); + if (is_null($sharedWith)) { + throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist'); + } $recipient = $this->userManager->get($recipientId); if (!$sharedWith->inGroup($recipient)) { throw new \InvalidArgumentException('Invalid recipient'); diff --git a/lib/private/SystemTag/SystemTagManager.php b/lib/private/SystemTag/SystemTagManager.php index 7c21c0e004e..d0854e885eb 100644 --- a/lib/private/SystemTag/SystemTagManager.php +++ b/lib/private/SystemTag/SystemTagManager.php @@ -400,6 +400,9 @@ class SystemTagManager implements ISystemTagManager { 'gid' => $query->createParameter('gid'), ]); foreach ($groupIds as $groupId) { + if ($groupId === '') { + continue; + } $query->setParameter('gid', $groupId); $query->execute(); } diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php index 6bf08dcdada..ca45bbee9c6 100644 --- a/lib/private/Template/JSConfigHelper.php +++ b/lib/private/Template/JSConfigHelper.php @@ -209,6 +209,7 @@ class JSConfigHelper { 'modRewriteWorking' => ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true'), 'sharing.maxAutocompleteResults' => intval($this->config->getSystemValue('sharing.maxAutocompleteResults', 0)), 'sharing.minSearchStringLength' => intval($this->config->getSystemValue('sharing.minSearchStringLength', 0)), + 'blacklist_files_regex' => \OCP\Files\FileInfo::BLACKLIST_FILES_REGEX, ]), "oc_appconfig" => json_encode([ 'core' => [ diff --git a/lib/private/Template/ResourceLocator.php b/lib/private/Template/ResourceLocator.php index 9015bf5d97c..e82a77ba65f 100755 --- a/lib/private/Template/ResourceLocator.php +++ b/lib/private/Template/ResourceLocator.php @@ -84,7 +84,7 @@ abstract class ResourceLocator { $this->doFindTheme($resource); } catch (ResourceNotFoundException $e) { $resourceApp = substr($resource, 0, strpos($resource, '/')); - $this->logger->debug('Could not find resource file "' . $e->getResourcePath() . '"', ['app' => $resourceApp]); + $this->logger->debug('Could not find resource file in theme "' . $e->getResourcePath() . '"', ['app' => $resourceApp]); } } } diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index 060953c3009..ec463ba91dd 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -234,7 +234,7 @@ class Database extends Backend implements IUserBackend { /** * Load an user in the cache * @param string $uid the username - * @return boolean + * @return boolean true if user was found, false otherwise */ private function loadUser($uid) { if (!isset($this->cache[$uid])) { @@ -254,9 +254,14 @@ class Database extends Backend implements IUserBackend { $this->cache[$uid] = false; - while ($row = $result->fetchRow()) { + // "uid" is primary key, so there can only be a single result + if ($row = $result->fetchRow()) { $this->cache[$uid]['uid'] = $row['uid']; $this->cache[$uid]['displayname'] = $row['displayname']; + $result->closeCursor(); + } else { + $result->closeCursor(); + return false; } } diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index c03cbd5891b..4980318b554 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -14,6 +14,7 @@ * @author Robin McCorkell <robin@mccorkell.me.uk> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> + * @author Felix Rupp <kontakt@felixrupp.com> * * @license AGPL-3.0 * @@ -70,6 +71,7 @@ use Symfony\Component\EventDispatcher\GenericEvent; * - preRememberedLogin(string $uid) * - postRememberedLogin(\OC\User\User $user) * - logout() + * - postLogout() * * @package OC\User */ @@ -796,6 +798,7 @@ class Session implements IUserSession, Emitter { $this->setToken(null); $this->unsetMagicInCookie(); $this->session->clear(); + $this->manager->emit('\OC\User', 'postLogout'); } /** diff --git a/lib/private/legacy/files.php b/lib/private/legacy/files.php index ed3aa719409..017691805c9 100644 --- a/lib/private/legacy/files.php +++ b/lib/private/legacy/files.php @@ -264,12 +264,12 @@ class OC_Files { if (\OC\Files\Filesystem::isReadable($filename)) { self::sendHeaders($filename, $name, $rangeArray); } elseif (!\OC\Files\Filesystem::file_exists($filename)) { - header("HTTP/1.0 404 Not Found"); + header("HTTP/1.1 404 Not Found"); $tmpl = new OC_Template('', '404', 'guest'); $tmpl->printPage(); exit(); } else { - header("HTTP/1.0 403 Forbidden"); + header("HTTP/1.1 403 Forbidden"); die('403 Forbidden'); } if (isset($params['head']) && $params['head']) { diff --git a/lib/public/Files/FileInfo.php b/lib/public/Files/FileInfo.php index b6718efba34..8eeb8df08ce 100644 --- a/lib/public/Files/FileInfo.php +++ b/lib/public/Files/FileInfo.php @@ -64,6 +64,12 @@ interface FileInfo { const MIMETYPE_FOLDER = 'httpd/unix-directory'; /** + * @const \OCP\Files\FileInfo::BLACKLIST_FILES_REGEX Return regular expression to test filenames against (blacklisting) + * @since 12.0.0 + */ + const BLACKLIST_FILES_REGEX = '\.(part|filepart)$'; + + /** * Get the Etag of the file or folder * * @return string diff --git a/settings/js/apps.js b/settings/js/apps.js index 8be18c4e9c0..d2f26578a7c 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -541,10 +541,10 @@ OC.Settings.Apps = OC.Settings.Apps || { if (navEntries.length > 7) { $('#more-apps').show(); - $('#apps-management').hide(); + $('.apps-management').hide(); } else { $('#more-apps').hide(); - $('#apps-management').show(); + $('.apps-management').show(); } } }); diff --git a/settings/templates/personal.php b/settings/templates/personal.php index b47e2e28ffa..d94fbb33770 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -81,7 +81,7 @@ <input type="text" id="displayname" name="displayname" <?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?> value="<?php p($_['displayName']) ?>" - autocomplete="on" autocapitalize="off" autocorrect="off" /> + autocomplete="on" autocapitalize="none" autocorrect="off" /> <?php if(!$_['displayNameChangeSupported']) { ?> <span><?php if(isset($_['displayName']) && !empty($_['displayName'])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span> <?php } ?> @@ -98,7 +98,7 @@ <input type="email" name="email" id="email" value="<?php p($_['email']); ?>" <?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?> placeholder="<?php p($l->t('Your email address')); ?>" - autocomplete="on" autocapitalize="off" autocorrect="off" /> + autocomplete="on" autocapitalize="none" autocorrect="off" /> <?php if(!$_['displayNameChangeSupported']) { ?> <span><?php if(isset($_['email']) && !empty($_['email'])) { p($_['email']); } else { p($l->t('No email address set')); }?></span> <?php } ?> @@ -119,7 +119,7 @@ <input type="tel" id="phone" name="phone" value="<?php p($_['phone']) ?>" placeholder="<?php p($l->t('Your phone number')); ?>" - autocomplete="on" autocapitalize="off" autocorrect="off" /> + autocomplete="on" autocapitalize="none" autocorrect="off" /> <span class="icon-checkmark hidden"/> <input type="hidden" id="phonescope" value="<?php p($_['phoneScope']) ?>"> </form> @@ -133,7 +133,7 @@ <input type="text" id="address" name="address" placeholder="<?php p($l->t('Your postal address')); ?>" value="<?php p($_['address']) ?>" - autocomplete="on" autocapitalize="off" autocorrect="off" /> + autocomplete="on" autocapitalize="none" autocorrect="off" /> <span class="icon-checkmark hidden"/> <input type="hidden" id="addressscope" value="<?php p($_['addressScope']) ?>"> </form> @@ -146,7 +146,7 @@ </h2> <input type="text" name="website" id="website" value="<?php p($_['website']); ?>" placeholder="<?php p($l->t('Your website')); ?>" - autocomplete="on" autocapitalize="off" autocorrect="off" /> + autocomplete="on" autocapitalize="none" autocorrect="off" /> <span class="icon-checkmark hidden"/> <input type="hidden" id="websitescope" value="<?php p($_['websiteScope']) ?>"> </form> @@ -159,7 +159,7 @@ </h2> <input type="text" name="twitter" id="twitter" value="<?php p($_['twitter']); ?>" placeholder="<?php p($l->t('Your Twitter handle')); ?>" - autocomplete="on" autocapitalize="off" autocorrect="off" /> + autocomplete="on" autocapitalize="none" autocorrect="off" /> <span class="icon-checkmark hidden"/> <input type="hidden" id="twitterscope" value="<?php p($_['twitterScope']) ?>"> </form> @@ -188,13 +188,13 @@ if($_['passwordChangeSupported']) { <label for="pass1" class="hidden-visually"><?php p($l->t('Current password')); ?>: </label> <input type="password" id="pass1" name="oldpassword" placeholder="<?php p($l->t('Current password'));?>" - autocomplete="off" autocapitalize="off" autocorrect="off" /> + autocomplete="off" autocapitalize="none" autocorrect="off" /> <div class="personal-show-container"> <label for="pass2" class="hidden-visually"><?php p($l->t('New password'));?>: </label> <input type="password" id="pass2" name="newpassword" placeholder="<?php p($l->t('New password')); ?>" data-typetoggle="#personal-show" - autocomplete="off" autocapitalize="off" autocorrect="off" /> + autocomplete="off" autocapitalize="none" autocorrect="off" /> <input type="checkbox" id="personal-show" name="show" /><label for="personal-show" class="personal-show-label"></label> </div> <input id="passwordbutton" type="submit" value="<?php p($l->t('Change password')); ?>" /> diff --git a/settings/templates/users/part.createuser.php b/settings/templates/users/part.createuser.php index 6f23d06cfa3..ca36b196ea8 100644 --- a/settings/templates/users/part.createuser.php +++ b/settings/templates/users/part.createuser.php @@ -2,14 +2,14 @@ <form id="newuser" autocomplete="off"> <input id="newusername" type="text" placeholder="<?php p($l->t('Username'))?>" - autocomplete="off" autocapitalize="off" autocorrect="off" /> + autocomplete="off" autocapitalize="none" autocorrect="off" /> <input type="password" id="newuserpassword" placeholder="<?php p($l->t('Password'))?>" - autocomplete="off" autocapitalize="off" autocorrect="off" /> + autocomplete="off" autocapitalize="none" autocorrect="off" /> <input id="newemail" type="text" style="display:none" placeholder="<?php p($l->t('E-Mail'))?>" - autocomplete="off" autocapitalize="off" autocorrect="off" /> + autocomplete="off" autocapitalize="none" autocorrect="off" /> <div class="groups"><div class="groupsListContainer multiselect button" data-placeholder="<?php p($l->t('Groups'))?>"><span class="title groupsList"></span><span class="icon-triangle-s"></span></div></div> <input type="submit" class="button" value="<?php p($l->t('Create'))?>" /> </form> diff --git a/tests/lib/App/ManagerTest.php b/tests/lib/App/ManagerTest.php index e38f72b3d92..8b23168938c 100644 --- a/tests/lib/App/ManagerTest.php +++ b/tests/lib/App/ManagerTest.php @@ -116,16 +116,33 @@ class ManagerTest extends TestCase { public function testEnableApp() { $this->expectClearCache(); - $this->manager->enableApp('test'); - $this->assertEquals('yes', $this->appConfig->getValue('test', 'enabled', 'no')); + // making sure "files_trashbin" is disabled + if ($this->manager->isEnabledForUser('files_trashbin')) { + $this->manager->disableApp('files_trashbin'); + } + $this->manager->enableApp('files_trashbin'); + $this->assertEquals('yes', $this->appConfig->getValue('files_trashbin', 'enabled', 'no')); } public function testDisableApp() { $this->expectClearCache(); - $this->manager->disableApp('test'); - $this->assertEquals('no', $this->appConfig->getValue('test', 'enabled', 'no')); + $this->manager->disableApp('files_trashbin'); + $this->assertEquals('no', $this->appConfig->getValue('files_trashbin', 'enabled', 'no')); } + public function testNotEnableIfNotInstalled() { + try { + $this->manager->enableApp('some_random_name_which_i_hope_is_not_an_app'); + $this->assertFalse(true, 'If this line is reached the expected exception is not thrown.'); + } catch (\Exception $e) { + // excpetion is expected + $this->assertEquals("some_random_name_which_i_hope_is_not_an_app can't be enabled since it is not installed.", $e->getMessage()); + } + $this->assertEquals('no', $this->appConfig->getValue( + 'some_random_name_which_i_hope_is_not_an_app', 'enabled', 'no' + )); + } + public function testEnableAppForGroups() { $groups = array( new Group('group1', array(), null), diff --git a/tests/lib/Files/ViewTest.php b/tests/lib/Files/ViewTest.php index 0aaeb094cd4..3635323e169 100644 --- a/tests/lib/Files/ViewTest.php +++ b/tests/lib/Files/ViewTest.php @@ -1488,6 +1488,8 @@ class ViewTest extends \Test\TestCase { /** * @dataProvider pathRelativeToFilesProviderExceptionCases * @expectedException \InvalidArgumentException + * @expectedExceptionMessage $absolutePath must be relative to "files" + * @param string $path */ public function testGetPathRelativeToFilesWithInvalidArgument($path) { $view = new View(); diff --git a/tests/lib/Group/ManagerTest.php b/tests/lib/Group/ManagerTest.php index 1a7ced5f1ba..23a35024e0a 100644 --- a/tests/lib/Group/ManagerTest.php +++ b/tests/lib/Group/ManagerTest.php @@ -22,18 +22,24 @@ */ namespace Test\Group; +use OC\Group\Database; use OC\User\Manager; +use OCP\ILogger; use OCP\IUser; use OCP\GroupInterface; +use Test\TestCase; -class ManagerTest extends \Test\TestCase { +class ManagerTest extends TestCase { /** @var Manager|\PHPUnit_Framework_MockObject_MockObject $userManager */ protected $userManager; + /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject $userManager */ + protected $logger; protected function setUp() { parent::setUp(); $this->userManager = $this->createMock(Manager::class); + $this->logger = $this->createMock(ILogger::class); } private function getTestUser($userId) { @@ -47,8 +53,12 @@ class ManagerTest extends \Test\TestCase { return $mockUser; } + /** + * @param null|int $implementedActions + * @return \PHPUnit_Framework_MockObject_MockObject + */ private function getTestBackend($implementedActions = null) { - if (is_null($implementedActions)) { + if ($implementedActions === null) { $implementedActions = GroupInterface::ADD_TO_GROUP | GroupInterface::REMOVE_FROM_GOUP | @@ -58,7 +68,7 @@ class ManagerTest extends \Test\TestCase { } // need to declare it this way due to optional methods // thanks to the implementsActions logic - $backend = $this->getMockBuilder(\OCP\GroupInterface::class) + $backend = $this->getMockBuilder(GroupInterface::class) ->disableOriginalConstructor() ->setMethods([ 'getGroupDetails', @@ -91,7 +101,7 @@ class ManagerTest extends \Test\TestCase { ->with('group1') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $group = $manager->get('group1'); @@ -100,7 +110,7 @@ class ManagerTest extends \Test\TestCase { } public function testGetNoBackend() { - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $this->assertNull($manager->get('group1')); } @@ -115,7 +125,7 @@ class ManagerTest extends \Test\TestCase { ->with('group1') ->will($this->returnValue(false)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $this->assertNull($manager->get('group1')); @@ -125,7 +135,7 @@ class ManagerTest extends \Test\TestCase { $backend = new \Test\Util\Group\Dummy(); $backend->createGroup('group1'); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $group = $manager->get('group1'); @@ -152,7 +162,7 @@ class ManagerTest extends \Test\TestCase { ->with('group1') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend1); $manager->addBackend($backend2); @@ -162,9 +172,7 @@ class ManagerTest extends \Test\TestCase { } public function testCreate() { - /** - * @var \PHPUnit_Framework_MockObject_MockObject | \OC\Group\Backend $backend - */ + /**@var \PHPUnit_Framework_MockObject_MockObject|\OC\Group\Backend $backend */ $backendGroupCreated = false; $backend = $this->getTestBackend(); $backend->expects($this->any()) @@ -177,9 +185,9 @@ class ManagerTest extends \Test\TestCase { ->method('createGroup') ->will($this->returnCallback(function () use (&$backendGroupCreated) { $backendGroupCreated = true; - }));; + })); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $group = $manager->createGroup('group1'); @@ -187,9 +195,7 @@ class ManagerTest extends \Test\TestCase { } public function testCreateExists() { - /** - * @var \PHPUnit_Framework_MockObject_MockObject | \OC\Group\Backend $backend - */ + /** @var \PHPUnit_Framework_MockObject_MockObject|\OC\Group\Backend $backend */ $backend = $this->getTestBackend(); $backend->expects($this->any()) ->method('groupExists') @@ -198,7 +204,7 @@ class ManagerTest extends \Test\TestCase { $backend->expects($this->never()) ->method('createGroup'); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $group = $manager->createGroup('group1'); @@ -219,11 +225,11 @@ class ManagerTest extends \Test\TestCase { ->with('group1') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $groups = $manager->search('1'); - $this->assertEquals(1, count($groups)); + $this->assertCount(1, $groups); $group1 = reset($groups); $this->assertEquals('group1', $group1->getGID()); } @@ -253,12 +259,12 @@ class ManagerTest extends \Test\TestCase { ->method('groupExists') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend1); $manager->addBackend($backend2); $groups = $manager->search('1'); - $this->assertEquals(2, count($groups)); + $this->assertCount(2, $groups); $group1 = reset($groups); $group12 = next($groups); $this->assertEquals('group1', $group1->getGID()); @@ -290,18 +296,40 @@ class ManagerTest extends \Test\TestCase { ->method('groupExists') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend1); $manager->addBackend($backend2); $groups = $manager->search('1', 2, 1); - $this->assertEquals(2, count($groups)); + $this->assertCount(2, $groups); $group1 = reset($groups); $group12 = next($groups); $this->assertEquals('group1', $group1->getGID()); $this->assertEquals('group12', $group12->getGID()); } + public function testSearchResultExistsButGroupDoesNot() { + /** @var \PHPUnit_Framework_MockObject_MockObject|\OC\Group\Backend $backend */ + $backend = $this->createMock(Database::class); + $backend->expects($this->once()) + ->method('getGroups') + ->with('1') + ->will($this->returnValue(['group1'])); + $backend->expects($this->once()) + ->method('groupExists') + ->with('group1') + ->will($this->returnValue(false)); + + /** @var \OC\User\Manager $userManager */ + $userManager = $this->createMock(Manager::class); + + $manager = new \OC\Group\Manager($userManager, $this->logger); + $manager->addBackend($backend); + + $groups = $manager->search('1'); + $this->assertEmpty($groups); + } + public function testGetUserGroups() { /** * @var \PHPUnit_Framework_MockObject_MockObject | \OC\Group\Backend $backend @@ -316,18 +344,18 @@ class ManagerTest extends \Test\TestCase { ->with('group1') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $groups = $manager->getUserGroups($this->getTestUser('user1')); - $this->assertEquals(1, count($groups)); + $this->assertCount(1, $groups); $group1 = reset($groups); $this->assertEquals('group1', $group1->getGID()); } public function testGetUserGroupIds() { /** @var \PHPUnit_Framework_MockObject_MockObject|\OC\Group\Manager $manager */ - $manager = $this->getMockBuilder('OC\Group\Manager') + $manager = $this->getMockBuilder(\OC\Group\Manager::class) ->disableOriginalConstructor() ->setMethods(['getUserGroups']) ->getMock(); @@ -338,19 +366,44 @@ class ManagerTest extends \Test\TestCase { 'abc' => 'abc', ]); - /** @var \OC\User\User $user */ - $user = $this->getMockBuilder('OC\User\User') - ->disableOriginalConstructor() - ->getMock(); + /** @var \OC\User\User|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->createMock(IUser::class); $groups = $manager->getUserGroupIds($user); - $this->assertEquals(2, count($groups)); + $this->assertCount(2, $groups); foreach ($groups as $group) { $this->assertInternalType('string', $group); } } + public function testGetUserGroupsWithDeletedGroup() { + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \OC\Group\Backend $backend + */ + $backend = $this->createMock(Database::class); + $backend->expects($this->once()) + ->method('getUserGroups') + ->with('user1') + ->will($this->returnValue(array('group1'))); + $backend->expects($this->any()) + ->method('groupExists') + ->with('group1') + ->will($this->returnValue(false)); + + $manager = new \OC\Group\Manager($this->userManager, $this->logger); + $manager->addBackend($backend); + + /** @var \OC\User\User|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->createMock(IUser::class); + $user->expects($this->atLeastOnce()) + ->method('getUID') + ->willReturn('user1'); + + $groups = $manager->getUserGroups($user); + $this->assertEmpty($groups); + } + public function testInGroup() { /** * @var \PHPUnit_Framework_MockObject_MockObject | \OC\Group\Backend $backend @@ -364,7 +417,7 @@ class ManagerTest extends \Test\TestCase { ->method('groupExists') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $this->assertTrue($manager->isInGroup('user1', 'group1')); @@ -383,7 +436,7 @@ class ManagerTest extends \Test\TestCase { ->method('groupExists') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $this->assertTrue($manager->isAdmin('user1')); @@ -402,7 +455,7 @@ class ManagerTest extends \Test\TestCase { ->method('groupExists') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $this->assertFalse($manager->isAdmin('user1')); @@ -433,12 +486,12 @@ class ManagerTest extends \Test\TestCase { ->method('groupExists') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend1); $manager->addBackend($backend2); $groups = $manager->getUserGroups($this->getTestUser('user1')); - $this->assertEquals(2, count($groups)); + $this->assertCount(2, $groups); $group1 = reset($groups); $group2 = next($groups); $this->assertEquals('group1', $group1->getGID()); @@ -468,14 +521,10 @@ class ManagerTest extends \Test\TestCase { } })); - $userBackend = $this->getMockBuilder('\OC\User\Backend') - ->disableOriginalConstructor() - ->getMock(); - $this->userManager->expects($this->any()) ->method('searchDisplayName') ->with('user3') - ->will($this->returnCallback(function($search, $limit, $offset) use ($userBackend) { + ->will($this->returnCallback(function($search, $limit, $offset) { switch($offset) { case 0 : return ['user3' => $this->getTestUser('user3'), 'user33' => $this->getTestUser('user33')]; @@ -485,7 +534,7 @@ class ManagerTest extends \Test\TestCase { })); $this->userManager->expects($this->any()) ->method('get') - ->will($this->returnCallback(function($uid) use ($userBackend) { + ->will($this->returnCallback(function($uid) { switch($uid) { case 'user1' : return $this->getTestUser('user1'); case 'user2' : return $this->getTestUser('user2'); @@ -496,11 +545,11 @@ class ManagerTest extends \Test\TestCase { } })); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $users = $manager->displayNamesInGroup('testgroup', 'user3'); - $this->assertEquals(1, count($users)); + $this->assertCount(1, $users); $this->assertFalse(isset($users['user1'])); $this->assertFalse(isset($users['user2'])); $this->assertFalse(isset($users['user3'])); @@ -531,14 +580,10 @@ class ManagerTest extends \Test\TestCase { } })); - $userBackend = $this->getMockBuilder('\OC\User\Backend') - ->disableOriginalConstructor() - ->getMock(); - $this->userManager->expects($this->any()) ->method('searchDisplayName') ->with('user3') - ->will($this->returnCallback(function($search, $limit, $offset) use ($userBackend) { + ->will($this->returnCallback(function($search, $limit, $offset) { switch($offset) { case 0 : return ['user3' => $this->getTestUser('user3'), 'user33' => $this->getTestUser('user33')]; @@ -548,7 +593,7 @@ class ManagerTest extends \Test\TestCase { })); $this->userManager->expects($this->any()) ->method('get') - ->will($this->returnCallback(function($uid) use ($userBackend) { + ->will($this->returnCallback(function($uid) { switch($uid) { case 'user1' : return $this->getTestUser('user1'); case 'user2' : return $this->getTestUser('user2'); @@ -560,11 +605,11 @@ class ManagerTest extends \Test\TestCase { } })); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $users = $manager->displayNamesInGroup('testgroup', 'user3', 1); - $this->assertEquals(1, count($users)); + $this->assertCount(1, $users); $this->assertFalse(isset($users['user1'])); $this->assertFalse(isset($users['user2'])); $this->assertFalse(isset($users['user3'])); @@ -596,14 +641,10 @@ class ManagerTest extends \Test\TestCase { } })); - $userBackend = $this->getMockBuilder('\OC\User\Backend') - ->disableOriginalConstructor() - ->getMock(); - $this->userManager->expects($this->any()) ->method('searchDisplayName') ->with('user3') - ->will($this->returnCallback(function($search, $limit, $offset) use ($userBackend) { + ->will($this->returnCallback(function($search, $limit, $offset) { switch($offset) { case 0 : return [ @@ -616,7 +657,7 @@ class ManagerTest extends \Test\TestCase { })); $this->userManager->expects($this->any()) ->method('get') - ->will($this->returnCallback(function($uid) use ($userBackend) { + ->will($this->returnCallback(function($uid) { switch($uid) { case 'user1' : return $this->getTestUser('user1'); case 'user2' : return $this->getTestUser('user2'); @@ -628,11 +669,11 @@ class ManagerTest extends \Test\TestCase { } })); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $users = $manager->displayNamesInGroup('testgroup', 'user3', 1, 1); - $this->assertEquals(1, count($users)); + $this->assertCount(1, $users); $this->assertFalse(isset($users['user1'])); $this->assertFalse(isset($users['user2'])); $this->assertFalse(isset($users['user3'])); @@ -655,13 +696,9 @@ class ManagerTest extends \Test\TestCase { ->with('testgroup', '', -1, 0) ->will($this->returnValue(array('user2', 'user33'))); - $userBackend = $this->getMockBuilder('\OC\User\Backend') - ->disableOriginalConstructor() - ->getMock(); - $this->userManager->expects($this->any()) ->method('get') - ->will($this->returnCallback(function($uid) use ($userBackend) { + ->will($this->returnCallback(function($uid) { switch($uid) { case 'user1' : return $this->getTestUser('user1'); case 'user2' : return $this->getTestUser('user2'); @@ -672,11 +709,11 @@ class ManagerTest extends \Test\TestCase { } })); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $users = $manager->displayNamesInGroup('testgroup', ''); - $this->assertEquals(2, count($users)); + $this->assertCount(2, $users); $this->assertFalse(isset($users['user1'])); $this->assertTrue(isset($users['user2'])); $this->assertFalse(isset($users['user3'])); @@ -698,13 +735,9 @@ class ManagerTest extends \Test\TestCase { ->with('testgroup', '', 1, 0) ->will($this->returnValue(array('user2'))); - $userBackend = $this->getMockBuilder('\OC\User\Backend') - ->disableOriginalConstructor() - ->getMock(); - $this->userManager->expects($this->any()) ->method('get') - ->will($this->returnCallback(function($uid) use ($userBackend) { + ->will($this->returnCallback(function($uid) { switch($uid) { case 'user1' : return $this->getTestUser('user1'); case 'user2' : return $this->getTestUser('user2'); @@ -715,11 +748,11 @@ class ManagerTest extends \Test\TestCase { } })); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $users = $manager->displayNamesInGroup('testgroup', '', 1); - $this->assertEquals(1, count($users)); + $this->assertCount(1, $users); $this->assertFalse(isset($users['user1'])); $this->assertTrue(isset($users['user2'])); $this->assertFalse(isset($users['user3'])); @@ -741,13 +774,9 @@ class ManagerTest extends \Test\TestCase { ->with('testgroup', '', 1, 1) ->will($this->returnValue(array('user33'))); - $userBackend = $this->getMockBuilder('\OC\User\Backend') - ->disableOriginalConstructor() - ->getMock(); - $this->userManager->expects($this->any()) ->method('get') - ->will($this->returnCallback(function($uid) use ($userBackend) { + ->will($this->returnCallback(function($uid) { switch($uid) { case 'user1' : return $this->getTestUser('user1'); case 'user2' : return $this->getTestUser('user2'); @@ -758,11 +787,11 @@ class ManagerTest extends \Test\TestCase { } })); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $users = $manager->displayNamesInGroup('testgroup', '', 1, 1); - $this->assertEquals(1, count($users)); + $this->assertCount(1, $users); $this->assertFalse(isset($users['user1'])); $this->assertFalse(isset($users['user2'])); $this->assertFalse(isset($users['user3'])); @@ -786,7 +815,7 @@ class ManagerTest extends \Test\TestCase { ->with('group1') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); // prime cache @@ -797,11 +826,11 @@ class ManagerTest extends \Test\TestCase { // add user $group = $manager->get('group1'); $group->addUser($user1); - $expectedGroups = ['group1']; + $expectedGroups[] = 'group1'; // check result $groups = $manager->getUserGroups($user1); - $this->assertEquals(1, count($groups)); + $this->assertCount(1, $groups); $group1 = reset($groups); $this->assertEquals('group1', $group1->getGID()); } @@ -829,13 +858,13 @@ class ManagerTest extends \Test\TestCase { ->method('removeFromGroup') ->will($this->returnValue(true)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); // prime cache $user1 = $this->getTestUser('user1'); $groups = $manager->getUserGroups($user1); - $this->assertEquals(1, count($groups)); + $this->assertCount(1, $groups); $group1 = reset($groups); $this->assertEquals('group1', $group1->getGID()); @@ -859,7 +888,7 @@ class ManagerTest extends \Test\TestCase { ->with('user1') ->will($this->returnValue(null)); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); $groups = $manager->getUserIdGroups('user1'); @@ -885,7 +914,7 @@ class ManagerTest extends \Test\TestCase { ['group2', ['gid' => 'group2']], ])); - $manager = new \OC\Group\Manager($this->userManager); + $manager = new \OC\Group\Manager($this->userManager, $this->logger); $manager->addBackend($backend); // group with display name diff --git a/tests/lib/Preview/GeneratorTest.php b/tests/lib/Preview/GeneratorTest.php index ddb24cdb3ee..50d46ae932d 100644 --- a/tests/lib/Preview/GeneratorTest.php +++ b/tests/lib/Preview/GeneratorTest.php @@ -399,6 +399,10 @@ class GeneratorTest extends \Test\TestCase { ); $result = $this->generator->getPreview($file, $reqX, $reqY, $crop, $mode); - $this->assertSame($preview, $result); + if ($expectedX === $maxX && $expectedY === $maxY) { + $this->assertSame($maxPreview, $result); + } else { + $this->assertSame($preview, $result); + } } } diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php index 5870da8d218..a1e78313558 100644 --- a/tests/lib/Share20/DefaultShareProviderTest.php +++ b/tests/lib/Share20/DefaultShareProviderTest.php @@ -1524,6 +1524,48 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->provider->deleteFromSelf($share, 'user2'); } + /** + * @expectedException \OC\Share20\Exception\ProviderException + * @expectedExceptionMessage Group "group" does not exist + */ + public function testDeleteFromSelfGroupDoesNotExist() { + $qb = $this->dbConn->getQueryBuilder(); + $stmt = $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_GROUP), + 'share_with' => $qb->expr()->literal('group'), + 'uid_owner' => $qb->expr()->literal('user1'), + 'uid_initiator' => $qb->expr()->literal('user1'), + 'item_type' => $qb->expr()->literal('file'), + 'file_source' => $qb->expr()->literal(1), + 'file_target' => $qb->expr()->literal('myTarget1'), + 'permissions' => $qb->expr()->literal(2) + ])->execute(); + $this->assertEquals(1, $stmt); + $id = $qb->getLastInsertId(); + + $user1 = $this->getMock('\OCP\IUser'); + $user1->method('getUID')->willReturn('user1'); + $user2 = $this->getMock('\OCP\IUser'); + $user2->method('getUID')->willReturn('user2'); + $this->userManager->method('get')->will($this->returnValueMap([ + ['user1', $user1], + ['user2', $user2], + ])); + + $this->groupManager->method('get')->with('group')->willReturn(null); + + $file = $this->getMock('\OCP\Files\File'); + $file->method('getId')->willReturn(1); + + $this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf()); + $this->rootFolder->method('getById')->with(1)->willReturn([$file]); + + $share = $this->provider->getShareById($id); + + $this->provider->deleteFromSelf($share, 'user2'); + } + public function testDeleteFromSelfUser() { $qb = $this->dbConn->getQueryBuilder(); $stmt = $qb->insert('share') diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php index 448373a8368..2a7df0df50f 100644 --- a/tests/lib/Share20/ManagerTest.php +++ b/tests/lib/Share20/ManagerTest.php @@ -1139,6 +1139,39 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'userCreateChecks', [$share]); } + public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup() { + $share = $this->manager->newShare(); + + $sharedWith = $this->getMock('\OCP\IUser'); + $sharedWith->method('getUID')->willReturn('sharedWith'); + + $this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith); + + $path = $this->getMock('\OCP\Files\Node'); + + $share->setSharedWith('sharedWith') + ->setNode($path) + ->setShareOwner('shareOwner') + ->setProviderId('foo') + ->setId('bar'); + + $share2 = $this->manager->newShare(); + $share2->setShareType(\OCP\Share::SHARE_TYPE_GROUP) + ->setShareOwner('shareOwner2') + ->setProviderId('foo') + ->setId('baz') + ->setSharedWith('group'); + + $this->groupManager->method('get')->with('group')->willReturn(null); + + $this->defaultProvider + ->method('getSharesByPath') + ->with($path) + ->willReturn([$share2]); + + $this->assertNull($this->invokePrivate($this->manager, 'userCreateChecks', [$share])); + } + public function testUserCreateChecksIdenticalPathNotSharedWithUser() { $share = $this->manager->newShare(); $sharedWith = $this->createMock(IUser::class); @@ -1216,6 +1249,29 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'groupCreateChecks', [$share]); } + /** + * @expectedException Exception + * @expectedExceptionMessage Only sharing within your own groups is allowed + */ + public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup() { + $share = $this->manager->newShare(); + + $user = $this->getMock('\OCP\IUser'); + $share->setSharedBy('user')->setSharedWith('group'); + + $this->groupManager->method('get')->with('group')->willReturn(null); + $this->userManager->method('get')->with('user')->willReturn($user); + + $this->config + ->method('getAppValue') + ->will($this->returnValueMap([ + ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], + ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'], + ])); + + $this->assertNull($this->invokePrivate($this->manager, 'groupCreateChecks', [$share])); + } + public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup() { $share = $this->manager->newShare(); @@ -2666,6 +2722,23 @@ class ManagerTest extends \Test\TestCase { $this->manager->moveShare($share, 'recipient'); } + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Group "shareWith" does not exist + */ + public function testMoveShareGroupNull() { + $share = $this->manager->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_GROUP); + $share->setSharedWith('shareWith'); + + $recipient = $this->getMock('\OCP\IUser'); + + $this->groupManager->method('get')->with('shareWith')->willReturn(null); + $this->userManager->method('get')->with('recipient')->willReturn($recipient); + + $this->manager->moveShare($share, 'recipient'); + } + public function testMoveShareGroup() { $share = $this->manager->newShare(); $share->setShareType(\OCP\Share::SHARE_TYPE_GROUP) diff --git a/tests/lib/SystemTag/SystemTagManagerTest.php b/tests/lib/SystemTag/SystemTagManagerTest.php index e697e373465..61fac99ca6c 100644 --- a/tests/lib/SystemTag/SystemTagManagerTest.php +++ b/tests/lib/SystemTag/SystemTagManagerTest.php @@ -517,6 +517,15 @@ class SystemTagManagerTest extends TestCase { } /** + * empty groupIds should be ignored + */ + public function testEmptyTagGroup() { + $tag1 = $this->tagManager->createTag('tag1', true, false); + $this->tagManager->setTagGroups($tag1, ['']); + $this->assertEquals([], $this->tagManager->getTagGroups($tag1)); + } + + /** * @param ISystemTag $tag1 * @param ISystemTag $tag2 */ diff --git a/tests/lib/User/DatabaseTest.php b/tests/lib/User/DatabaseTest.php index d7e4b9256cb..0e6900651cd 100644 --- a/tests/lib/User/DatabaseTest.php +++ b/tests/lib/User/DatabaseTest.php @@ -87,7 +87,7 @@ class DatabaseTest extends Backend { $this->eventDispatcher->expects($this->once())->method('dispatch') ->willReturnCallback( function ($eventName, GenericEvent $event) { - $this->assertSame('OCP\PasswordPolicy::validate', $eventName); + $this->assertSame('OCP\PasswordPolicy::validate', $eventName); $this->assertSame('newpass', $event->getSubject()); throw new HintException('password change failed', 'password change failed'); } @@ -96,4 +96,21 @@ class DatabaseTest extends Backend { $this->backend->setPassword($user, 'newpass'); $this->assertSame($user, $this->backend->checkPassword($user, 'newpass')); } + + public function testCreateUserInvalidatesCache() { + $user1 = $this->getUniqueID('test_'); + $this->assertFalse($this->backend->userExists($user1)); + $this->backend->createUser($user1, 'pw'); + $this->assertTrue($this->backend->userExists($user1)); + } + + public function testDeleteUserInvalidatesCache() { + $user1 = $this->getUniqueID('test_'); + $this->backend->createUser($user1, 'pw'); + $this->assertTrue($this->backend->userExists($user1)); + $this->backend->deleteUser($user1); + $this->assertFalse($this->backend->userExists($user1)); + $this->backend->createUser($user1, 'pw2'); + $this->assertTrue($this->backend->userExists($user1)); + } } |