mirror of
https://github.com/nextcloud/server.git
synced 2026-06-13 18:50:47 -04:00
commit
980d900b88
14 changed files with 172 additions and 58 deletions
|
|
@ -32,6 +32,7 @@ use OCA\Dav\Migration\AddressBookAdapter;
|
|||
use OCA\Dav\Migration\CalendarAdapter;
|
||||
use OCA\Dav\Migration\MigrateAddressbooks;
|
||||
use OCA\Dav\Migration\MigrateCalendars;
|
||||
use OCA\Dav\Migration\NothingToDoException;
|
||||
use \OCP\AppFramework\App;
|
||||
use OCP\AppFramework\IAppContainer;
|
||||
use OCP\Contacts\IManager;
|
||||
|
|
@ -190,6 +191,8 @@ class Application extends App {
|
|||
/** @var IUser $user */
|
||||
$migration->migrateForUser($user->getUID());
|
||||
});
|
||||
} catch (NothingToDoException $ex) {
|
||||
// nothing to do, yay!
|
||||
} catch (\Exception $ex) {
|
||||
$this->getContainer()->getServer()->getLogger()->logException($ex);
|
||||
}
|
||||
|
|
@ -206,6 +209,8 @@ class Application extends App {
|
|||
/** @var IUser $user */
|
||||
$migration->migrateForUser($user->getUID());
|
||||
});
|
||||
} catch (NothingToDoException $ex) {
|
||||
// nothing to do, yay!
|
||||
} catch (\Exception $ex) {
|
||||
$this->getContainer()->getServer()->getLogger()->logException($ex);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class AddressBookAdapter {
|
|||
|
||||
public function setup() {
|
||||
if (!$this->dbConnection->tableExists($this->sourceBookTable)) {
|
||||
throw new \DomainException('Contacts tables are missing. Nothing to do.');
|
||||
throw new NothingToDoException('Contacts tables are missing');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class CalendarAdapter {
|
|||
|
||||
public function setup() {
|
||||
if (!$this->dbConnection->tableExists($this->sourceCalendarTable)) {
|
||||
throw new \DomainException('Calendar tables are missing. Nothing to do.');
|
||||
throw new NothingToDoException('Calendar tables are missing');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
27
apps/dav/lib/migration/nothingtodoexception.php
Normal file
27
apps/dav/lib/migration/nothingtodoexception.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Robin McCorkell <robin@mccorkell.me.uk>
|
||||
*
|
||||
* @copyright Copyright (c) 2016, 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 OCA\Dav\Migration;
|
||||
|
||||
/**
|
||||
* Exception if no migration needs to be done
|
||||
*/
|
||||
class NothingToDoException extends \DomainException {}
|
||||
|
|
@ -1327,13 +1327,27 @@
|
|||
return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
|
||||
},
|
||||
|
||||
_isValidPath: function(path) {
|
||||
var sections = path.split('/');
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i] === '..') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the current directory name and updates the breadcrumb.
|
||||
* @param targetDir directory to display
|
||||
* @param changeUrl true to also update the URL, false otherwise (default)
|
||||
*/
|
||||
_setCurrentDir: function(targetDir, changeUrl) {
|
||||
targetDir = targetDir.replace(/\\/g, '/').replace(/\/\.\.\//g, '/');
|
||||
targetDir = targetDir.replace(/\\/g, '/');
|
||||
if (!this._isValidPath(targetDir)) {
|
||||
targetDir = '/';
|
||||
changeUrl = true;
|
||||
}
|
||||
var previousDir = this.getCurrentDirectory(),
|
||||
baseDir = OC.basename(targetDir);
|
||||
|
||||
|
|
|
|||
|
|
@ -1323,13 +1323,32 @@ describe('OCA.Files.FileList tests', function() {
|
|||
fileList.changeDirectory('/another\\subdir');
|
||||
expect(fileList.getCurrentDirectory()).toEqual('/another/subdir');
|
||||
});
|
||||
it('converts backslashes to slashes and removes traversals when calling changeDirectory()', function() {
|
||||
fileList.changeDirectory('/another\\subdir/../foo\\../bar\\..\\file/..\\folder/../');
|
||||
expect(fileList.getCurrentDirectory()).toEqual('/another/subdir/foo/bar/file/folder/');
|
||||
it('switches to root dir when current directory is invalid', function() {
|
||||
_.each([
|
||||
'..',
|
||||
'/..',
|
||||
'../',
|
||||
'/../',
|
||||
'/../abc',
|
||||
'/abc/..',
|
||||
'/abc/../',
|
||||
'/../abc/',
|
||||
'/another\\subdir/../foo\\../bar\\..\\file/..\\folder/../'
|
||||
], function(path) {
|
||||
fileList.changeDirectory(path);
|
||||
expect(fileList.getCurrentDirectory()).toEqual('/');
|
||||
});
|
||||
});
|
||||
it('does not convert folders with a ".." in the name', function() {
|
||||
fileList.changeDirectory('/abc../def');
|
||||
expect(fileList.getCurrentDirectory()).toEqual('/abc../def');
|
||||
it('allows paths with dotdot at the beginning or end', function() {
|
||||
_.each([
|
||||
'/..abc',
|
||||
'/def..',
|
||||
'/...',
|
||||
'/abc../def'
|
||||
], function(path) {
|
||||
fileList.changeDirectory(path);
|
||||
expect(fileList.getCurrentDirectory()).toEqual(path);
|
||||
});
|
||||
});
|
||||
it('switches to root dir when current directory does not exist', function() {
|
||||
fileList.changeDirectory('/unexist');
|
||||
|
|
|
|||
|
|
@ -644,7 +644,7 @@ class Storage {
|
|||
//distance between two version too small, mark to delete
|
||||
$toDelete[$key] = $version['path'] . '.v' . $version['version'];
|
||||
$size += $version['size'];
|
||||
\OCP\Util::writeLog('files_versions', 'Mark to expire '. $version['path'] .' next version should be ' . $nextVersion . " or smaller. (prevTimestamp: " . $prevTimestamp . "; step: " . $step, \OCP\Util::DEBUG);
|
||||
\OCP\Util::writeLog('files_versions', 'Mark to expire '. $version['path'] .' next version should be ' . $nextVersion . " or smaller. (prevTimestamp: " . $prevTimestamp . "; step: " . $step, \OCP\Util::INFO);
|
||||
} else {
|
||||
$nextVersion = $version['version'] - $step;
|
||||
$prevTimestamp = $version['version'];
|
||||
|
|
@ -765,7 +765,7 @@ class Storage {
|
|||
self::deleteVersion($versionsFileview, $path);
|
||||
\OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED));
|
||||
unset($allVersions[$key]); // update array with the versions we keep
|
||||
\OCP\Util::writeLog('files_versions', "Expire: " . $path, \OCP\Util::DEBUG);
|
||||
\OCP\Util::writeLog('files_versions', "Expire: " . $path, \OCP\Util::INFO);
|
||||
}
|
||||
|
||||
// Check if enough space is available after versions are rearranged.
|
||||
|
|
@ -781,7 +781,7 @@ class Storage {
|
|||
\OC_Hook::emit('\OCP\Versions', 'preDelete', array('path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED));
|
||||
self::deleteVersion($versionsFileview, $version['path'] . '.v' . $version['version']);
|
||||
\OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED));
|
||||
\OCP\Util::writeLog('files_versions', 'running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'] , \OCP\Util::DEBUG);
|
||||
\OCP\Util::writeLog('files_versions', 'running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'] , \OCP\Util::INFO);
|
||||
$versionsSize -= $version['size'];
|
||||
$availableSpace += $version['size'];
|
||||
next($allVersions);
|
||||
|
|
|
|||
|
|
@ -228,6 +228,11 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
|
|||
return false;
|
||||
}
|
||||
$newDn = $this->access->getUserDnByUuid($uuid);
|
||||
//check if renamed user is still valid by reapplying the ldap filter
|
||||
if(!is_array($this->access->readAttribute($newDn, '', $this->access->connection->ldapUserFilter))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,21 @@ Feature: sharing
|
|||
Then the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
|
||||
Scenario: Creating a new share with user who already received a share through their group
|
||||
Given As an "admin"
|
||||
And user "user0" exists
|
||||
And user "user1" exists
|
||||
And group "sharing-group" exists
|
||||
And user "user1" belongs to group "sharing-group"
|
||||
And file "welcome.txt" of user "user0" is shared with group "sharing-group"
|
||||
And As an "user0"
|
||||
Then sending "POST" to "/apps/files_sharing/api/v1/shares" with
|
||||
| path | welcome.txt |
|
||||
| shareWith | user1 |
|
||||
| shareType | 0 |
|
||||
Then the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
|
||||
Scenario: Creating a new public share
|
||||
Given user "user0" exists
|
||||
And As an "user0"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Björn Schießle <schiessle@owncloud.com>
|
||||
* @author Björn Schießle <bjoern@schiessle.org>
|
||||
* @author Joas Schilling <nickvergessen@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
|
|
@ -111,7 +111,8 @@ class DecryptAll extends Command {
|
|||
$this->addArgument(
|
||||
'user',
|
||||
InputArgument::OPTIONAL,
|
||||
'user for which you want to decrypt all files (optional)'
|
||||
'user for which you want to decrypt all files (optional)',
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -127,8 +128,15 @@ class DecryptAll extends Command {
|
|||
return;
|
||||
}
|
||||
|
||||
$uid = $input->getArgument('user');
|
||||
if ($uid === '') {
|
||||
$message = 'your Nextcloud';
|
||||
} else {
|
||||
$message = "$uid's account";
|
||||
}
|
||||
|
||||
$output->writeln("\n");
|
||||
$output->writeln('You are about to start to decrypt all files stored in your Nextcloud.');
|
||||
$output->writeln("You are about to start to decrypt all files stored in $message.");
|
||||
$output->writeln('It will depend on the encryption module and your setup if this is possible.');
|
||||
$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!');
|
||||
|
|
@ -140,6 +148,7 @@ class DecryptAll extends Command {
|
|||
$result = $this->decryptAll->decryptAll($input, $output, $user);
|
||||
if ($result === false) {
|
||||
$output->writeln(' aborted.');
|
||||
$output->writeln('Server side encryption remains enabled');
|
||||
$this->config->setAppValue('core', 'encryption_enabled', 'yes');
|
||||
}
|
||||
$this->resetSingleUserAndTrashbin();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Björn Schießle <schiessle@owncloud.com>
|
||||
* @author Björn Schießle <bjoern@schiessle.org>
|
||||
*
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
|
|
@ -80,7 +80,7 @@ class DecryptAll {
|
|||
$this->input = $input;
|
||||
$this->output = $output;
|
||||
|
||||
if (!empty($user) && $this->userManager->userExists($user) === false) {
|
||||
if ($user !== '' && $this->userManager->userExists($user) === false) {
|
||||
$this->output->writeln('User "' . $user . '" does not exist. Please check the username and try again');
|
||||
return false;
|
||||
}
|
||||
|
|
@ -133,6 +133,7 @@ class DecryptAll {
|
|||
|
||||
/**
|
||||
* iterate over all user and encrypt their files
|
||||
*
|
||||
* @param string $user which users files should be decrypted, default = all users
|
||||
*/
|
||||
protected function decryptAllUsersFiles($user = '') {
|
||||
|
|
@ -140,7 +141,7 @@ class DecryptAll {
|
|||
$this->output->writeln("\n");
|
||||
|
||||
$userList = [];
|
||||
if (empty($user)) {
|
||||
if ($user === '') {
|
||||
|
||||
$fetchUsersProgress = new ProgressBar($this->output);
|
||||
$fetchUsersProgress->setFormat(" %message% \n [%bar%]");
|
||||
|
|
@ -200,9 +201,9 @@ class DecryptAll {
|
|||
|
||||
$this->setupUserFS($uid);
|
||||
$directories = array();
|
||||
$directories[] = '/' . $uid . '/files';
|
||||
$directories[] = '/' . $uid . '/files';
|
||||
|
||||
while($root = array_pop($directories)) {
|
||||
while ($root = array_pop($directories)) {
|
||||
$content = $this->rootView->getDirectoryContent($root);
|
||||
foreach ($content as $file) {
|
||||
$path = $root . '/' . $file['name'];
|
||||
|
|
@ -213,9 +214,14 @@ class DecryptAll {
|
|||
try {
|
||||
$progress->setMessage("decrypt files for user $userCount: $path");
|
||||
$progress->advance();
|
||||
if ($this->decryptFile($path) === false) {
|
||||
if ($file->isEncrypted() === false) {
|
||||
$progress->setMessage("decrypt files for user $userCount: $path (already decrypted)");
|
||||
$progress->advance();
|
||||
} else {
|
||||
if ($this->decryptFile($path) === false) {
|
||||
$progress->setMessage("decrypt files for user $userCount: $path (already decrypted)");
|
||||
$progress->advance();
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
if (isset($this->failed[$uid])) {
|
||||
|
|
|
|||
|
|
@ -221,7 +221,9 @@ class OC_Helper {
|
|||
|
||||
foreach ($files as $fileInfo) {
|
||||
/** @var SplFileInfo $fileInfo */
|
||||
if ($fileInfo->isDir()) {
|
||||
if ($fileInfo->isLink()) {
|
||||
unlink($fileInfo->getPathname());
|
||||
} else if ($fileInfo->isDir()) {
|
||||
rmdir($fileInfo->getRealPath());
|
||||
} else {
|
||||
unlink($fileInfo->getRealPath());
|
||||
|
|
|
|||
|
|
@ -507,6 +507,24 @@ class Manager implements IManager {
|
|||
|
||||
$this->generalCreateChecks($share);
|
||||
|
||||
// Verify if there are any issues with the path
|
||||
$this->pathCreateChecks($share->getNode());
|
||||
|
||||
/*
|
||||
* On creation of a share the owner is always the owner of the path
|
||||
* Except for mounted federated shares.
|
||||
*/
|
||||
$storage = $share->getNode()->getStorage();
|
||||
if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
|
||||
$parent = $share->getNode()->getParent();
|
||||
while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
|
||||
$parent = $parent->getParent();
|
||||
}
|
||||
$share->setShareOwner($parent->getOwner()->getUID());
|
||||
} else {
|
||||
$share->setShareOwner($share->getNode()->getOwner()->getUID());
|
||||
}
|
||||
|
||||
//Verify share type
|
||||
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
|
||||
$this->userCreateChecks($share);
|
||||
|
|
@ -540,24 +558,6 @@ class Manager implements IManager {
|
|||
}
|
||||
}
|
||||
|
||||
// Verify if there are any issues with the path
|
||||
$this->pathCreateChecks($share->getNode());
|
||||
|
||||
/*
|
||||
* On creation of a share the owner is always the owner of the path
|
||||
* Except for mounted federated shares.
|
||||
*/
|
||||
$storage = $share->getNode()->getStorage();
|
||||
if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
|
||||
$parent = $share->getNode()->getParent();
|
||||
while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
|
||||
$parent = $parent->getParent();
|
||||
}
|
||||
$share->setShareOwner($parent->getOwner()->getUID());
|
||||
} else {
|
||||
$share->setShareOwner($share->getNode()->getOwner()->getUID());
|
||||
}
|
||||
|
||||
// Cannot share with the owner
|
||||
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
|
||||
$share->getSharedWith() === $share->getShareOwner()) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ namespace Test\Encryption;
|
|||
use OC\Encryption\DecryptAll;
|
||||
use OC\Encryption\Exceptions\DecryptionFailedException;
|
||||
use OC\Encryption\Manager;
|
||||
use OC\Files\FileInfo;
|
||||
use OC\Files\View;
|
||||
use OCP\IUserManager;
|
||||
use Test\TestCase;
|
||||
|
|
@ -85,13 +86,25 @@ class DecryptAllTest extends TestCase {
|
|||
$this->invokePrivate($this->instance, 'output', [$this->outputInterface]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTrueFalse
|
||||
* @param bool $prepareResult
|
||||
*/
|
||||
public function testDecryptAll($prepareResult, $user) {
|
||||
public function dataDecryptAll() {
|
||||
return [
|
||||
[true, 'user1', true],
|
||||
[false, 'user1', true],
|
||||
[true, '0', true],
|
||||
[false, '0', true],
|
||||
[true, '', false],
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($user)) {
|
||||
/**
|
||||
* @dataProvider dataDecryptAll
|
||||
* @param bool $prepareResult
|
||||
* @param string $user
|
||||
* @param bool $userExistsChecked
|
||||
*/
|
||||
public function testDecryptAll($prepareResult, $user, $userExistsChecked) {
|
||||
|
||||
if ($userExistsChecked) {
|
||||
$this->userManager->expects($this->once())->method('userExists')->willReturn(true);
|
||||
} else {
|
||||
$this->userManager->expects($this->never())->method('userExists');
|
||||
|
|
@ -124,15 +137,6 @@ class DecryptAllTest extends TestCase {
|
|||
$instance->decryptAll($this->inputInterface, $this->outputInterface, $user);
|
||||
}
|
||||
|
||||
public function dataTrueFalse() {
|
||||
return [
|
||||
[true, 'user1'],
|
||||
[false, 'user1'],
|
||||
[true, ''],
|
||||
[true, null]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* test decrypt all call with a user who doesn't exists
|
||||
*/
|
||||
|
|
@ -146,8 +150,16 @@ class DecryptAllTest extends TestCase {
|
|||
);
|
||||
}
|
||||
|
||||
public function dataTrueFalse() {
|
||||
return [
|
||||
[true],
|
||||
[false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTrueFalse
|
||||
* @param bool $success
|
||||
*/
|
||||
public function testPrepareEncryptionModules($success) {
|
||||
|
||||
|
|
@ -242,15 +254,15 @@ class DecryptAllTest extends TestCase {
|
|||
$this->view->expects($this->at(0))->method('getDirectoryContent')
|
||||
->with('/user1/files')->willReturn(
|
||||
[
|
||||
['name' => 'foo', 'type'=>'dir'],
|
||||
['name' => 'bar', 'type'=>'file'],
|
||||
new FileInfo('path', null, 'intPath', ['name' => 'foo', 'type'=>'dir'], null),
|
||||
new FileInfo('path', null, 'intPath', ['name' => 'bar', 'type'=>'file', 'encrypted'=>true], null)
|
||||
]
|
||||
);
|
||||
|
||||
$this->view->expects($this->at(3))->method('getDirectoryContent')
|
||||
->with('/user1/files/foo')->willReturn(
|
||||
[
|
||||
['name' => 'subfile', 'type'=>'file']
|
||||
new FileInfo('path', null, 'intPath', ['name' => 'subfile', 'type'=>'file', 'encrypted'=>true], null)
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue