summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/comments/activity/extension.php11
-rw-r--r--apps/dav/lib/connector/sabre/filesplugin.php22
-rw-r--r--apps/dav/lib/connector/sabre/serverfactory.php11
-rw-r--r--apps/dav/lib/hookmanager.php36
-rw-r--r--apps/dav/lib/server.php11
-rw-r--r--apps/dav/tests/unit/connector/sabre/filesplugin.php59
-rw-r--r--apps/dav/tests/unit/connector/sabre/filesreportplugin.php10
-rw-r--r--apps/dav/tests/unit/dav/HookManagerTest.php71
-rw-r--r--apps/encryption/hooks/userhooks.php11
-rw-r--r--apps/encryption/lib/crypto/encryption.php13
-rw-r--r--apps/encryption/lib/keymanager.php1
-rw-r--r--apps/encryption/tests/hooks/UserHooksTest.php47
-rw-r--r--apps/files/appinfo/routes.php5
-rw-r--r--apps/files/command/transferownership.php6
-rw-r--r--apps/files/controller/apicontroller.php12
-rw-r--r--apps/files/controller/viewcontroller.php3
-rw-r--r--apps/files/css/files.css5
-rw-r--r--apps/files/js/app.js51
-rw-r--r--apps/files/js/filelist.js46
-rw-r--r--apps/files/templates/appnavigation.php10
-rw-r--r--apps/files/templates/index.php1
-rw-r--r--apps/files/tests/controller/ViewControllerTest.php6
-rw-r--r--apps/files/tests/controller/apicontrollertest.php14
-rw-r--r--apps/files_sharing/js/app.js9
-rw-r--r--apps/files_sharing/tests/testcase.php2
-rw-r--r--apps/files_trashbin/js/app.js3
-rw-r--r--apps/systemtags/js/app.js3
27 files changed, 423 insertions, 56 deletions
diff --git a/apps/comments/activity/extension.php b/apps/comments/activity/extension.php
index 6bf7cae5882..ef800e88abc 100644
--- a/apps/comments/activity/extension.php
+++ b/apps/comments/activity/extension.php
@@ -80,7 +80,10 @@ class Extension implements IExtension {
$l = $this->getL10N($languageCode);
return array(
- self::APP_NAME => (string) $l->t('<strong>Comments</strong> for files'),
+ self::APP_NAME => [
+ 'desc' => (string) $l->t('<strong>Comments</strong> for files <em>(always listed in stream)</em>'),
+ 'methods' => [self::METHOD_MAIL], // self::METHOD_STREAM is forced true by the default value
+ ],
);
}
@@ -274,7 +277,11 @@ class Extension implements IExtension {
*/
public function filterNotificationTypes($types, $filter) {
if ($filter === self::APP_NAME) {
- return array_intersect($types, [self::APP_NAME]);
+ return [self::APP_NAME];
+ }
+ if (in_array($filter, ['all', 'by', 'self', 'filter'])) {
+ $types[] = self::APP_NAME;
+ return $types;
}
return false;
}
diff --git a/apps/dav/lib/connector/sabre/filesplugin.php b/apps/dav/lib/connector/sabre/filesplugin.php
index 686d0863f91..dd4670da5fa 100644
--- a/apps/dav/lib/connector/sabre/filesplugin.php
+++ b/apps/dav/lib/connector/sabre/filesplugin.php
@@ -39,6 +39,7 @@ use Sabre\DAV\Tree;
use \Sabre\HTTP\RequestInterface;
use \Sabre\HTTP\ResponseInterface;
use OCP\Files\StorageNotAvailableException;
+use OCP\IConfig;
class FilesPlugin extends ServerPlugin {
@@ -55,6 +56,7 @@ class FilesPlugin extends ServerPlugin {
const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
+ const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
/**
* Reference to main server object
@@ -87,6 +89,11 @@ class FilesPlugin extends ServerPlugin {
private $downloadAttachment;
/**
+ * @var IConfig
+ */
+ private $config;
+
+ /**
* @param Tree $tree
* @param View $view
* @param bool $isPublic
@@ -94,10 +101,12 @@ class FilesPlugin extends ServerPlugin {
*/
public function __construct(Tree $tree,
View $view,
+ IConfig $config,
$isPublic = false,
$downloadAttachment = true) {
$this->tree = $tree;
$this->fileView = $view;
+ $this->config = $config;
$this->isPublic = $isPublic;
$this->downloadAttachment = $downloadAttachment;
}
@@ -125,6 +134,7 @@ class FilesPlugin extends ServerPlugin {
$server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
$server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
$server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
+ $server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
// normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
$allowedProperties = ['{DAV:}getetag'];
@@ -272,6 +282,18 @@ class FilesPlugin extends ServerPlugin {
$displayName = $owner->getDisplayName();
return $displayName;
});
+
+ $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
+ if ($node->getPath() === '/') {
+ return $this->config->getSystemValue('data-fingerprint', '');
+ }
+ });
+ }
+
+ if ($node instanceof \OCA\DAV\Files\FilesHome) {
+ $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
+ return $this->config->getSystemValue('data-fingerprint', '');
+ });
}
if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
diff --git a/apps/dav/lib/connector/sabre/serverfactory.php b/apps/dav/lib/connector/sabre/serverfactory.php
index cab7a85d19f..5853370778d 100644
--- a/apps/dav/lib/connector/sabre/serverfactory.php
+++ b/apps/dav/lib/connector/sabre/serverfactory.php
@@ -137,8 +137,15 @@ class ServerFactory {
}
$objectTree->init($root, $view, $this->mountManager);
- $server->addPlugin(new \OCA\DAV\Connector\Sabre\FilesPlugin($objectTree, $view, false,
- !$this->config->getSystemValue('debug', false)));
+ $server->addPlugin(
+ new \OCA\DAV\Connector\Sabre\FilesPlugin(
+ $objectTree,
+ $view,
+ $this->config,
+ false,
+ !$this->config->getSystemValue('debug', false)
+ )
+ );
$server->addPlugin(new \OCA\DAV\Connector\Sabre\QuotaPlugin($view));
if($this->userSession->isLoggedIn()) {
diff --git a/apps/dav/lib/hookmanager.php b/apps/dav/lib/hookmanager.php
index 4a4704ff2a2..687e6718db3 100644
--- a/apps/dav/lib/hookmanager.php
+++ b/apps/dav/lib/hookmanager.php
@@ -100,26 +100,26 @@ class HookManager {
public function postLogin($params) {
$user = $this->userManager->get($params['uid']);
-
- $principal = 'principals/users/' . $user->getUID();
- $calendars = $this->calDav->getCalendarsForUser($principal);
- if (empty($calendars)) {
- try {
- $this->calDav->createCalendar($principal, 'personal', [
- 'displayname' => 'Personal']);
- } catch (\Exception $ex) {
- \OC::$server->getLogger()->logException($ex);
+ if (!is_null($user)) {
+ $principal = 'principals/users/' . $user->getUID();
+ $calendars = $this->calDav->getCalendarsForUser($principal);
+ if (empty($calendars)) {
+ try {
+ $this->calDav->createCalendar($principal, 'personal', [
+ '{DAV:}displayname' => 'Personal']);
+ } catch (\Exception $ex) {
+ \OC::$server->getLogger()->logException($ex);
+ }
}
- }
- $books = $this->cardDav->getAddressBooksForUser($principal);
- if (empty($books)) {
- try {
- $this->cardDav->createAddressBook($principal, 'contacts', [
- 'displayname' => 'Contacts']);
- } catch (\Exception $ex) {
- \OC::$server->getLogger()->logException($ex);
+ $books = $this->cardDav->getAddressBooksForUser($principal);
+ if (empty($books)) {
+ try {
+ $this->cardDav->createAddressBook($principal, 'contacts', [
+ '{DAV:}displayname' => 'Contacts']);
+ } catch (\Exception $ex) {
+ \OC::$server->getLogger()->logException($ex);
+ }
}
}
-
}
}
diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php
index e6668556448..73e24c9a292 100644
--- a/apps/dav/lib/server.php
+++ b/apps/dav/lib/server.php
@@ -132,8 +132,15 @@ class Server {
$user = \OC::$server->getUserSession()->getUser();
if (!is_null($user)) {
$view = \OC\Files\Filesystem::getView();
- $this->server->addPlugin(new FilesPlugin($this->server->tree, $view, false,
- !\OC::$server->getConfig()->getSystemValue('debug', false)));
+ $this->server->addPlugin(
+ new FilesPlugin(
+ $this->server->tree,
+ $view,
+ \OC::$server->getConfig(),
+ false,
+ !\OC::$server->getConfig()->getSystemValue('debug', false)
+ )
+ );
$this->server->addPlugin(
new \Sabre\DAV\PropertyStorage\Plugin(
diff --git a/apps/dav/tests/unit/connector/sabre/filesplugin.php b/apps/dav/tests/unit/connector/sabre/filesplugin.php
index 63ee5a53c17..fb5d658b39c 100644
--- a/apps/dav/tests/unit/connector/sabre/filesplugin.php
+++ b/apps/dav/tests/unit/connector/sabre/filesplugin.php
@@ -43,6 +43,7 @@ class FilesPlugin extends TestCase {
const DOWNLOADURL_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::DOWNLOADURL_PROPERTYNAME;
const OWNER_ID_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::OWNER_ID_PROPERTYNAME;
const OWNER_DISPLAY_NAME_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME;
+ const DATA_FINGERPRINT_PROPERTYNAME = \OCA\DAV\Connector\Sabre\FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME;
/**
* @var \Sabre\DAV\Server | \PHPUnit_Framework_MockObject_MockObject
@@ -64,6 +65,11 @@ class FilesPlugin extends TestCase {
*/
private $view;
+ /**
+ * @var \OCP\IConfig | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $config;
+
public function setUp() {
parent::setUp();
$this->server = $this->getMockBuilder('\Sabre\DAV\Server')
@@ -75,8 +81,16 @@ class FilesPlugin extends TestCase {
$this->view = $this->getMockBuilder('\OC\Files\View')
->disableOriginalConstructor()
->getMock();
-
- $this->plugin = new \OCA\DAV\Connector\Sabre\FilesPlugin($this->tree, $this->view);
+ $this->config = $this->getMock('\OCP\IConfig');
+ $this->config->method('getSystemValue')
+ ->with($this->equalTo('data-fingerprint'), $this->equalTo(''))
+ ->willReturn('my_fingerprint');
+
+ $this->plugin = new \OCA\DAV\Connector\Sabre\FilesPlugin(
+ $this->tree,
+ $this->view,
+ $this->config
+ );
$this->plugin->initialize($this->server);
}
@@ -128,7 +142,8 @@ class FilesPlugin extends TestCase {
self::PERMISSIONS_PROPERTYNAME,
self::DOWNLOADURL_PROPERTYNAME,
self::OWNER_ID_PROPERTYNAME,
- self::OWNER_DISPLAY_NAME_PROPERTYNAME
+ self::OWNER_DISPLAY_NAME_PROPERTYNAME,
+ self::DATA_FINGERPRINT_PROPERTYNAME,
),
0
);
@@ -166,7 +181,7 @@ class FilesPlugin extends TestCase {
$this->assertEquals('http://example.com/', $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
$this->assertEquals('foo', $propFind->get(self::OWNER_ID_PROPERTYNAME));
$this->assertEquals('M. Foo', $propFind->get(self::OWNER_DISPLAY_NAME_PROPERTYNAME));
- $this->assertEquals(array(self::SIZE_PROPERTYNAME), $propFind->get404Properties());
+ $this->assertEquals([self::SIZE_PROPERTYNAME, self::DATA_FINGERPRINT_PROPERTYNAME], $propFind->get404Properties());
}
public function testGetPropertiesForFileHome() {
@@ -185,7 +200,8 @@ class FilesPlugin extends TestCase {
self::PERMISSIONS_PROPERTYNAME,
self::DOWNLOADURL_PROPERTYNAME,
self::OWNER_ID_PROPERTYNAME,
- self::OWNER_DISPLAY_NAME_PROPERTYNAME
+ self::OWNER_DISPLAY_NAME_PROPERTYNAME,
+ self::DATA_FINGERPRINT_PROPERTYNAME,
),
0
);
@@ -217,6 +233,7 @@ class FilesPlugin extends TestCase {
'{http://owncloud.org/ns}owner-id',
'{http://owncloud.org/ns}owner-display-name'
], $propFind->get404Properties());
+ $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
}
public function testGetPropertiesStorageNotAvailable() {
@@ -244,7 +261,11 @@ class FilesPlugin extends TestCase {
}
public function testGetPublicPermissions() {
- $this->plugin = new \OCA\DAV\Connector\Sabre\FilesPlugin($this->tree, $this->view, true);
+ $this->plugin = new \OCA\DAV\Connector\Sabre\FilesPlugin(
+ $this->tree,
+ $this->view,
+ $this->config,
+ true);
$this->plugin->initialize($this->server);
$propFind = new PropFind(
@@ -281,6 +302,7 @@ class FilesPlugin extends TestCase {
self::SIZE_PROPERTYNAME,
self::PERMISSIONS_PROPERTYNAME,
self::DOWNLOADURL_PROPERTYNAME,
+ self::DATA_FINGERPRINT_PROPERTYNAME,
),
0
);
@@ -299,7 +321,30 @@ class FilesPlugin extends TestCase {
$this->assertEquals(1025, $propFind->get(self::SIZE_PROPERTYNAME));
$this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME));
$this->assertEquals(null, $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
- $this->assertEquals(array(self::DOWNLOADURL_PROPERTYNAME), $propFind->get404Properties());
+ $this->assertEquals([self::DOWNLOADURL_PROPERTYNAME, self::DATA_FINGERPRINT_PROPERTYNAME], $propFind->get404Properties());
+ }
+
+ public function testGetPropertiesForRootDirectory() {
+ /** @var \OCA\DAV\Connector\Sabre\Directory | \PHPUnit_Framework_MockObject_MockObject $node */
+ $node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Directory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $node->method('getPath')->willReturn('/');
+
+ $propFind = new PropFind(
+ '/',
+ [
+ self::DATA_FINGERPRINT_PROPERTYNAME,
+ ],
+ 0
+ );
+
+ $this->plugin->handleGetProperties(
+ $propFind,
+ $node
+ );
+
+ $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
}
public function testUpdateProps() {
diff --git a/apps/dav/tests/unit/connector/sabre/filesreportplugin.php b/apps/dav/tests/unit/connector/sabre/filesreportplugin.php
index 87973ef0071..ffe1a19ee56 100644
--- a/apps/dav/tests/unit/connector/sabre/filesreportplugin.php
+++ b/apps/dav/tests/unit/connector/sabre/filesreportplugin.php
@@ -336,7 +336,15 @@ class FilesReportPlugin extends \Test\TestCase {
->method('getSize')
->will($this->returnValue(1024));
- $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\FilesPlugin($this->tree, $this->view));
+ $config = $this->getMock('\OCP\IConfig');
+
+ $this->server->addPlugin(
+ new \OCA\DAV\Connector\Sabre\FilesPlugin(
+ $this->tree,
+ $this->view,
+ $config
+ )
+ );
$this->plugin->initialize($this->server);
$responses = $this->plugin->prepareResponses($requestedProps, [$node1, $node2]);
diff --git a/apps/dav/tests/unit/dav/HookManagerTest.php b/apps/dav/tests/unit/dav/HookManagerTest.php
new file mode 100644
index 00000000000..bec4c240ce8
--- /dev/null
+++ b/apps/dav/tests/unit/dav/HookManagerTest.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @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\Tests\Unit\DAV;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CardDAV\CardDavBackend;
+use OCA\DAV\CardDAV\SyncService;
+use OCA\DAV\HookManager;
+use OCP\IUserManager;
+use Test\TestCase;
+
+class HookManagerTest extends TestCase {
+ public function test() {
+ $user = $this->getMockBuilder('\OCP\IUser')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject $userManager */
+ $userManager = $this->getMockBuilder('\OCP\IUserManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $userManager->expects($this->once())->method('get')->willReturn($user);
+
+ /** @var SyncService | \PHPUnit_Framework_MockObject_MockObject $syncService */
+ $syncService = $this->getMockBuilder('OCA\DAV\CardDAV\SyncService')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ /** @var CalDavBackend | \PHPUnit_Framework_MockObject_MockObject $cal */
+ $cal = $this->getMockBuilder('OCA\DAV\CalDAV\CalDavBackend')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $cal->expects($this->once())->method('getCalendarsForUser')->willReturn([]);
+ $cal->expects($this->once())->method('createCalendar')->with(
+ 'principals/users/newUser',
+ 'personal', ['{DAV:}displayname' => 'Personal']);
+
+ /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject $card */
+ $card = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $card->expects($this->once())->method('getAddressBooksForUser')->willReturn([]);
+ $card->expects($this->once())->method('createAddressBook')->with(
+ 'principals/users/newUser',
+ 'contacts', ['{DAV:}displayname' => 'Contacts']);
+
+ $hm = new HookManager($userManager, $syncService, $cal, $card);
+ $hm->postLogin(['uid' => 'newUser']);
+ }
+}
diff --git a/apps/encryption/hooks/userhooks.php b/apps/encryption/hooks/userhooks.php
index 62acd168909..bde4d5869b4 100644
--- a/apps/encryption/hooks/userhooks.php
+++ b/apps/encryption/hooks/userhooks.php
@@ -24,6 +24,7 @@
namespace OCA\Encryption\Hooks;
+use OC\Files\Filesystem;
use OCP\IUserManager;
use OCP\Util as OCUtil;
use OCA\Encryption\Hooks\Contracts\IHook;
@@ -243,6 +244,7 @@ class UserHooks implements IHook {
// used to decrypt it has changed
} else { // admin changed the password for a different user, create new keys and re-encrypt file keys
$user = $params['uid'];
+ $this->initMountPoints($user);
$recoveryPassword = isset($params['recoveryPassword']) ? $params['recoveryPassword'] : null;
// we generate new keys if...
@@ -281,6 +283,15 @@ class UserHooks implements IHook {
}
}
+ /**
+ * init mount points for given user
+ *
+ * @param string $user
+ * @throws \OC\User\NoUserException
+ */
+ protected function initMountPoints($user) {
+ Filesystem::initMountPoints($user);
+ }
/**
diff --git a/apps/encryption/lib/crypto/encryption.php b/apps/encryption/lib/crypto/encryption.php
index 907a6437f5b..6eff66e72be 100644
--- a/apps/encryption/lib/crypto/encryption.php
+++ b/apps/encryption/lib/crypto/encryption.php
@@ -547,4 +547,17 @@ class Encryption implements IEncryptionModule {
return $path;
}
+ /**
+ * Check if the module is ready to be used by that specific user.
+ * In case a module is not ready - because e.g. key pairs have not been generated
+ * upon login this method can return false before any operation starts and might
+ * cause issues during operations.
+ *
+ * @param string $user
+ * @return boolean
+ * @since 9.1.0
+ */
+ public function isReadyForUser($user) {
+ return $this->keyManager->userHasKeys($user);
+ }
}
diff --git a/apps/encryption/lib/keymanager.php b/apps/encryption/lib/keymanager.php
index 12fa5f92bd5..0accfb7900a 100644
--- a/apps/encryption/lib/keymanager.php
+++ b/apps/encryption/lib/keymanager.php
@@ -493,6 +493,7 @@ class KeyManager {
*/
public function userHasKeys($userId) {
$privateKey = $publicKey = true;
+ $exception = null;
try {
$this->getPrivateKey($userId);
diff --git a/apps/encryption/tests/hooks/UserHooksTest.php b/apps/encryption/tests/hooks/UserHooksTest.php
index 08d1981266c..d2a7d4f2d04 100644
--- a/apps/encryption/tests/hooks/UserHooksTest.php
+++ b/apps/encryption/tests/hooks/UserHooksTest.php
@@ -29,6 +29,12 @@ use OCA\Encryption\Crypto\Crypt;
use OCA\Encryption\Hooks\UserHooks;
use Test\TestCase;
+/**
+ * Class UserHooksTest
+ *
+ * @group DB
+ * @package OCA\Encryption\Tests\Hooks
+ */
class UserHooksTest extends TestCase {
/**
* @var \PHPUnit_Framework_MockObject_MockObject
@@ -190,6 +196,23 @@ class UserHooksTest extends TestCase {
->willReturnOnConsecutiveCalls(true, false);
+ $this->instance = $this->getMockBuilder('OCA\Encryption\Hooks\UserHooks')
+ ->setConstructorArgs(
+ [
+ $this->keyManagerMock,
+ $this->userManagerMock,
+ $this->loggerMock,
+ $this->userSetupMock,
+ $this->userSessionMock,
+ $this->utilMock,
+ $this->sessionMock,
+ $this->cryptMock,
+ $this->recoveryMock
+ ]
+ )->setMethods(['initMountPoints'])->getMock();
+
+ $this->instance->expects($this->exactly(3))->method('initMountPoints');
+
// Test first if statement
$this->assertNull($this->instance->setPassphrase($this->params));
@@ -236,16 +259,20 @@ class UserHooksTest extends TestCase {
->with('testUser')
->willReturn(false);
- $userHooks = new UserHooks($this->keyManagerMock,
- $this->userManagerMock,
- $this->loggerMock,
- $this->userSetupMock,
- $userSessionMock,
- $this->utilMock,
- $this->sessionMock,
- $this->cryptMock,
- $this->recoveryMock
- );
+ $userHooks = $this->getMockBuilder('OCA\Encryption\Hooks\UserHooks')
+ ->setConstructorArgs(
+ [
+ $this->keyManagerMock,
+ $this->userManagerMock,
+ $this->loggerMock,
+ $this->userSetupMock,
+ $userSessionMock,
+ $this->utilMock,
+ $this->sessionMock,
+ $this->cryptMock,
+ $this->recoveryMock
+ ]
+ )->setMethods(['initMountPoints'])->getMock();
$this->assertNull($userHooks->setPassphrase($this->params));
}
diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php
index 6ad938101a2..2291b48e3c5 100644
--- a/apps/files/appinfo/routes.php
+++ b/apps/files/appinfo/routes.php
@@ -54,6 +54,11 @@ $application->registerRoutes(
'url' => '/api/v1/sorting',
'verb' => 'POST'
),
+ array(
+ 'name' => 'API#showHiddenFiles',
+ 'url' => '/api/v1/showhidden',
+ 'verb' => 'POST'
+ ),
[
'name' => 'view#index',
'url' => '/',
diff --git a/apps/files/command/transferownership.php b/apps/files/command/transferownership.php
index 6bf2fae6bdf..1f46efdde0d 100644
--- a/apps/files/command/transferownership.php
+++ b/apps/files/command/transferownership.php
@@ -97,6 +97,12 @@ class TransferOwnership extends Command {
$output->writeln("<error>Unknown destination user $this->destinationUser</error>");
return;
}
+
+ // target user has to be ready
+ if (!\OC::$server->getEncryptionManager()->isReadyForUser($this->destinationUser)) {
+ $output->writeln("<error>The target user is not ready to accept files. The user has at least to be logged in once.</error>");
+ return;
+ }
$date = date('c');
$this->finalTarget = "$this->destinationUser/files/transferred from $this->sourceUser on $date";
diff --git a/apps/files/controller/apicontroller.php b/apps/files/controller/apicontroller.php
index 43d426476fe..072498c7b5f 100644
--- a/apps/files/controller/apicontroller.php
+++ b/apps/files/controller/apicontroller.php
@@ -224,4 +224,16 @@ class ApiController extends Controller {
return new Response();
}
+ /**
+ * Toggle default for showing/hiding hidden files
+ *
+ * @NoAdminRequired
+ *
+ * @param bool $show
+ */
+ public function showHiddenFiles($show) {
+ $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', (int) $show);
+ return new Response();
+ }
+
}
diff --git a/apps/files/controller/viewcontroller.php b/apps/files/controller/viewcontroller.php
index 6c5f4c6d2a0..9fe34521332 100644
--- a/apps/files/controller/viewcontroller.php
+++ b/apps/files/controller/viewcontroller.php
@@ -67,6 +67,7 @@ class ViewController extends Controller {
* @param IL10N $l10n
* @param IConfig $config
* @param EventDispatcherInterface $eventDispatcherInterface
+ * @param IUserSession $userSession
*/
public function __construct($appName,
IRequest $request,
@@ -222,6 +223,8 @@ class ViewController extends Controller {
$user = $this->userSession->getUser()->getUID();
$params['defaultFileSorting'] = $this->config->getUserValue($user, 'files', 'file_sorting', 'name');
$params['defaultFileSortingDirection'] = $this->config->getUserValue($user, 'files', 'file_sorting_direction', 'asc');
+ $showHidden = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', false);
+ $params['showHiddenFiles'] = $showHidden ? 1 : 0;
$params['appNavigation'] = $nav;
$params['appContents'] = $contentItems;
$this->navigationManager->setActiveEntry('files_index');
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index d20ab102ba5..373739071e9 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -2,6 +2,11 @@
This file is licensed under the Affero General Public License version 3 or later.
See the COPYING-README file. */
+/* SETTINGS */
+#files-setting-showhidden {
+ padding-bottom: 8px;
+}
+
/* FILE MENU */
.actions { padding:5px; height:32px; display: inline-block; float: left; }
.actions input, .actions button, .actions .button { margin:0; float:left; }
diff --git a/apps/files/js/app.js b/apps/files/js/app.js
index 4ed805d2681..eac080a009d 100644
--- a/apps/files/js/app.js
+++ b/apps/files/js/app.js
@@ -11,7 +11,7 @@
*
*/
-/* global dragOptions, folderDropOptions */
+/* global dragOptions, folderDropOptions, OC */
(function() {
if (!OCA.Files) {
@@ -41,10 +41,22 @@
fileList: null,
/**
+ * Backbone model for storing files preferences
+ */
+ _filesConfig: null,
+
+ /**
* Initializes the files app
*/
initialize: function() {
this.navigation = new OCA.Files.Navigation($('#app-navigation'));
+ this.$showHiddenFiles = $('input#showhiddenfilesToggle');
+ var showHidden = $('#showHiddenFiles').val() === "1";
+ this.$showHiddenFiles.prop('checked', showHidden);
+
+ this._filesConfig = new OC.Backbone.Model({
+ showhidden: showHidden
+ });
var urlParams = OC.Util.History.parseUrlQuery();
var fileActions = new OCA.Files.FileActions();
@@ -76,7 +88,8 @@
sorting: {
mode: $('#defaultFileSorting').val(),
direction: $('#defaultFileSortingDirection').val()
- }
+ },
+ config: this._filesConfig,
}
);
this.files.initialize();
@@ -90,6 +103,8 @@
this._setupEvents();
// trigger URL change event handlers
this._onPopState(urlParams);
+
+ this._debouncedPersistShowHiddenFilesState = _.debounce(this._persistShowHiddenFilesState, 1200);
},
/**
@@ -144,6 +159,14 @@
},
/**
+ *
+ * @returns {Backbone.Model}
+ */
+ getFilesConfig: function() {
+ return this._filesConfig;
+ },
+
+ /**
* Setup events based on URL changes
*/
_setupEvents: function() {
@@ -154,6 +177,30 @@
$('#app-content').delegate('>div', 'changeViewerMode', _.bind(this._onChangeViewerMode, this));
$('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this));
+ this.$showHiddenFiles.on('change', _.bind(this._onShowHiddenFilesChange, this));
+ },
+
+ /**
+ * Toggle showing hidden files according to the settings checkbox
+ *
+ * @returns {undefined}
+ */
+ _onShowHiddenFilesChange: function() {
+ var show = this.$showHiddenFiles.is(':checked');
+ this._filesConfig.set('showhidden', show);
+ this._debouncedPersistShowHiddenFilesState();
+ },
+
+ /**
+ * Persist show hidden preference on ther server
+ *
+ * @returns {undefined}
+ */
+ _persistShowHiddenFilesState: function() {
+ var show = this._filesConfig.get('showhidden');
+ $.post(OC.generateUrl('/apps/files/api/v1/showhidden'), {
+ show: show
+ });
},
/**
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 7de64f8ade3..79dc42da8f1 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -145,6 +145,11 @@
_filter: '',
/**
+ * @type Backbone.Model
+ */
+ _filesConfig: null,
+
+ /**
* Sort attribute
* @type String
*/
@@ -198,6 +203,15 @@
return;
}
+ if (options.config) {
+ this._filesConfig = options.config;
+ } else {
+ this._filesConfig = OCA.Files.App.getFilesConfig();
+ }
+ this._filesConfig.on('change:showhidden', function() {
+ self.setFiles(self.files);
+ });
+
if (options.dragOptions) {
this._dragOptions = options.dragOptions;
}
@@ -847,6 +861,10 @@
* @return array of DOM elements of the newly added files
*/
_nextPage: function(animate) {
+ // Save full files list while rendering
+ var allFiles = this.files;
+ this.files = this._filterHiddenFiles(this.files);
+
var index = this.$fileList.children().length,
count = this.pageSize(),
hidden,
@@ -893,6 +911,10 @@
}
}, 0);
}
+
+ // Restore full files list after rendering
+ this.files = allFiles;
+
return newTrs;
},
@@ -930,18 +952,25 @@
// clear "Select all" checkbox
this.$el.find('.select-all').prop('checked', false);
+ // Save full files list while rendering
+ var allFiles = this.files;
+ this.files = this._filterHiddenFiles(this.files);
+
this.isEmpty = this.files.length === 0;
this._nextPage();
this.updateEmptyContent();
- this.fileSummary.calculate(filesArray);
+ this.fileSummary.calculate(this.files);
this._selectedFiles = {};
this._selectionSummary.clear();
this.updateSelectionSummary();
$(window).scrollTop(0);
+ // Restore full files list after rendering
+ this.files = allFiles;
+
this.$fileList.trigger(jQuery.Event('updated'));
_.defer(function() {
self.$el.closest('#app-content').trigger(jQuery.Event('apprendered'));
@@ -949,6 +978,21 @@
},
/**
+ * Filter hidden files of the given filesArray (dot-files)
+ *
+ * @param filesArray files to be filtered
+ * @returns {array}
+ */
+ _filterHiddenFiles: function(files) {
+ if (this._filesConfig.get('showhidden')) {
+ return files;
+ }
+ return _.filter(files, function(file) {
+ return file.name.indexOf('.') !== 0;
+ });
+ },
+
+ /**
* Returns the icon URL matching the given file info
*
* @param {OC.Files.FileInfo} fileInfo file info
diff --git a/apps/files/templates/appnavigation.php b/apps/files/templates/appnavigation.php
index 39a5875f3d0..9c79f806713 100644
--- a/apps/files/templates/appnavigation.php
+++ b/apps/files/templates/appnavigation.php
@@ -16,9 +16,13 @@
</button>
</div>
<div id="app-settings-content">
- <label for="webdavurl"><?php p($l->t('WebDAV'));?></label>
- <input id="webdavurl" type="text" readonly="readonly" value="<?php p(\OCP\Util::linkToRemote('webdav')); ?>" />
- <em><?php print_unescaped($l->t('Use this address to <a href="%s" target="_blank" rel="noreferrer">access your Files via WebDAV</a>', array(link_to_docs('user-webdav'))));?></em>
+ <div id="files-setting-showhidden">
+ <input class="checkbox" id="showhiddenfilesToggle" checked="checked" type="checkbox">
+ <label for="showhiddenfilesToggle"><?php p($l->t('Show hidden files')); ?></label>
+ </div>
+ <label for="webdavurl"><?php p($l->t('WebDAV'));?></label>
+ <input id="webdavurl" type="text" readonly="readonly" value="<?php p(\OCP\Util::linkToRemote('webdav')); ?>" />
+ <em><?php print_unescaped($l->t('Use this address to <a href="%s" target="_blank" rel="noreferrer">access your Files via WebDAV</a>', array(link_to_docs('user-webdav'))));?></em>
</div>
</div>
</div>
diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php
index db464ad2eca..7281edd3aec 100644
--- a/apps/files/templates/index.php
+++ b/apps/files/templates/index.php
@@ -20,4 +20,5 @@
<input type="hidden" name="allowShareWithLink" id="allowShareWithLink" value="<?php p($_['allowShareWithLink']) ?>" />
<input type="hidden" name="defaultFileSorting" id="defaultFileSorting" value="<?php p($_['defaultFileSorting']) ?>" />
<input type="hidden" name="defaultFileSortingDirection" id="defaultFileSortingDirection" value="<?php p($_['defaultFileSortingDirection']) ?>" />
+<input type="hidden" name="showHiddenFiles" id="showHiddenFiles" value="<?php p($_['showHiddenFiles']); ?>" />
<?php endif;
diff --git a/apps/files/tests/controller/ViewControllerTest.php b/apps/files/tests/controller/ViewControllerTest.php
index 0446cc8982c..420e635b4b9 100644
--- a/apps/files/tests/controller/ViewControllerTest.php
+++ b/apps/files/tests/controller/ViewControllerTest.php
@@ -155,11 +155,12 @@ class ViewControllerTest extends TestCase {
'owner' => 'MyName',
'ownerDisplayName' => 'MyDisplayName',
]));
- $this->config->expects($this->exactly(2))
+ $this->config->expects($this->exactly(3))
->method('getUserValue')
->will($this->returnValueMap([
[$this->user->getUID(), 'files', 'file_sorting', 'name', 'name'],
- [$this->user->getUID(), 'files', 'file_sorting_direction', 'asc', 'asc']
+ [$this->user->getUID(), 'files', 'file_sorting_direction', 'asc', 'asc'],
+ [$this->user->getUID(), 'files', 'show_hidden', false, false],
]));
$this->config
@@ -244,6 +245,7 @@ class ViewControllerTest extends TestCase {
'isPublic' => false,
'defaultFileSorting' => 'name',
'defaultFileSortingDirection' => 'asc',
+ 'showHiddenFiles' => false,
'mailNotificationEnabled' => 'no',
'mailPublicNotificationEnabled' => 'no',
'allowShareWithLink' => 'yes',
diff --git a/apps/files/tests/controller/apicontrollertest.php b/apps/files/tests/controller/apicontrollertest.php
index 59f53e8ee81..2eba7d62feb 100644
--- a/apps/files/tests/controller/apicontrollertest.php
+++ b/apps/files/tests/controller/apicontrollertest.php
@@ -1,4 +1,5 @@
<?php
+
/**
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Lukas Reschke <lukas@owncloud.com>
@@ -382,4 +383,17 @@ class ApiControllerTest extends TestCase {
$this->assertEquals($expected, $result);
}
+ public function testShowHiddenFiles() {
+ $show = false;
+
+ $this->config->expects($this->once())
+ ->method('setUserValue')
+ ->with($this->user->getUID(), 'files', 'show_hidden', $show);
+
+ $expected = new Http\Response();
+ $actual = $this->apiController->showHiddenFiles($show);
+
+ $this->assertEquals($expected, $actual);
+ }
+
}
diff --git a/apps/files_sharing/js/app.js b/apps/files_sharing/js/app.js
index af198208de2..6f12b3d4456 100644
--- a/apps/files_sharing/js/app.js
+++ b/apps/files_sharing/js/app.js
@@ -33,7 +33,8 @@ OCA.Sharing.App = {
id: 'shares.self',
scrollContainer: $('#app-content'),
sharedWithUser: true,
- fileActions: this._createFileActions()
+ fileActions: this._createFileActions(),
+ config: OCA.Files.App.getFilesConfig()
}
);
@@ -55,7 +56,8 @@ OCA.Sharing.App = {
id: 'shares.others',
scrollContainer: $('#app-content'),
sharedWithUser: false,
- fileActions: this._createFileActions()
+ fileActions: this._createFileActions(),
+ config: OCA.Files.App.getFilesConfig()
}
);
@@ -77,7 +79,8 @@ OCA.Sharing.App = {
id: 'shares.link',
scrollContainer: $('#app-content'),
linksOnly: true,
- fileActions: this._createFileActions()
+ fileActions: this._createFileActions(),
+ config: OCA.Files.App.getFilesConfig()
}
);
diff --git a/apps/files_sharing/tests/testcase.php b/apps/files_sharing/tests/testcase.php
index d30782e5074..0950c2a62f5 100644
--- a/apps/files_sharing/tests/testcase.php
+++ b/apps/files_sharing/tests/testcase.php
@@ -87,7 +87,7 @@ abstract class TestCase extends \Test\TestCase {
$backend->createUser(self::TEST_FILES_SHARING_API_USER4, self::TEST_FILES_SHARING_API_USER4);
// create group
- $groupBackend = new \OC_Group_Dummy();
+ $groupBackend = new \Test\Util\Group\Dummy();
$groupBackend->createGroup(self::TEST_FILES_SHARING_API_GROUP1);
$groupBackend->createGroup('group');
$groupBackend->createGroup('group1');
diff --git a/apps/files_trashbin/js/app.js b/apps/files_trashbin/js/app.js
index 771ea90bc16..fd3d5db32ff 100644
--- a/apps/files_trashbin/js/app.js
+++ b/apps/files_trashbin/js/app.js
@@ -29,7 +29,8 @@ OCA.Trashbin.App = {
scrollContainer: $('#app-content'),
fileActions: this._createFileActions(),
detailsViewEnabled: false,
- scrollTo: urlParams.scrollto
+ scrollTo: urlParams.scrollto,
+ config: OCA.Files.App.getFilesConfig()
}
);
},
diff --git a/apps/systemtags/js/app.js b/apps/systemtags/js/app.js
index d28514358c1..e027c0be123 100644
--- a/apps/systemtags/js/app.js
+++ b/apps/systemtags/js/app.js
@@ -28,7 +28,8 @@
{
id: 'systemtags',
scrollContainer: $('#app-content'),
- fileActions: this._createFileActions()
+ fileActions: this._createFileActions(),
+ config: OCA.Files.App.getFilesConfig()
}
);