aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/encryption/lib/crypto/encryptall.php6
-rw-r--r--apps/files/css/detailsView.css8
-rw-r--r--apps/files/js/mainfileinfodetailview.js6
-rw-r--r--apps/files_external/controller/globalstoragescontroller.php13
-rw-r--r--apps/files_external/controller/storagescontroller.php16
-rw-r--r--apps/files_external/controller/userstoragescontroller.php13
-rw-r--r--apps/files_external/js/settings.js13
-rw-r--r--apps/files_external/lib/auth/authmechanism.php8
-rw-r--r--apps/files_external/lib/backend/backend.php7
-rw-r--r--apps/files_external/lib/backend/local.php2
-rw-r--r--apps/files_external/lib/backend/sftp_key.php8
-rw-r--r--apps/files_external/lib/backend/smb_oc.php8
-rw-r--r--apps/files_external/lib/config.php14
-rw-r--r--apps/files_external/lib/config/configadapter.php2
-rw-r--r--apps/files_external/lib/identifiertrait.php34
-rw-r--r--apps/files_external/lib/permissionstrait.php164
-rw-r--r--apps/files_external/lib/visibilitytrait.php136
-rw-r--r--apps/files_external/personal.php6
-rw-r--r--apps/files_external/service/backendservice.php20
-rw-r--r--apps/files_external/service/globalstoragesservice.php9
-rw-r--r--apps/files_external/service/storagesservice.php45
-rw-r--r--apps/files_external/service/userglobalstoragesservice.php2
-rw-r--r--apps/files_external/service/userstoragesservice.php9
-rw-r--r--apps/files_external/settings.php10
-rw-r--r--apps/files_external/templates/settings.php9
-rw-r--r--apps/files_external/tests/controller/globalstoragescontrollertest.php4
-rw-r--r--apps/files_external/tests/controller/storagescontrollertest.php16
-rw-r--r--apps/files_external/tests/controller/userstoragescontrollertest.php19
-rw-r--r--apps/files_external/tests/service/backendservicetest.php6
-rw-r--r--apps/files_external/tests/service/storagesservicetest.php46
-rw-r--r--apps/files_external/tests/service/userglobalstoragesservicetest.php14
-rw-r--r--apps/files_sharing/api/sharees.php20
-rw-r--r--apps/files_sharing/tests/api/shareestest.php438
-rw-r--r--apps/user_ldap/js/wizard/wizardTabLoginFilter.js13
-rw-r--r--apps/user_ldap/templates/part.wizard-loginfilter.php2
-rw-r--r--core/ajax/share.php10
-rw-r--r--core/css/fixes.css5
-rw-r--r--core/img/actions/close.pngbin206 -> 493 bytes
-rw-r--r--core/img/actions/close.svg9
-rw-r--r--core/js/shareitemmodel.js2
-rw-r--r--core/js/tests/specs/shareitemmodelSpec.js8
-rw-r--r--core/search/js/search.js4
-rw-r--r--core/shipped.json4
-rw-r--r--lib/private/app.php4
-rw-r--r--lib/private/connector/sabre/listenerplugin.php12
-rw-r--r--lib/private/db/querybuilder/quotehelper.php2
-rw-r--r--lib/private/encryption/decryptall.php2
-rw-r--r--lib/private/files/storage/wrapper/permissionsmask.php2
-rw-r--r--lib/private/files/view.php5
-rw-r--r--lib/private/templatelayout.php9
-rw-r--r--lib/public/sabrepluginevent.php82
-rw-r--r--lib/public/sabrepluginexception.php41
-rw-r--r--settings/admin.php1
-rw-r--r--settings/templates/admin.php5
-rw-r--r--tests/lib/db/querybuilder/quotehelpertest.php4
-rw-r--r--tests/lib/encryption/decryptalltest.php16
-rw-r--r--tests/lib/files/storage/storage.php25
-rw-r--r--tests/lib/files/view.php135
58 files changed, 1152 insertions, 381 deletions
diff --git a/apps/encryption/lib/crypto/encryptall.php b/apps/encryption/lib/crypto/encryptall.php
index a0c69c13fdd..8e97fe341b4 100644
--- a/apps/encryption/lib/crypto/encryptall.php
+++ b/apps/encryption/lib/crypto/encryptall.php
@@ -280,6 +280,12 @@ class EncryptAll {
$newPasswords[] = [$uid, $password];
}
}
+
+ if (empty($newPasswords)) {
+ $this->output->writeln("\nAll users already had a key-pair, no further action needed.\n");
+ return;
+ }
+
$table->setRows($newPasswords);
$table->render();
diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css
index 8acf884f219..faa26678562 100644
--- a/apps/files/css/detailsView.css
+++ b/apps/files/css/detailsView.css
@@ -32,12 +32,18 @@
#app-sidebar .image .thumbnail {
width:100%;
display:block;
- height: 250px;
background-repeat: no-repeat;
background-position: center;
background-size: 100%;
float: none;
margin: 0;
+ height: auto;
+}
+
+#app-sidebar .image.landscape .thumbnail::before {
+ content: '';
+ display: block;
+ padding-bottom: 56.25%; /* sets height of .thumbnail to 9/16 of the width */
}
#app-sidebar .image.portrait .thumbnail {
diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js
index 830f074f3f1..82cca0d0fb3 100644
--- a/apps/files/js/mainfileinfodetailview.js
+++ b/apps/files/js/mainfileinfodetailview.js
@@ -176,9 +176,7 @@
$iconDiv.removeClass('icon-loading icon-32');
var targetHeight = getTargetHeight(img);
if (this.model.isImage() && targetHeight > smallPreviewSize) {
- if (!isLandscape(img)) {
- $container.addClass('portrait');
- }
+ $container.addClass(isLandscape(img)? 'landscape': 'portrait');
$container.addClass('image');
}
@@ -186,7 +184,7 @@
// when we dont have a preview we show the mime icon in the error handler
$iconDiv.css({
'background-image': 'url("' + previewUrl + '")',
- 'height': targetHeight
+ height: (isLandscape(img) && targetHeight > smallPreviewSize)? 'auto': targetHeight
});
}.bind(this),
error: function () {
diff --git a/apps/files_external/controller/globalstoragescontroller.php b/apps/files_external/controller/globalstoragescontroller.php
index 7d97fdbb4f4..3c1f2022505 100644
--- a/apps/files_external/controller/globalstoragescontroller.php
+++ b/apps/files_external/controller/globalstoragescontroller.php
@@ -98,7 +98,7 @@ class GlobalStoragesController extends StoragesController {
return $newStorage;
}
- $response = $this->validate($newStorage, BackendService::PERMISSION_CREATE);
+ $response = $this->validate($newStorage);
if (!empty($response)) {
return $response;
}
@@ -154,7 +154,7 @@ class GlobalStoragesController extends StoragesController {
}
$storage->setId($id);
- $response = $this->validate($storage, BackendService::PERMISSION_MODIFY);
+ $response = $this->validate($storage);
if (!empty($response)) {
return $response;
}
@@ -179,14 +179,5 @@ class GlobalStoragesController extends StoragesController {
}
- /**
- * Get the user type for this controller, used in validation
- *
- * @return string BackendService::USER_* constants
- */
- protected function getUserType() {
- return BackendService::USER_ADMIN;
- }
-
}
diff --git a/apps/files_external/controller/storagescontroller.php b/apps/files_external/controller/storagescontroller.php
index 46202c8ba4a..6a01112f8c5 100644
--- a/apps/files_external/controller/storagescontroller.php
+++ b/apps/files_external/controller/storagescontroller.php
@@ -125,11 +125,10 @@ abstract class StoragesController extends Controller {
* Validate storage config
*
* @param StorageConfig $storage storage config
- * @param int $permissionCheck permission to check
*
* @return DataResponse|null returns response in case of validation error
*/
- protected function validate(StorageConfig $storage, $permissionCheck = BackendService::PERMISSION_CREATE) {
+ protected function validate(StorageConfig $storage) {
$mountPoint = $storage->getMountPoint();
if ($mountPoint === '' || $mountPoint === '/') {
return new DataResponse(
@@ -154,7 +153,7 @@ abstract class StoragesController extends Controller {
$backend = $storage->getBackend();
/** @var AuthMechanism */
$authMechanism = $storage->getAuthMechanism();
- if (!$backend || $backend->checkDependencies()) {
+ if ($backend->checkDependencies()) {
// invalid backend
return new DataResponse(
array(
@@ -166,7 +165,7 @@ abstract class StoragesController extends Controller {
);
}
- if (!$backend->isPermitted($this->getUserType(), $permissionCheck)) {
+ if (!$backend->isVisibleFor($this->service->getVisibilityType())) {
// not permitted to use backend
return new DataResponse(
array(
@@ -177,7 +176,7 @@ abstract class StoragesController extends Controller {
Http::STATUS_UNPROCESSABLE_ENTITY
);
}
- if (!$authMechanism->isPermitted($this->getUserType(), $permissionCheck)) {
+ if (!$authMechanism->isVisibleFor($this->service->getVisibilityType())) {
// not permitted to use auth mechanism
return new DataResponse(
array(
@@ -212,13 +211,6 @@ abstract class StoragesController extends Controller {
}
/**
- * Get the user type for this controller, used in validation
- *
- * @return string BackendService::USER_* constants
- */
- abstract protected function getUserType();
-
- /**
* Check whether the given storage is available / valid.
*
* Note that this operation can be time consuming depending
diff --git a/apps/files_external/controller/userstoragescontroller.php b/apps/files_external/controller/userstoragescontroller.php
index 801c9ab0aae..f39f8a85d2d 100644
--- a/apps/files_external/controller/userstoragescontroller.php
+++ b/apps/files_external/controller/userstoragescontroller.php
@@ -103,7 +103,7 @@ class UserStoragesController extends StoragesController {
return $newStorage;
}
- $response = $this->validate($newStorage, BackendService::PERMISSION_CREATE);
+ $response = $this->validate($newStorage);
if (!empty($response)) {
return $response;
}
@@ -151,7 +151,7 @@ class UserStoragesController extends StoragesController {
}
$storage->setId($id);
- $response = $this->validate($storage, BackendService::PERMISSION_MODIFY);
+ $response = $this->validate($storage);
if (!empty($response)) {
return $response;
}
@@ -187,13 +187,4 @@ class UserStoragesController extends StoragesController {
return parent::destroy($id);
}
- /**
- * Get the user type for this controller, used in validation
- *
- * @return string BackendService::USER_* constants
- */
- protected function getUserType() {
- return BackendService::USER_PERSONAL;
- }
-
}
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js
index 4319677f4f4..5da34c52193 100644
--- a/apps/files_external/js/settings.js
+++ b/apps/files_external/js/settings.js
@@ -1113,7 +1113,18 @@ $(document).ready(function() {
$('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() {
OC.msg.startSaving('#userMountingMsg');
- var userMountingBackends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){return $(this).val();}).get();
+
+ var userMountingBackends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){
+ return $(this).val();
+ }).get();
+ var deprecatedBackends = $('input[name="allowUserMountingBackends\\[\\]"][data-deprecate-to]').map(function(){
+ if ($.inArray($(this).data('deprecate-to'), userMountingBackends) !== -1) {
+ return $(this).val();
+ }
+ return null;
+ }).get();
+ userMountingBackends = userMountingBackends.concat(deprecatedBackends);
+
OC.AppConfig.setValue('files_external', 'user_mounting_backends', userMountingBackends.join());
OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('files_external', 'Saved')}});
diff --git a/apps/files_external/lib/auth/authmechanism.php b/apps/files_external/lib/auth/authmechanism.php
index ddc0c6a4dca..2ab34ed0105 100644
--- a/apps/files_external/lib/auth/authmechanism.php
+++ b/apps/files_external/lib/auth/authmechanism.php
@@ -22,7 +22,7 @@
namespace OCA\Files_External\Lib\Auth;
use \OCA\Files_External\Lib\StorageConfig;
-use \OCA\Files_External\Lib\PermissionsTrait;
+use \OCA\Files_External\Lib\VisibilityTrait;
use \OCA\Files_External\Lib\IdentifierTrait;
use \OCA\Files_External\Lib\FrontendDefinitionTrait;
use \OCA\Files_External\Lib\StorageModifierTrait;
@@ -40,7 +40,7 @@ use \OCA\Files_External\Lib\StorageModifierTrait;
* scheme, which are provided from the authentication mechanism.
*
* This class uses the following traits:
- * - PermissionsTrait
+ * - VisibilityTrait
* Restrict usage to admin-only/none
* - FrontendDefinitionTrait
* Specify configuration parameters and other definitions
@@ -58,7 +58,7 @@ class AuthMechanism implements \JsonSerializable {
const SCHEME_PUBLICKEY = 'publickey';
const SCHEME_OPENSTACK = 'openstack';
- use PermissionsTrait;
+ use VisibilityTrait;
use FrontendDefinitionTrait;
use StorageModifierTrait;
use IdentifierTrait;
@@ -92,6 +92,8 @@ class AuthMechanism implements \JsonSerializable {
*/
public function jsonSerialize() {
$data = $this->jsonSerializeDefinition();
+ $data += $this->jsonSerializeIdentifier();
+
$data['scheme'] = $this->getScheme();
return $data;
diff --git a/apps/files_external/lib/backend/backend.php b/apps/files_external/lib/backend/backend.php
index 2a2add3ac59..68585cf377e 100644
--- a/apps/files_external/lib/backend/backend.php
+++ b/apps/files_external/lib/backend/backend.php
@@ -22,7 +22,7 @@
namespace OCA\Files_External\Lib\Backend;
use \OCA\Files_External\Lib\StorageConfig;
-use \OCA\Files_External\Lib\PermissionsTrait;
+use \OCA\Files_External\Lib\VisibilityTrait;
use \OCA\Files_External\Lib\FrontendDefinitionTrait;
use \OCA\Files_External\Lib\PriorityTrait;
use \OCA\Files_External\Lib\DependencyTrait;
@@ -43,7 +43,7 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism;
* scheme, which are provided from the authentication mechanism.
*
* This class uses the following traits:
- * - PermissionsTrait
+ * - VisibilityTrait
* Restrict usage to admin-only/none
* - FrontendDefinitionTrait
* Specify configuration parameters and other definitions
@@ -56,7 +56,7 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism;
*/
class Backend implements \JsonSerializable {
- use PermissionsTrait;
+ use VisibilityTrait;
use FrontendDefinitionTrait;
use PriorityTrait;
use DependencyTrait;
@@ -142,6 +142,7 @@ class Backend implements \JsonSerializable {
*/
public function jsonSerialize() {
$data = $this->jsonSerializeDefinition();
+ $data += $this->jsonSerializeIdentifier();
$data['backend'] = $data['name']; // legacy compat
$data['priority'] = $this->getPriority();
diff --git a/apps/files_external/lib/backend/local.php b/apps/files_external/lib/backend/local.php
index a6635491b6e..a80b437fab7 100644
--- a/apps/files_external/lib/backend/local.php
+++ b/apps/files_external/lib/backend/local.php
@@ -39,7 +39,7 @@ class Local extends Backend {
->addParameters([
(new DefinitionParameter('datadir', $l->t('Location'))),
])
- ->setAllowedPermissions(BackendService::USER_PERSONAL, BackendService::PERMISSION_NONE)
+ ->setAllowedVisibility(BackendService::VISIBILITY_ADMIN)
->setPriority(BackendService::PRIORITY_DEFAULT + 50)
->addAuthScheme(AuthMechanism::SCHEME_NULL)
->setLegacyAuthMechanism($legacyAuth)
diff --git a/apps/files_external/lib/backend/sftp_key.php b/apps/files_external/lib/backend/sftp_key.php
index 6a75172026d..13f45f1140c 100644
--- a/apps/files_external/lib/backend/sftp_key.php
+++ b/apps/files_external/lib/backend/sftp_key.php
@@ -27,23 +27,23 @@ use \OCA\Files_External\Lib\DefinitionParameter;
use \OCA\Files_External\Lib\Auth\AuthMechanism;
use \OCA\Files_External\Service\BackendService;
use \OCA\Files_External\Lib\Auth\PublicKey\RSA;
+use \OCA\Files_External\Lib\Backend\SFTP;
class SFTP_Key extends Backend {
- public function __construct(IL10N $l, RSA $legacyAuth) {
+ public function __construct(IL10N $l, RSA $legacyAuth, SFTP $sftpBackend) {
$this
->setIdentifier('\OC\Files\Storage\SFTP_Key')
->setStorageClass('\OC\Files\Storage\SFTP')
- ->setText($l->t('SFTP with secret key login [DEPRECATED]'))
+ ->setText($l->t('SFTP with secret key login'))
->addParameters([
(new DefinitionParameter('host', $l->t('Host'))),
(new DefinitionParameter('root', $l->t('Remote subfolder')))
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
])
- ->removeAllowedPermission(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE)
- ->removeAllowedPermission(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE)
->addAuthScheme(AuthMechanism::SCHEME_PUBLICKEY)
->setLegacyAuthMechanism($legacyAuth)
+ ->deprecateTo($sftpBackend)
;
}
diff --git a/apps/files_external/lib/backend/smb_oc.php b/apps/files_external/lib/backend/smb_oc.php
index d21b0ddaf42..9fc17400884 100644
--- a/apps/files_external/lib/backend/smb_oc.php
+++ b/apps/files_external/lib/backend/smb_oc.php
@@ -29,6 +29,7 @@ use \OCA\Files_External\Service\BackendService;
use \OCA\Files_External\Lib\Auth\Password\SessionCredentials;
use \OCA\Files_External\Lib\StorageConfig;
use \OCA\Files_External\Lib\LegacyDependencyCheckPolyfill;
+use \OCA\Files_External\Lib\Backend\SMB;
/**
* Deprecated SMB_OC class - use SMB with the password::sessioncredentials auth mechanism
@@ -37,11 +38,11 @@ class SMB_OC extends Backend {
use LegacyDependencyCheckPolyfill;
- public function __construct(IL10N $l, SessionCredentials $legacyAuth) {
+ public function __construct(IL10N $l, SessionCredentials $legacyAuth, SMB $smbBackend) {
$this
->setIdentifier('\OC\Files\Storage\SMB_OC')
->setStorageClass('\OC\Files\Storage\SMB')
- ->setText($l->t('SMB / CIFS using OC login [DEPRECATED]'))
+ ->setText($l->t('SMB / CIFS using OC login'))
->addParameters([
(new DefinitionParameter('host', $l->t('Host'))),
(new DefinitionParameter('username_as_share', $l->t('Username as share')))
@@ -51,11 +52,10 @@ class SMB_OC extends Backend {
(new DefinitionParameter('root', $l->t('Remote subfolder')))
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
])
- ->removeAllowedPermission(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE)
- ->removeAllowedPermission(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE)
->setPriority(BackendService::PRIORITY_DEFAULT - 10)
->addAuthScheme(AuthMechanism::SCHEME_PASSWORD)
->setLegacyAuthMechanism($legacyAuth)
+ ->deprecateTo($smbBackend)
;
}
diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php
index 2dc7de30a6c..afea7ead4e6 100644
--- a/apps/files_external/lib/config.php
+++ b/apps/files_external/lib/config.php
@@ -112,7 +112,7 @@ class OC_Mount_Config {
* @param string $uid user
* @return array of mount point string as key, mountpoint config as value
*
- * @deprecated 8.2.0 use UserGlobalStoragesService::getAllStorages() and UserStoragesService::getAllStorages()
+ * @deprecated 8.2.0 use UserGlobalStoragesService::getStorages() and UserStoragesService::getStorages()
*/
public static function getAbsoluteMountPoints($uid) {
$mountPoints = array();
@@ -124,7 +124,7 @@ class OC_Mount_Config {
$userGlobalStoragesService->setUser($user);
$userStoragesService->setUser($user);
- foreach ($userGlobalStoragesService->getAllStorages() as $storage) {
+ foreach ($userGlobalStoragesService->getStorages() as $storage) {
$mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
$mountEntry = self::prepareMountPointEntry($storage, false);
foreach ($mountEntry['options'] as &$option) {
@@ -133,7 +133,7 @@ class OC_Mount_Config {
$mountPoints[$mountPoint] = $mountEntry;
}
- foreach ($userStoragesService->getAllStorages() as $storage) {
+ foreach ($userStoragesService->getStorages() as $storage) {
$mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
$mountEntry = self::prepareMountPointEntry($storage, true);
foreach ($mountEntry['options'] as &$option) {
@@ -153,13 +153,13 @@ class OC_Mount_Config {
*
* @return array
*
- * @deprecated 8.2.0 use GlobalStoragesService::getAllStorages()
+ * @deprecated 8.2.0 use GlobalStoragesService::getStorages()
*/
public static function getSystemMountPoints() {
$mountPoints = [];
$service = self::$app->getContainer()->query('OCA\Files_External\Service\GlobalStoragesService');
- foreach ($service->getAllStorages() as $storage) {
+ foreach ($service->getStorages() as $storage) {
$mountPoints[] = self::prepareMountPointEntry($storage, false);
}
@@ -171,13 +171,13 @@ class OC_Mount_Config {
*
* @return array
*
- * @deprecated 8.2.0 use UserStoragesService::getAllStorages()
+ * @deprecated 8.2.0 use UserStoragesService::getStorages()
*/
public static function getPersonalMountPoints() {
$mountPoints = [];
$service = self::$app->getContainer()->query('OCA\Files_External\Service\UserStoragesService');
- foreach ($service->getAllStorages() as $storage) {
+ foreach ($service->getStorages() as $storage) {
$mountPoints[] = self::prepareMountPointEntry($storage, true);
}
diff --git a/apps/files_external/lib/config/configadapter.php b/apps/files_external/lib/config/configadapter.php
index cb8c2f24caa..fb36e011655 100644
--- a/apps/files_external/lib/config/configadapter.php
+++ b/apps/files_external/lib/config/configadapter.php
@@ -133,7 +133,7 @@ class ConfigAdapter implements IMountProvider {
$mounts[$storage->getMountPoint()] = $mount;
}
- foreach ($this->userStoragesService->getAllStorages() as $storage) {
+ foreach ($this->userStoragesService->getStorages() as $storage) {
try {
$this->prepareStorageConfig($storage, $user);
$impl = $this->constructStorage($storage);
diff --git a/apps/files_external/lib/identifiertrait.php b/apps/files_external/lib/identifiertrait.php
index 139911580fc..7f36144e474 100644
--- a/apps/files_external/lib/identifiertrait.php
+++ b/apps/files_external/lib/identifiertrait.php
@@ -23,6 +23,7 @@ namespace OCA\Files_External\Lib;
/**
* Trait for objects requiring an identifier (and/or identifier aliases)
+ * Also supports deprecation to a different object, linking the objects
*/
trait IdentifierTrait {
@@ -32,6 +33,9 @@ trait IdentifierTrait {
/** @var string[] */
protected $identifierAliases = [];
+ /** @var IdentifierTrait */
+ protected $deprecateTo = null;
+
/**
* @return string
*/
@@ -65,4 +69,34 @@ trait IdentifierTrait {
return $this;
}
+ /**
+ * @return object|null
+ */
+ public function getDeprecateTo() {
+ return $this->deprecateTo;
+ }
+
+ /**
+ * @param object $destinationObject
+ * @return self
+ */
+ public function deprecateTo($destinationObject) {
+ $this->deprecateTo = $destinationObject;
+ return $this;
+ }
+
+ /**
+ * @return array
+ */
+ public function jsonSerializeIdentifier() {
+ $data = [
+ 'identifier' => $this->identifier,
+ 'identifierAliases' => $this->identifierAliases,
+ ];
+ if ($this->deprecateTo) {
+ $data['deprecateTo'] = $this->deprecateTo->getIdentifier();
+ }
+ return $data;
+ }
+
}
diff --git a/apps/files_external/lib/permissionstrait.php b/apps/files_external/lib/permissionstrait.php
deleted file mode 100644
index 8509a01e422..00000000000
--- a/apps/files_external/lib/permissionstrait.php
+++ /dev/null
@@ -1,164 +0,0 @@
-<?php
-/**
- * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
- *
- * @copyright Copyright (c) 2015, 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\Files_External\Lib;
-
-use \OCA\Files_External\Service\BackendService;
-
-/**
- * Trait to implement backend and auth mechanism permissions
- *
- * For user type constants, see BackendService::USER_*
- * For permission constants, see BackendService::PERMISSION_*
- */
-trait PermissionsTrait {
-
- /** @var array [user type => permissions] */
- protected $permissions = [
- BackendService::USER_PERSONAL => BackendService::PERMISSION_DEFAULT,
- BackendService::USER_ADMIN => BackendService::PERMISSION_DEFAULT,
- ];
-
- /** @var array [user type => allowed permissions] */
- protected $allowedPermissions = [
- BackendService::USER_PERSONAL => BackendService::PERMISSION_DEFAULT,
- BackendService::USER_ADMIN => BackendService::PERMISSION_DEFAULT,
- ];
-
- /**
- * @param string $userType
- * @return int
- */
- public function getPermissions($userType) {
- if (isset($this->permissions[$userType])) {
- return $this->permissions[$userType];
- }
- return BackendService::PERMISSION_NONE;
- }
-
- /**
- * Check if the user type has permission
- *
- * @param string $userType
- * @param int $permission
- * @return bool
- */
- public function isPermitted($userType, $permission) {
- if ($this->getPermissions($userType) & $permission) {
- return true;
- }
- return false;
- }
-
- /**
- * @param string $userType
- * @param int $permissions
- * @return self
- */
- public function setPermissions($userType, $permissions) {
- $this->permissions[$userType] = $permissions;
- $this->allowedPermissions[$userType] =
- $this->getAllowedPermissions($userType) | $permissions;
- return $this;
- }
-
- /**
- * @param string $userType
- * @param int $permission
- * @return self
- */
- public function addPermission($userType, $permission) {
- return $this->setPermissions($userType,
- $this->getPermissions($userType) | $permission
- );
- }
-
- /**
- * @param string $userType
- * @param int $permission
- * @return self
- */
- public function removePermission($userType, $permission) {
- return $this->setPermissions($userType,
- $this->getPermissions($userType) & ~$permission
- );
- }
-
- /**
- * @param string $userType
- * @return int
- */
- public function getAllowedPermissions($userType) {
- if (isset($this->allowedPermissions[$userType])) {
- return $this->allowedPermissions[$userType];
- }
- return BackendService::PERMISSION_NONE;
- }
-
- /**
- * Check if the user type has an allowed permission
- *
- * @param string $userType
- * @param int $permission
- * @return bool
- */
- public function isAllowedPermitted($userType, $permission) {
- if ($this->getAllowedPermissions($userType) & $permission) {
- return true;
- }
- return false;
- }
-
- /**
- * @param string $userType
- * @param int $permissions
- * @return self
- */
- public function setAllowedPermissions($userType, $permissions) {
- $this->allowedPermissions[$userType] = $permissions;
- $this->permissions[$userType] =
- $this->getPermissions($userType) & $permissions;
- return $this;
- }
-
- /**
- * @param string $userType
- * @param int $permission
- * @return self
- */
- public function addAllowedPermission($userType, $permission) {
- return $this->setAllowedPermissions($userType,
- $this->getAllowedPermissions($userType) | $permission
- );
- }
-
- /**
- * @param string $userType
- * @param int $permission
- * @return self
- */
- public function removeAllowedPermission($userType, $permission) {
- return $this->setAllowedPermissions($userType,
- $this->getAllowedPermissions($userType) & ~$permission
- );
- }
-
-}
diff --git a/apps/files_external/lib/visibilitytrait.php b/apps/files_external/lib/visibilitytrait.php
new file mode 100644
index 00000000000..dfd2d323ca6
--- /dev/null
+++ b/apps/files_external/lib/visibilitytrait.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
+ *
+ * @copyright Copyright (c) 2015, 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\Files_External\Lib;
+
+use \OCA\Files_External\Service\BackendService;
+
+/**
+ * Trait to implement visibility mechanics for a configuration class
+ *
+ * The standard visibility defines which users/groups can use or see the
+ * object. The allowed visibility defines the maximum visibility allowed to be
+ * set on the object. The standard visibility is often set dynamically by
+ * stored configuration parameters that can be modified by the administrator,
+ * while the allowed visibility is set directly by the object and cannot be
+ * modified by the administrator.
+ */
+trait VisibilityTrait {
+
+ /** @var int visibility */
+ protected $visibility = BackendService::VISIBILITY_DEFAULT;
+
+ /** @var int allowed visibilities */
+ protected $allowedVisibility = BackendService::VISIBILITY_DEFAULT;
+
+ /**
+ * @return int
+ */
+ public function getVisibility() {
+ return $this->visibility;
+ }
+
+ /**
+ * Check if the backend is visible for a user type
+ *
+ * @param int $visibility
+ * @return bool
+ */
+ public function isVisibleFor($visibility) {
+ if ($this->visibility & $visibility) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param int $visibility
+ * @return self
+ */
+ public function setVisibility($visibility) {
+ $this->visibility = $visibility;
+ $this->allowedVisibility |= $visibility;
+ return $this;
+ }
+
+ /**
+ * @param int $visibility
+ * @return self
+ */
+ public function addVisibility($visibility) {
+ return $this->setVisibility($this->visibility | $visibility);
+ }
+
+ /**
+ * @param int $visibility
+ * @return self
+ */
+ public function removeVisibility($visibility) {
+ return $this->setVisibility($this->visibility & ~$visibility);
+ }
+
+ /**
+ * @return int
+ */
+ public function getAllowedVisibility() {
+ return $this->allowedVisibility;
+ }
+
+ /**
+ * Check if the backend is allowed to be visible for a user type
+ *
+ * @param int $allowedVisibility
+ * @return bool
+ */
+ public function isAllowedVisibleFor($allowedVisibility) {
+ if ($this->allowedVisibility & $allowedVisibility) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param int $allowedVisibility
+ * @return self
+ */
+ public function setAllowedVisibility($allowedVisibility) {
+ $this->allowedVisibility = $allowedVisibility;
+ $this->visibility &= $allowedVisibility;
+ return $this;
+ }
+
+ /**
+ * @param int $allowedVisibility
+ * @return self
+ */
+ public function addAllowedVisibility($allowedVisibility) {
+ return $this->setAllowedVisibility($this->allowedVisibility | $allowedVisibility);
+ }
+
+ /**
+ * @param int $allowedVisibility
+ * @return self
+ */
+ public function removeAllowedVisibility($allowedVisibility) {
+ return $this->setAllowedVisibility($this->allowedVisibility & ~$allowedVisibility);
+ }
+
+}
diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php
index d47f983b357..f048d65540b 100644
--- a/apps/files_external/personal.php
+++ b/apps/files_external/personal.php
@@ -35,10 +35,10 @@ OCP\Util::addScript('files_external', 'settings');
OCP\Util::addStyle('files_external', 'settings');
$backends = array_filter($backendService->getAvailableBackends(), function($backend) {
- return $backend->isPermitted(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE);
+ return $backend->isVisibleFor(BackendService::VISIBILITY_PERSONAL);
});
$authMechanisms = array_filter($backendService->getAuthMechanisms(), function($authMechanism) {
- return $authMechanism->isPermitted(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE);
+ return $authMechanism->isVisibleFor(BackendService::VISIBILITY_PERSONAL);
});
foreach ($backends as $backend) {
if ($backend->getCustomJs()) {
@@ -54,7 +54,7 @@ foreach ($authMechanisms as $authMechanism) {
$tmpl = new OCP\Template('files_external', 'settings');
$tmpl->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled());
$tmpl->assign('isAdminPage', false);
-$tmpl->assign('storages', $userStoragesService->getAllStorages());
+$tmpl->assign('storages', $userStoragesService->getStorages());
$tmpl->assign('dependencies', OC_Mount_Config::dependencyMessage($backendService->getBackends()));
$tmpl->assign('backends', $backends);
$tmpl->assign('authMechanisms', $authMechanisms);
diff --git a/apps/files_external/service/backendservice.php b/apps/files_external/service/backendservice.php
index 70cb9291660..1e90247b3e4 100644
--- a/apps/files_external/service/backendservice.php
+++ b/apps/files_external/service/backendservice.php
@@ -31,17 +31,13 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism;
*/
class BackendService {
- /** Permission constants for PermissionsTrait */
- const PERMISSION_NONE = 0;
- const PERMISSION_MOUNT = 1;
- const PERMISSION_CREATE = 2;
- const PERMISSION_MODIFY = 4;
+ /** Visibility constants for VisibilityTrait */
+ const VISIBILITY_NONE = 0;
+ const VISIBILITY_PERSONAL = 1;
+ const VISIBILITY_ADMIN = 2;
+ //const VISIBILITY_ALIENS = 4;
- const PERMISSION_DEFAULT = 7; // MOUNT | CREATE | MODIFY
-
- /** User contants */
- const USER_ADMIN = 'admin';
- const USER_PERSONAL = 'personal';
+ const VISIBILITY_DEFAULT = 3; // PERSONAL | ADMIN
/** Priority constants for PriorityTrait */
const PRIORITY_DEFAULT = 100;
@@ -85,7 +81,7 @@ class BackendService {
*/
public function registerBackend(Backend $backend) {
if (!$this->isAllowedUserBackend($backend)) {
- $backend->removePermission(self::USER_PERSONAL, self::PERMISSION_CREATE | self::PERMISSION_MOUNT);
+ $backend->removeVisibility(BackendService::VISIBILITY_PERSONAL);
}
foreach ($backend->getIdentifierAliases() as $alias) {
$this->backends[$alias] = $backend;
@@ -107,7 +103,7 @@ class BackendService {
*/
public function registerAuthMechanism(AuthMechanism $authMech) {
if (!$this->isAllowedAuthMechanism($authMech)) {
- $authMech->removePermission(self::USER_PERSONAL, self::PERMISSION_CREATE | self::PERMISSION_MOUNT);
+ $authMech->removeVisibility(BackendService::VISIBILITY_PERSONAL);
}
foreach ($authMech->getIdentifierAliases() as $alias) {
$this->authMechanisms[$alias] = $authMech;
diff --git a/apps/files_external/service/globalstoragesservice.php b/apps/files_external/service/globalstoragesservice.php
index 0e2d3f2b9c1..49ffea43d1b 100644
--- a/apps/files_external/service/globalstoragesservice.php
+++ b/apps/files_external/service/globalstoragesservice.php
@@ -210,4 +210,13 @@ class GlobalStoragesService extends StoragesService {
);
}
}
+
+ /**
+ * Get the visibility type for this controller, used in validation
+ *
+ * @return string BackendService::VISIBILITY_* constants
+ */
+ public function getVisibilityType() {
+ return BackendService::VISIBILITY_ADMIN;
+ }
}
diff --git a/apps/files_external/service/storagesservice.php b/apps/files_external/service/storagesservice.php
index 703f277d84e..83a82de0bed 100644
--- a/apps/files_external/service/storagesservice.php
+++ b/apps/files_external/service/storagesservice.php
@@ -29,6 +29,8 @@ use \OC\Files\Filesystem;
use \OCA\Files_external\Lib\StorageConfig;
use \OCA\Files_external\NotFoundException;
use \OCA\Files_External\Service\BackendService;
+use \OCA\Files_External\Lib\Backend\Backend;
+use \OCA\Files_External\Lib\Auth\AuthMechanism;
/**
* Service class to manage external storages
@@ -331,7 +333,7 @@ abstract class StoragesService {
}
/**
- * Gets all storages
+ * Gets all storages, valid or not
*
* @return array array of storage configs
*/
@@ -340,6 +342,47 @@ abstract class StoragesService {
}
/**
+ * Gets all valid storages
+ *
+ * @return array
+ */
+ public function getStorages() {
+ return array_filter($this->getAllStorages(), [$this, 'validateStorage']);
+ }
+
+ /**
+ * Validate storage
+ * FIXME: De-duplicate with StoragesController::validate()
+ *
+ * @param StorageConfig $storage
+ * @return bool
+ */
+ protected function validateStorage(StorageConfig $storage) {
+ /** @var Backend */
+ $backend = $storage->getBackend();
+ /** @var AuthMechanism */
+ $authMechanism = $storage->getAuthMechanism();
+
+ if (!$backend->isVisibleFor($this->getVisibilityType())) {
+ // not permitted to use backend
+ return false;
+ }
+ if (!$authMechanism->isVisibleFor($this->getVisibilityType())) {
+ // not permitted to use auth mechanism
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the visibility type for this controller, used in validation
+ *
+ * @return string BackendService::VISIBILITY_* constants
+ */
+ abstract public function getVisibilityType();
+
+ /**
* Add new storage to the configuration
*
* @param array $newStorage storage attributes
diff --git a/apps/files_external/service/userglobalstoragesservice.php b/apps/files_external/service/userglobalstoragesservice.php
index b60473f131e..7c60bc6d497 100644
--- a/apps/files_external/service/userglobalstoragesservice.php
+++ b/apps/files_external/service/userglobalstoragesservice.php
@@ -117,7 +117,7 @@ class UserGlobalStoragesService extends GlobalStoragesService {
* @return StorageConfig[]
*/
public function getUniqueStorages() {
- $storages = $this->getAllStorages();
+ $storages = $this->getStorages();
$storagesByMountpoint = [];
foreach ($storages as $storage) {
diff --git a/apps/files_external/service/userstoragesservice.php b/apps/files_external/service/userstoragesservice.php
index c69b8d4f51e..6e3c327c09c 100644
--- a/apps/files_external/service/userstoragesservice.php
+++ b/apps/files_external/service/userstoragesservice.php
@@ -171,4 +171,13 @@ class UserStoragesService extends StoragesService {
$this->triggerHooks($newStorage, Filesystem::signal_create_mount);
}
}
+
+ /**
+ * Get the visibility type for this controller, used in validation
+ *
+ * @return string BackendService::VISIBILITY_* constants
+ */
+ public function getVisibilityType() {
+ return BackendService::VISIBILITY_PERSONAL;
+ }
}
diff --git a/apps/files_external/settings.php b/apps/files_external/settings.php
index 840f1325fb5..f82ab035c1c 100644
--- a/apps/files_external/settings.php
+++ b/apps/files_external/settings.php
@@ -42,10 +42,10 @@ OCP\Util::addStyle('files_external', 'settings');
\OC_Util::addVendorStyle('select2/select2');
$backends = array_filter($backendService->getAvailableBackends(), function($backend) {
- return $backend->isPermitted(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE);
+ return $backend->isVisibleFor(BackendService::VISIBILITY_ADMIN);
});
$authMechanisms = array_filter($backendService->getAuthMechanisms(), function($authMechanism) {
- return $authMechanism->isPermitted(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE);
+ return $authMechanism->isVisibleFor(BackendService::VISIBILITY_ADMIN);
});
foreach ($backends as $backend) {
if ($backend->getCustomJs()) {
@@ -59,15 +59,13 @@ foreach ($authMechanisms as $authMechanism) {
}
$userBackends = array_filter($backendService->getAvailableBackends(), function($backend) {
- return $backend->isAllowedPermitted(
- BackendService::USER_PERSONAL, BackendService::PERMISSION_MOUNT
- );
+ return $backend->isAllowedVisibleFor(BackendService::VISIBILITY_PERSONAL);
});
$tmpl = new OCP\Template('files_external', 'settings');
$tmpl->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled());
$tmpl->assign('isAdminPage', true);
-$tmpl->assign('storages', $globalStoragesService->getAllStorages());
+$tmpl->assign('storages', $globalStoragesService->getStorages());
$tmpl->assign('backends', $backends);
$tmpl->assign('authMechanisms', $authMechanisms);
$tmpl->assign('userBackends', $userBackends);
diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php
index 7762ff60333..141994d0050 100644
--- a/apps/files_external/templates/settings.php
+++ b/apps/files_external/templates/settings.php
@@ -157,6 +157,7 @@
});
?>
<?php foreach ($sortedBackends as $backend): ?>
+ <?php if ($backend->getDeprecateTo()) continue; // ignore deprecated backends ?>
<option value="<?php p($backend->getIdentifier()); ?>"><?php p($backend->getText()); ?></option>
<?php endforeach; ?>
</select>
@@ -197,8 +198,12 @@
<p id="userMountingBackends"<?php if ($_['allowUserMounting'] != 'yes'): ?> class="hidden"<?php endif; ?>>
<?php p($l->t('Allow users to mount the following external storage')); ?><br />
<?php $i = 0; foreach ($_['userBackends'] as $backend): ?>
- <input type="checkbox" id="allowUserMountingBackends<?php p($i); ?>" name="allowUserMountingBackends[]" value="<?php p($backend->getIdentifier()); ?>" <?php if ($backend->isPermitted(BackendService::USER_PERSONAL, BackendService::PERMISSION_MOUNT)) print_unescaped(' checked="checked"'); ?> />
- <label for="allowUserMountingBackends<?php p($i); ?>"><?php p($backend->getText()); ?></label> <br />
+ <?php if ($deprecateTo = $backend->getDeprecateTo()): ?>
+ <input type="hidden" id="allowUserMountingBackends<?php p($i); ?>" name="allowUserMountingBackends[]" value="<?php p($backend->getIdentifier()); ?>" data-deprecate-to="<?php p($deprecateTo->getIdentifier()); ?>" />
+ <?php else: ?>
+ <input type="checkbox" id="allowUserMountingBackends<?php p($i); ?>" name="allowUserMountingBackends[]" value="<?php p($backend->getIdentifier()); ?>" <?php if ($backend->isVisibleFor(BackendService::VISIBILITY_PERSONAL)) print_unescaped(' checked="checked"'); ?> />
+ <label for="allowUserMountingBackends<?php p($i); ?>"><?php p($backend->getText()); ?></label> <br />
+ <?php endif; ?>
<?php $i++; ?>
<?php endforeach; ?>
</p>
diff --git a/apps/files_external/tests/controller/globalstoragescontrollertest.php b/apps/files_external/tests/controller/globalstoragescontrollertest.php
index e1bfad8caf6..6b020198bd8 100644
--- a/apps/files_external/tests/controller/globalstoragescontrollertest.php
+++ b/apps/files_external/tests/controller/globalstoragescontrollertest.php
@@ -24,6 +24,7 @@ use \OCA\Files_external\Controller\GlobalStoragesController;
use \OCA\Files_external\Service\GlobalStoragesService;
use \OCP\AppFramework\Http;
use \OCA\Files_external\NotFoundException;
+use \OCA\Files_External\Service\BackendService;
class GlobalStoragesControllerTest extends StoragesControllerTest {
public function setUp() {
@@ -32,6 +33,9 @@ class GlobalStoragesControllerTest extends StoragesControllerTest {
->disableOriginalConstructor()
->getMock();
+ $this->service->method('getVisibilityType')
+ ->willReturn(BackendService::VISIBILITY_ADMIN);
+
$this->controller = new GlobalStoragesController(
'files_external',
$this->getMock('\OCP\IRequest'),
diff --git a/apps/files_external/tests/controller/storagescontrollertest.php b/apps/files_external/tests/controller/storagescontrollertest.php
index c43761f3bcb..5e1deb821f4 100644
--- a/apps/files_external/tests/controller/storagescontrollertest.php
+++ b/apps/files_external/tests/controller/storagescontrollertest.php
@@ -75,12 +75,12 @@ abstract class StoragesControllerTest extends \Test\TestCase {
$authMech = $this->getAuthMechMock();
$authMech->method('validateStorage')
->willReturn(true);
- $authMech->method('isPermitted')
+ $authMech->method('isVisibleFor')
->willReturn(true);
$backend = $this->getBackendMock();
$backend->method('validateStorage')
->willReturn(true);
- $backend->method('isPermitted')
+ $backend->method('isVisibleFor')
->willReturn(true);
$storageConfig = new StorageConfig(1);
@@ -116,12 +116,12 @@ abstract class StoragesControllerTest extends \Test\TestCase {
$authMech = $this->getAuthMechMock();
$authMech->method('validateStorage')
->willReturn(true);
- $authMech->method('isPermitted')
+ $authMech->method('isVisibleFor')
->willReturn(true);
$backend = $this->getBackendMock();
$backend->method('validateStorage')
->willReturn(true);
- $backend->method('isPermitted')
+ $backend->method('isVisibleFor')
->willReturn(true);
$storageConfig = new StorageConfig(1);
@@ -249,12 +249,12 @@ abstract class StoragesControllerTest extends \Test\TestCase {
$authMech = $this->getAuthMechMock();
$authMech->method('validateStorage')
->willReturn(true);
- $authMech->method('isPermitted')
+ $authMech->method('isVisibleFor')
->willReturn(true);
$backend = $this->getBackendMock();
$backend->method('validateStorage')
->willReturn(true);
- $backend->method('isPermitted')
+ $backend->method('isVisibleFor')
->willReturn(true);
$storageConfig = new StorageConfig(255);
@@ -338,13 +338,13 @@ abstract class StoragesControllerTest extends \Test\TestCase {
$backend = $this->getBackendMock();
$backend->method('validateStorage')
->willReturn($backendValidate);
- $backend->method('isPermitted')
+ $backend->method('isVisibleFor')
->willReturn(true);
$authMech = $this->getAuthMechMock();
$authMech->method('validateStorage')
->will($this->returnValue($authMechValidate));
- $authMech->method('isPermitted')
+ $authMech->method('isVisibleFor')
->willReturn(true);
$storageConfig = new StorageConfig();
diff --git a/apps/files_external/tests/controller/userstoragescontrollertest.php b/apps/files_external/tests/controller/userstoragescontrollertest.php
index b61174b0797..33ef274c87c 100644
--- a/apps/files_external/tests/controller/userstoragescontrollertest.php
+++ b/apps/files_external/tests/controller/userstoragescontrollertest.php
@@ -40,6 +40,9 @@ class UserStoragesControllerTest extends StoragesControllerTest {
->disableOriginalConstructor()
->getMock();
+ $this->service->method('getVisibilityType')
+ ->willReturn(BackendService::VISIBILITY_PERSONAL);
+
$this->controller = new UserStoragesController(
'files_external',
$this->getMock('\OCP\IRequest'),
@@ -49,21 +52,15 @@ class UserStoragesControllerTest extends StoragesControllerTest {
}
public function testAddOrUpdateStorageDisallowedBackend() {
- $backend1 = $this->getBackendMock();
- $backend1->expects($this->once())
- ->method('isPermitted')
- ->with(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE)
- ->willReturn(false);
- $backend2 = $this->getBackendMock();
- $backend2->expects($this->once())
- ->method('isPermitted')
- ->with(BackendService::USER_PERSONAL, BackendService::PERMISSION_MODIFY)
+ $backend = $this->getBackendMock();
+ $backend->method('isVisibleFor')
+ ->with(BackendService::VISIBILITY_PERSONAL)
->willReturn(false);
$authMech = $this->getAuthMechMock();
$storageConfig = new StorageConfig(1);
$storageConfig->setMountPoint('mount');
- $storageConfig->setBackend($backend1);
+ $storageConfig->setBackend($backend);
$storageConfig->setAuthMechanism($authMech);
$storageConfig->setBackendOptions([]);
@@ -88,8 +85,6 @@ class UserStoragesControllerTest extends StoragesControllerTest {
$this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus());
- $storageConfig->setBackend($backend2);
-
$response = $this->controller->update(
1,
'mount',
diff --git a/apps/files_external/tests/service/backendservicetest.php b/apps/files_external/tests/service/backendservicetest.php
index b37b5e9b466..414a9eee2ec 100644
--- a/apps/files_external/tests/service/backendservicetest.php
+++ b/apps/files_external/tests/service/backendservicetest.php
@@ -83,11 +83,11 @@ class BackendServiceTest extends \Test\TestCase {
$backendAllowed = $this->getBackendMock('\User\Mount\Allowed');
$backendAllowed->expects($this->never())
- ->method('removePermission');
+ ->method('removeVisibility');
$backendNotAllowed = $this->getBackendMock('\User\Mount\NotAllowed');
$backendNotAllowed->expects($this->once())
- ->method('removePermission')
- ->with(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE | BackendService::PERMISSION_MOUNT);
+ ->method('removeVisibility')
+ ->with(BackendService::VISIBILITY_PERSONAL);
$backendAlias = $this->getMockBuilder('\OCA\Files_External\Lib\Backend\Backend')
->disableOriginalConstructor()
diff --git a/apps/files_external/tests/service/storagesservicetest.php b/apps/files_external/tests/service/storagesservicetest.php
index 28220c9bc2e..ddf52e6272e 100644
--- a/apps/files_external/tests/service/storagesservicetest.php
+++ b/apps/files_external/tests/service/storagesservicetest.php
@@ -305,6 +305,52 @@ abstract class StoragesServiceTest extends \Test\TestCase {
);
}
+ public function testGetStoragesBackendNotVisible() {
+ $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
+ $backend->expects($this->once())
+ ->method('isVisibleFor')
+ ->with($this->service->getVisibilityType())
+ ->willReturn(false);
+ $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
+ $authMechanism->method('isVisibleFor')
+ ->with($this->service->getVisibilityType())
+ ->willReturn(true);
+
+ $storage = new StorageConfig(255);
+ $storage->setMountPoint('mountpoint');
+ $storage->setBackend($backend);
+ $storage->setAuthMechanism($authMechanism);
+ $storage->setBackendOptions(['password' => 'testPassword']);
+
+ $newStorage = $this->service->addStorage($storage);
+
+ $this->assertCount(1, $this->service->getAllStorages());
+ $this->assertEmpty($this->service->getStorages());
+ }
+
+ public function testGetStoragesAuthMechanismNotVisible() {
+ $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
+ $backend->method('isVisibleFor')
+ ->with($this->service->getVisibilityType())
+ ->willReturn(true);
+ $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
+ $authMechanism->expects($this->once())
+ ->method('isVisibleFor')
+ ->with($this->service->getVisibilityType())
+ ->willReturn(false);
+
+ $storage = new StorageConfig(255);
+ $storage->setMountPoint('mountpoint');
+ $storage->setBackend($backend);
+ $storage->setAuthMechanism($authMechanism);
+ $storage->setBackendOptions(['password' => 'testPassword']);
+
+ $newStorage = $this->service->addStorage($storage);
+
+ $this->assertCount(1, $this->service->getAllStorages());
+ $this->assertEmpty($this->service->getStorages());
+ }
+
public static function createHookCallback($params) {
self::$hookCalls[] = array(
'signal' => Filesystem::signal_create_mount,
diff --git a/apps/files_external/tests/service/userglobalstoragesservicetest.php b/apps/files_external/tests/service/userglobalstoragesservicetest.php
index 867872f3683..b6dc952605d 100644
--- a/apps/files_external/tests/service/userglobalstoragesservicetest.php
+++ b/apps/files_external/tests/service/userglobalstoragesservicetest.php
@@ -209,7 +209,11 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
$expectedPrecedence
) {
$backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
+ $backend->method('isVisibleFor')
+ ->willReturn(true);
$authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
+ $authMechanism->method('isVisibleFor')
+ ->willReturn(true);
$storage1 = new StorageConfig();
$storage1->setMountPoint('mountpoint');
@@ -243,6 +247,16 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
}
}
+ public function testGetStoragesBackendNotVisible() {
+ // we don't test this here
+ $this->assertTrue(true);
+ }
+
+ public function testGetStoragesAuthMechanismNotVisible() {
+ // we don't test this here
+ $this->assertTrue(true);
+ }
+
public function testHooksAddStorage($a = null, $b = null, $c = null) {
// we don't test this here
$this->assertTrue(true);
diff --git a/apps/files_sharing/api/sharees.php b/apps/files_sharing/api/sharees.php
index 9e324078dad..734c267020f 100644
--- a/apps/files_sharing/api/sharees.php
+++ b/apps/files_sharing/api/sharees.php
@@ -62,6 +62,9 @@ class Sharees {
/** @var bool */
protected $shareWithGroupOnly = false;
+ /** @var bool */
+ protected $shareeEnumeration = true;
+
/** @var int */
protected $offset = 0;
@@ -134,7 +137,7 @@ class Sharees {
}
}
- if (sizeof($users) < $this->limit) {
+ if (!$this->shareeEnumeration || sizeof($users) < $this->limit) {
$this->reachedEndFor[] = 'users';
}
@@ -176,6 +179,10 @@ class Sharees {
]);
}
}
+
+ if (!$this->shareeEnumeration) {
+ $this->result['users'] = [];
+ }
}
/**
@@ -187,7 +194,7 @@ class Sharees {
$groups = $this->groupManager->search($search, $this->limit, $this->offset);
$groups = array_map(function (IGroup $group) { return $group->getGID(); }, $groups);
- if (sizeof($groups) < $this->limit) {
+ if (!$this->shareeEnumeration || sizeof($groups) < $this->limit) {
$this->reachedEndFor[] = 'groups';
}
@@ -233,6 +240,10 @@ class Sharees {
]);
}
}
+
+ if (!$this->shareeEnumeration) {
+ $this->result['groups'] = [];
+ }
}
/**
@@ -273,6 +284,10 @@ class Sharees {
}
}
+ if (!$this->shareeEnumeration) {
+ $this->result['remotes'] = [];
+ }
+
if (!$foundRemoteById && substr_count($search, '@') >= 1 && substr_count($search, ' ') === 0 && $this->offset === 0) {
$this->result['exact']['remotes'][] = [
'label' => $search,
@@ -322,6 +337,7 @@ class Sharees {
}
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
+ $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->limit = (int) $perPage;
$this->offset = $perPage * ($page - 1);
diff --git a/apps/files_sharing/tests/api/shareestest.php b/apps/files_sharing/tests/api/shareestest.php
index 5c5d5b0d309..91b8b1c7e66 100644
--- a/apps/files_sharing/tests/api/shareestest.php
+++ b/apps/files_sharing/tests/api/shareestest.php
@@ -110,16 +110,30 @@ class ShareesTest extends TestCase {
public function dataGetUsers() {
return [
- ['test', false, [], [], [], [], true, false],
- ['test', true, [], [], [], [], true, false],
+ ['test', false, true, [], [], [], [], true, false],
+ ['test', false, false, [], [], [], [], true, false],
+ ['test', true, true, [], [], [], [], true, false],
+ ['test', true, false, [], [], [], [], true, false],
[
- 'test', false, [], [],
+ 'test', false, true, [], [],
[
['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
], [], true, $this->getUserMock('test', 'Test')
],
[
- 'test', true, [], [],
+ 'test', false, false, [], [],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test', true, true, [], [],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test', true, false, [], [],
[
['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
], [], true, $this->getUserMock('test', 'Test')
@@ -127,6 +141,7 @@ class ShareesTest extends TestCase {
[
'test',
false,
+ true,
[],
[
$this->getUserMock('test1', 'Test One'),
@@ -141,6 +156,20 @@ class ShareesTest extends TestCase {
[
'test',
false,
+ false,
+ [],
+ [
+ $this->getUserMock('test1', 'Test One'),
+ ],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ false,
+ true,
[],
[
$this->getUserMock('test1', 'Test One'),
@@ -157,6 +186,21 @@ class ShareesTest extends TestCase {
[
'test',
false,
+ false,
+ [],
+ [
+ $this->getUserMock('test1', 'Test One'),
+ $this->getUserMock('test2', 'Test Two'),
+ ],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ false,
+ true,
[],
[
$this->getUserMock('test0', 'Test'),
@@ -175,6 +219,24 @@ class ShareesTest extends TestCase {
],
[
'test',
+ false,
+ false,
+ [],
+ [
+ $this->getUserMock('test0', 'Test'),
+ $this->getUserMock('test1', 'Test One'),
+ $this->getUserMock('test2', 'Test Two'),
+ ],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test0']],
+ ],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ true,
true,
['abc', 'xyz'],
[
@@ -191,6 +253,21 @@ class ShareesTest extends TestCase {
[
'test',
true,
+ false,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, ['test1' => 'Test One']],
+ ['xyz', 'test', 2, 0, []],
+ ],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ true,
['abc', 'xyz'],
[
['abc', 'test', 2, 0, [
@@ -213,6 +290,27 @@ class ShareesTest extends TestCase {
[
'test',
true,
+ false,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, [
+ 'test1' => 'Test One',
+ 'test2' => 'Test Two',
+ ]],
+ ['xyz', 'test', 2, 0, [
+ 'test1' => 'Test One',
+ 'test2' => 'Test Two',
+ ]],
+ ],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ true,
['abc', 'xyz'],
[
['abc', 'test', 2, 0, [
@@ -231,6 +329,26 @@ class ShareesTest extends TestCase {
false,
false,
],
+ [
+ 'test',
+ true,
+ false,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, [
+ 'test' => 'Test One',
+ ]],
+ ['xyz', 'test', 2, 0, [
+ 'test2' => 'Test Two',
+ ]],
+ ],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ],
+ [],
+ true,
+ false,
+ ],
];
}
@@ -239,6 +357,7 @@ class ShareesTest extends TestCase {
*
* @param string $searchTerm
* @param bool $shareWithGroupOnly
+ * @param bool $shareeEnumeration
* @param array $groupResponse
* @param array $userResponse
* @param array $exactExpected
@@ -246,10 +365,11 @@ class ShareesTest extends TestCase {
* @param bool $reachedEnd
* @param mixed $singleUser
*/
- public function testGetUsers($searchTerm, $shareWithGroupOnly, $groupResponse, $userResponse, $exactExpected, $expected, $reachedEnd, $singleUser) {
+ public function testGetUsers($searchTerm, $shareWithGroupOnly, $shareeEnumeration, $groupResponse, $userResponse, $exactExpected, $expected, $reachedEnd, $singleUser) {
$this->invokePrivate($this->sharees, 'limit', [2]);
$this->invokePrivate($this->sharees, 'offset', [0]);
$this->invokePrivate($this->sharees, 'shareWithGroupOnly', [$shareWithGroupOnly]);
+ $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
$user = $this->getUserMock('admin', 'Administrator');
$this->session->expects($this->any())
@@ -290,9 +410,10 @@ class ShareesTest extends TestCase {
public function dataGetGroups() {
return [
- ['test', false, [], [], [], [], true, false],
+ ['test', false, true, [], [], [], [], true, false],
+ ['test', false, false, [], [], [], [], true, false],
[
- 'test', false,
+ 'test', false, true,
[$this->getGroupMock('test1')],
[],
[],
@@ -301,7 +422,16 @@ class ShareesTest extends TestCase {
false,
],
[
- 'test', false,
+ 'test', false, false,
+ [$this->getGroupMock('test1')],
+ [],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', false, true,
[
$this->getGroupMock('test'),
$this->getGroupMock('test1'),
@@ -313,7 +443,19 @@ class ShareesTest extends TestCase {
false,
],
[
- 'test', false,
+ 'test', false, false,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', false, true,
[
$this->getGroupMock('test0'),
$this->getGroupMock('test1'),
@@ -328,7 +470,19 @@ class ShareesTest extends TestCase {
null,
],
[
- 'test', false,
+ 'test', false, false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [],
+ [],
+ true,
+ null,
+ ],
+ [
+ 'test', false, true,
[
$this->getGroupMock('test0'),
$this->getGroupMock('test1'),
@@ -344,9 +498,24 @@ class ShareesTest extends TestCase {
false,
$this->getGroupMock('test'),
],
- ['test', true, [], [], [], [], true, false],
[
- 'test', true,
+ 'test', false, false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [
+ ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
+ ],
+ [],
+ true,
+ $this->getGroupMock('test'),
+ ],
+ ['test', true, true, [], [], [], [], true, false],
+ ['test', true, false, [], [], [], [], true, false],
+ [
+ 'test', true, true,
[
$this->getGroupMock('test1'),
$this->getGroupMock('test2'),
@@ -358,7 +527,19 @@ class ShareesTest extends TestCase {
false,
],
[
- 'test', true,
+ 'test', true, false,
+ [
+ $this->getGroupMock('test1'),
+ $this->getGroupMock('test2'),
+ ],
+ [$this->getGroupMock('test1')],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', true, true,
[
$this->getGroupMock('test'),
$this->getGroupMock('test1'),
@@ -370,7 +551,19 @@ class ShareesTest extends TestCase {
false,
],
[
- 'test', true,
+ 'test', true, false,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test')],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', true, true,
[
$this->getGroupMock('test'),
$this->getGroupMock('test1'),
@@ -382,7 +575,19 @@ class ShareesTest extends TestCase {
false,
],
[
- 'test', true,
+ 'test', true, false,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test1')],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', true, true,
[
$this->getGroupMock('test'),
$this->getGroupMock('test1'),
@@ -394,7 +599,19 @@ class ShareesTest extends TestCase {
false,
],
[
- 'test', true,
+ 'test', true, false,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', true, true,
[
$this->getGroupMock('test0'),
$this->getGroupMock('test1'),
@@ -409,7 +626,19 @@ class ShareesTest extends TestCase {
null,
],
[
- 'test', true,
+ 'test', true, false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [],
+ [],
+ true,
+ null,
+ ],
+ [
+ 'test', true, true,
[
$this->getGroupMock('test0'),
$this->getGroupMock('test1'),
@@ -425,6 +654,20 @@ class ShareesTest extends TestCase {
false,
$this->getGroupMock('test'),
],
+ [
+ 'test', true, false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [
+ ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
+ ],
+ [],
+ true,
+ $this->getGroupMock('test'),
+ ],
];
}
@@ -433,6 +676,7 @@ class ShareesTest extends TestCase {
*
* @param string $searchTerm
* @param bool $shareWithGroupOnly
+ * @param bool $shareeEnumeration
* @param array $groupResponse
* @param array $userGroupsResponse
* @param array $exactExpected
@@ -440,10 +684,11 @@ class ShareesTest extends TestCase {
* @param bool $reachedEnd
* @param mixed $singleGroup
*/
- public function testGetGroups($searchTerm, $shareWithGroupOnly, $groupResponse, $userGroupsResponse, $exactExpected, $expected, $reachedEnd, $singleGroup) {
+ public function testGetGroups($searchTerm, $shareWithGroupOnly, $shareeEnumeration, $groupResponse, $userGroupsResponse, $exactExpected, $expected, $reachedEnd, $singleGroup) {
$this->invokePrivate($this->sharees, 'limit', [2]);
$this->invokePrivate($this->sharees, 'offset', [0]);
$this->invokePrivate($this->sharees, 'shareWithGroupOnly', [$shareWithGroupOnly]);
+ $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
$this->groupManager->expects($this->once())
->method('search')
@@ -480,10 +725,22 @@ class ShareesTest extends TestCase {
public function dataGetRemote() {
return [
- ['test', [], [], [], true],
+ ['test', [], true, [], [], true],
+ ['test', [], false, [], [], true],
+ [
+ 'test@remote',
+ [],
+ true,
+ [
+ ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
+ ],
+ [],
+ true,
+ ],
[
'test@remote',
[],
+ false,
[
['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
],
@@ -508,6 +765,7 @@ class ShareesTest extends TestCase {
],
],
],
+ true,
[],
[
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost']],
@@ -515,6 +773,29 @@ class ShareesTest extends TestCase {
true,
],
[
+ 'test',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ [],
+ [],
+ true,
+ ],
+ [
'test@remote',
[
[
@@ -532,6 +813,7 @@ class ShareesTest extends TestCase {
],
],
],
+ true,
[
['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
],
@@ -541,6 +823,31 @@ class ShareesTest extends TestCase {
true,
],
[
+ 'test@remote',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ [
+ ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
+ ],
+ [],
+ true,
+ ],
+ [
'username@localhost',
[
[
@@ -558,11 +865,36 @@ class ShareesTest extends TestCase {
],
],
],
+ true,
[
['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost']],
],
+ [],
+ true,
+ ],
+ [
+ 'username@localhost',
[
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
],
+ false,
+ [
+ ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost']],
+ ],
+ [],
true,
],
];
@@ -573,11 +905,13 @@ class ShareesTest extends TestCase {
*
* @param string $searchTerm
* @param array $contacts
+ * @param bool $shareeEnumeration
* @param array $exactExpected
* @param array $expected
* @param bool $reachedEnd
*/
- public function testGetRemote($searchTerm, $contacts, $exactExpected, $expected, $reachedEnd) {
+ public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $exactExpected, $expected, $reachedEnd) {
+ $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
$this->contactsManager->expects($this->any())
->method('search')
->with($searchTerm, ['CLOUD', 'FN'])
@@ -595,80 +929,84 @@ class ShareesTest extends TestCase {
$allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE];
return [
- [[], '', true, '', null, $allTypes, 1, 200, false],
+ [[], '', 'yes', true, '', null, $allTypes, 1, 200, false, true],
// Test itemType
[[
'search' => '',
- ], '', true, '', null, $allTypes, 1, 200, false],
+ ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true],
[[
'search' => 'foobar',
- ], '', true, 'foobar', null, $allTypes, 1, 200, false],
+ ], '', 'yes', true, 'foobar', null, $allTypes, 1, 200, false, true],
[[
'search' => 0,
- ], '', true, '0', null, $allTypes, 1, 200, false],
+ ], '', 'yes', true, '0', null, $allTypes, 1, 200, false, true],
// Test itemType
[[
'itemType' => '',
- ], '', true, '', '', $allTypes, 1, 200, false],
+ ], '', 'yes', true, '', '', $allTypes, 1, 200, false, true],
[[
'itemType' => 'folder',
- ], '', true, '', 'folder', $allTypes, 1, 200, false],
+ ], '', 'yes', true, '', 'folder', $allTypes, 1, 200, false, true],
[[
'itemType' => 0,
- ], '', true, '', '0', $allTypes, 1, 200, false],
+ ], '', 'yes', true, '', '0', $allTypes, 1, 200, false, true],
// Test shareType
[[
- ], '', true, '', null, $allTypes, 1, 200, false],
+ ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true],
[[
'shareType' => 0,
- ], '', true, '', null, [0], 1, 200, false],
+ ], '', 'yes', true, '', null, [0], 1, 200, false, true],
[[
'shareType' => '0',
- ], '', true, '', null, [0], 1, 200, false],
+ ], '', 'yes', true, '', null, [0], 1, 200, false, true],
[[
'shareType' => 1,
- ], '', true, '', null, [1], 1, 200, false],
+ ], '', 'yes', true, '', null, [1], 1, 200, false, true],
[[
'shareType' => 12,
- ], '', true, '', null, [], 1, 200, false],
+ ], '', 'yes', true, '', null, [], 1, 200, false, true],
[[
'shareType' => 'foobar',
- ], '', true, '', null, $allTypes, 1, 200, false],
+ ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true],
[[
'shareType' => [0, 1, 2],
- ], '', true, '', null, [0, 1], 1, 200, false],
+ ], '', 'yes', true, '', null, [0, 1], 1, 200, false, true],
[[
'shareType' => [0, 1],
- ], '', true, '', null, [0, 1], 1, 200, false],
+ ], '', 'yes', true, '', null, [0, 1], 1, 200, false, true],
[[
'shareType' => $allTypes,
- ], '', true, '', null, $allTypes, 1, 200, false],
+ ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true],
[[
'shareType' => $allTypes,
- ], '', false, '', null, [0, 1], 1, 200, false],
+ ], '', 'yes', false, '', null, [0, 1], 1, 200, false, true],
// Test pagination
[[
'page' => 1,
- ], '', true, '', null, $allTypes, 1, 200, false],
+ ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true],
[[
'page' => 10,
- ], '', true, '', null, $allTypes, 10, 200, false],
+ ], '', 'yes', true, '', null, $allTypes, 10, 200, false, true],
// Test perPage
[[
'perPage' => 1,
- ], '', true, '', null, $allTypes, 1, 1, false],
+ ], '', 'yes', true, '', null, $allTypes, 1, 1, false, true],
[[
'perPage' => 10,
- ], '', true, '', null, $allTypes, 1, 10, false],
+ ], '', 'yes', true, '', null, $allTypes, 1, 10, false, true],
// Test $shareWithGroupOnly setting
- [[], 'no', true, '', null, $allTypes, 1, 200, false],
- [[], 'yes', true, '', null, $allTypes, 1, 200, true],
+ [[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true],
+ [[], 'yes', 'yes', true, '', null, $allTypes, 1, 200, true, true],
+
+ // Test $shareeEnumeration setting
+ [[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true],
+ [[], 'no', 'no', true, '', null, $allTypes, 1, 200, false, false],
];
}
@@ -678,6 +1016,7 @@ class ShareesTest extends TestCase {
*
* @param array $getData
* @param string $apiSetting
+ * @param string $enumSetting
* @param bool $remoteSharingEnabled
* @param string $search
* @param string $itemType
@@ -685,18 +1024,22 @@ class ShareesTest extends TestCase {
* @param int $page
* @param int $perPage
* @param bool $shareWithGroupOnly
+ * @param bool $shareeEnumeration
*/
- public function testSearch($getData, $apiSetting, $remoteSharingEnabled, $search, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly) {
+ public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEnabled, $search, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly, $shareeEnumeration) {
$oldGet = $_GET;
$_GET = $getData;
$config = $this->getMockBuilder('OCP\IConfig')
->disableOriginalConstructor()
->getMock();
- $config->expects($this->once())
+ $config->expects($this->exactly(2))
->method('getAppValue')
- ->with('core', 'shareapi_only_share_with_group_members', 'no')
- ->willReturn($apiSetting);
+ ->with('core', $this->anything(), $this->anything())
+ ->willReturnMap([
+ ['core', 'shareapi_only_share_with_group_members', 'no', $apiSetting],
+ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', $enumSetting],
+ ]);
$sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees')
->setConstructorArgs([
@@ -735,6 +1078,7 @@ class ShareesTest extends TestCase {
$this->assertInstanceOf('\OC_OCS_Result', $sharees->search());
$this->assertSame($shareWithGroupOnly, $this->invokePrivate($sharees, 'shareWithGroupOnly'));
+ $this->assertSame($shareeEnumeration, $this->invokePrivate($sharees, 'shareeEnumeration'));
$_GET = $oldGet;
}
diff --git a/apps/user_ldap/js/wizard/wizardTabLoginFilter.js b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js
index b73d267d168..0316db5b61c 100644
--- a/apps/user_ldap/js/wizard/wizardTabLoginFilter.js
+++ b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js
@@ -71,7 +71,8 @@ OCA = OCA || {};
],
'ldap_login_filter_mode'
);
- _.bindAll(this, 'onVerifyClick');
+ _.bindAll(this, 'onVerifyClick', 'onTestLoginnameChange');
+ this.managedItems.ldap_test_loginname.$element.keyup(this.onTestLoginnameChange);
this.managedItems.ldap_test_loginname.$relatedElements.click(this.onVerifyClick);
},
@@ -231,6 +232,16 @@ OCA = OCA || {};
} else {
this.configModel.requestWizard('ldap_test_loginname', {ldap_test_loginname: testLogin});
}
+ },
+
+ /**
+ * enables/disables the "Verify Settings" button, depending whether
+ * the corresponding text input has a value or not
+ */
+ onTestLoginnameChange: function() {
+ var loginName = this.managedItems.ldap_test_loginname.$element.val();
+ var beDisabled = !_.isString(loginName) || !loginName.trim();
+ this.managedItems.ldap_test_loginname.$relatedElements.prop('disabled', beDisabled);
}
});
diff --git a/apps/user_ldap/templates/part.wizard-loginfilter.php b/apps/user_ldap/templates/part.wizard-loginfilter.php
index 8d9fccf24b8..a13931d9327 100644
--- a/apps/user_ldap/templates/part.wizard-loginfilter.php
+++ b/apps/user_ldap/templates/part.wizard-loginfilter.php
@@ -52,7 +52,7 @@
placeholder="<?php p($l->t('Test Loginname'));?>"
class="ldapVerifyInput"
title="Attempts to receive a DN for the given loginname and the current login filter"/>
- <button class="ldapVerifyLoginName" name="ldapTestLoginSettings" type="button">
+ <button class="ldapVerifyLoginName" name="ldapTestLoginSettings" type="button" disabled="disabled">
<?php p($l->t('Verify settings'));?>
</button>
</p>
diff --git a/core/ajax/share.php b/core/ajax/share.php
index 69b84564ab1..4546217def3 100644
--- a/core/ajax/share.php
+++ b/core/ajax/share.php
@@ -379,6 +379,16 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
}
}
+ $sharingAutocompletion = \OC::$server->getConfig()
+ ->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes');
+
+ if ($sharingAutocompletion !== 'yes') {
+ $searchTerm = strtolower($_GET['search']);
+ $shareWith = array_filter($shareWith, function($user) use ($searchTerm) {
+ return strtolower($user['label']) === $searchTerm
+ || strtolower($user['value']['shareWith']) === $searchTerm;
+ });
+ }
$sorter = new \OC\Share\SearchResultSorter((string)$_GET['search'],
'label',
diff --git a/core/css/fixes.css b/core/css/fixes.css
index 7ef44ba6909..e5dbeb137ab 100644
--- a/core/css/fixes.css
+++ b/core/css/fixes.css
@@ -115,3 +115,8 @@ select {
line-height: 38px;
}
+.lte8 input[type="checkbox"] + label:before { background-image: url('../img/actions/checkbox.png'); }
+.lte8 input[type="checkbox"].white + label:before { background-image: url('../img/actions/checkbox-white.png'); }
+.lte8 input[type="checkbox"]:checked + label:before { background-image: url('../img/actions/checkbox-checked.png'); }
+.lte8 input[type="checkbox"].white:checked + label:before { background-image: url('../img/actions/checkbox-checked-white.png'); }
+
diff --git a/core/img/actions/close.png b/core/img/actions/close.png
index ece33258e56..66e3c26cc65 100644
--- a/core/img/actions/close.png
+++ b/core/img/actions/close.png
Binary files differ
diff --git a/core/img/actions/close.svg b/core/img/actions/close.svg
index 4471dbc6301..e060da3f8bb 100644
--- a/core/img/actions/close.svg
+++ b/core/img/actions/close.svg
@@ -1,3 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
- <path d="M12.95,11.536,11.536,12.95,8,9.4142,4.4645,12.95,3.0503,11.536,6.5858,8,3.0503,4.4644,4.4645,3.0502,8,6.5858,11.516,3.0311,12.95,4.4644,9.4143,8z" fill="#000"/>
+ <defs>
+ <filter id="a" style="color-interpolation-filters:sRGB" height="1.5994" width="1.6006" y="-.29971" x="-.30029">
+ <feGaussianBlur stdDeviation="1.2386625"/>
+ </filter>
+ </defs>
+ <path d="m12.95 11.536-1.414 1.414-3.536-3.5358-3.5355 3.5358-1.4142-1.414 3.5355-3.536-3.5355-3.5356 1.4142-1.4142 3.5355 3.5356 3.516-3.5547 1.434 1.4333-3.5357 3.5356z" filter="url(#a)" stroke="#fff" stroke-width="2" fill="#fff"/>
+ <path d="m12.95 11.536-1.414 1.414-3.536-3.5358-3.5355 3.5358-1.4142-1.414 3.5355-3.536-3.5355-3.5356 1.4142-1.4142 3.5355 3.5356 3.516-3.5547 1.434 1.4333-3.5357 3.5356z"/>
</svg>
diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js
index 0c8b5f6f199..13396670aae 100644
--- a/core/js/shareitemmodel.js
+++ b/core/js/shareitemmodel.js
@@ -69,7 +69,7 @@
*/
var SHARE_RESPONSE_INT_PROPS = [
'id', 'file_parent', 'mail_send', 'file_source', 'item_source', 'permissions',
- 'storage', 'share_type', 'parent', 'stime', 'expiration'
+ 'storage', 'share_type', 'parent', 'stime'
];
/**
diff --git a/core/js/tests/specs/shareitemmodelSpec.js b/core/js/tests/specs/shareitemmodelSpec.js
index b169962f1d6..b4403e28475 100644
--- a/core/js/tests/specs/shareitemmodelSpec.js
+++ b/core/js/tests/specs/shareitemmodelSpec.js
@@ -169,7 +169,7 @@ describe('OC.Share.ShareItemModel', function() {
/* jshint camelcase: false */
shares: [{
displayname_owner: 'root',
- expiration: 1111,
+ expiration: '2015-10-12 00:00:00',
file_source: 123,
file_target: '/folder',
id: 20,
@@ -187,7 +187,7 @@ describe('OC.Share.ShareItemModel', function() {
uid_owner: 'root'
}, {
displayname_owner: 'root',
- expiration: 2222,
+ expiration: '2015-10-15 00:00:00',
file_source: 456,
file_target: '/file_in_folder.txt',
id: 21,
@@ -263,7 +263,7 @@ describe('OC.Share.ShareItemModel', function() {
reshare: {},
shares: [{
displayname_owner: 'root',
- expiration: '1403900000',
+ expiration: '2015-10-12 00:00:00',
file_source: '123',
file_target: '/folder',
id: '20',
@@ -301,7 +301,7 @@ describe('OC.Share.ShareItemModel', function() {
expect(share.share_type).toEqual(OC.Share.SHARE_TYPE_USER);
expect(share.share_with).toEqual('user1');
expect(share.stime).toEqual(1403884258);
- expect(share.expiration).toEqual(1403900000);
+ expect(share.expiration).toEqual('2015-10-12 00:00:00');
});
});
describe('hasUserShares', function() {
diff --git a/core/search/js/search.js b/core/search/js/search.js
index bc67eb0e154..4e83a070170 100644
--- a/core/search/js/search.js
+++ b/core/search/js/search.js
@@ -217,10 +217,10 @@
$status.addClass('emptycontent').removeClass('status');
$status.html('');
$status.append('<div class="icon-search"></div>');
- $status.append('<h2>' + t('core', 'No search results in other places') + '</h2>');
+ $status.append('<h2>' + t('core', 'No search results in other folders') + '</h2>');
} else {
$status.removeClass('emptycontent').addClass('status');
- $status.text(n('core', '{count} search result in other places', '{count} search results in other places', count, {count:count}));
+ $status.text(n('core', '{count} search result in another folder', '{count} search results in other folders', count, {count:count}));
}
}
function renderCurrent() {
diff --git a/core/shipped.json b/core/shipped.json
index 7993b61569c..ffa4ee9c738 100644
--- a/core/shipped.json
+++ b/core/shipped.json
@@ -3,11 +3,11 @@
"shippedApps": [
"activity",
"admin_audit",
+ "encryption",
"enterprise_key",
"external",
"files",
"files_antivirus",
- "encryption",
"files_external",
"files_ldap_home",
"files_locking",
@@ -21,6 +21,7 @@
"firewall",
"firstrunwizard",
"gallery",
+ "notifications",
"objectstore",
"provisioning_api",
"sharepoint",
@@ -29,7 +30,6 @@
"user_external",
"user_ldap",
"user_shibboleth",
- "user_webdavauth",
"windows_network_drive"
]
}
diff --git a/lib/private/app.php b/lib/private/app.php
index 6c9f7615228..5122a4964d4 100644
--- a/lib/private/app.php
+++ b/lib/private/app.php
@@ -411,7 +411,7 @@ class OC_App {
/**
* Returns the Settings Navigation
*
- * @return string
+ * @return string[]
*
* This function returns an array containing all settings pages added. The
* entries are sorted by the key 'order' ascending.
@@ -837,7 +837,7 @@ class OC_App {
$info['active'] = $active;
- if (isset($info['shipped']) and ($info['shipped'] == 'true')) {
+ if (self::isShipped($app)) {
$info['internal'] = true;
$info['level'] = self::officialApp;
$info['removable'] = false;
diff --git a/lib/private/connector/sabre/listenerplugin.php b/lib/private/connector/sabre/listenerplugin.php
index d0d40f4dc86..ec628add28b 100644
--- a/lib/private/connector/sabre/listenerplugin.php
+++ b/lib/private/connector/sabre/listenerplugin.php
@@ -21,6 +21,9 @@
namespace OC\Connector\Sabre;
+use OCP\AppFramework\Http;
+use OCP\SabrePluginEvent;
+use OCP\SabrePluginException;
use Sabre\DAV\ServerPlugin;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -49,9 +52,16 @@ class ListenerPlugin extends ServerPlugin {
* in case the system is in maintenance mode.
*
* @return bool
+ * @throws \Exception
*/
public function emitListener() {
- $this->dispatcher->dispatch('OC\Connector\Sabre::beforeMethod');
+ $event = new SabrePluginEvent();
+
+ $this->dispatcher->dispatch('OC\Connector\Sabre::beforeMethod', $event);
+
+ if ($event->getStatusCode() !== Http::STATUS_OK) {
+ throw new SabrePluginException($event->getMessage(), $event->getStatusCode());
+ }
return true;
}
diff --git a/lib/private/db/querybuilder/quotehelper.php b/lib/private/db/querybuilder/quotehelper.php
index 0735f313abc..4b62fee6a6c 100644
--- a/lib/private/db/querybuilder/quotehelper.php
+++ b/lib/private/db/querybuilder/quotehelper.php
@@ -52,7 +52,7 @@ class QuoteHelper {
return (string) $string;
}
- if ($string === null || $string === '*') {
+ if ($string === null || $string === 'null' || $string === '*') {
return $string;
}
diff --git a/lib/private/encryption/decryptall.php b/lib/private/encryption/decryptall.php
index 1ff9c74ef84..c1875f16abd 100644
--- a/lib/private/encryption/decryptall.php
+++ b/lib/private/encryption/decryptall.php
@@ -80,7 +80,7 @@ class DecryptAll {
$this->input = $input;
$this->output = $output;
- if ($user !== '' && $this->userManager->userExists($user) === false) {
+ if (!empty($user) && $this->userManager->userExists($user) === false) {
$this->output->writeln('User "' . $user . '" does not exist. Please check the username and try again');
return false;
}
diff --git a/lib/private/files/storage/wrapper/permissionsmask.php b/lib/private/files/storage/wrapper/permissionsmask.php
index 50c3f2a6268..8d40d023630 100644
--- a/lib/private/files/storage/wrapper/permissionsmask.php
+++ b/lib/private/files/storage/wrapper/permissionsmask.php
@@ -66,7 +66,7 @@ class PermissionsMask extends Wrapper {
}
public function isSharable($path) {
- return $this->checkMask(Constants::PERMISSION_SHARE) and parent::isSharable($parm);
+ return $this->checkMask(Constants::PERMISSION_SHARE) and parent::isSharable($path);
}
public function getPermissions($path) {
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index f92441492f7..95b688fef5c 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -153,7 +153,10 @@ class View {
return '/';
}
- if (strpos($path, $this->fakeRoot) !== 0) {
+ // missing slashes can cause wrong matches!
+ $root = rtrim($this->fakeRoot, '/') . '/';
+
+ if (strpos($path, $root) !== 0) {
return null;
} else {
$path = substr($path, strlen($this->fakeRoot));
diff --git a/lib/private/templatelayout.php b/lib/private/templatelayout.php
index 93bf6cbd307..ae3c1093b20 100644
--- a/lib/private/templatelayout.php
+++ b/lib/private/templatelayout.php
@@ -116,9 +116,14 @@ class OC_TemplateLayout extends OC_Template {
}
}
$userDisplayName = OC_User::getDisplayName();
+ $appsMgmtActive = strpos(\OC::$server->getRequest()->getRequestUri(), \OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')) === 0;
+ if ($appsMgmtActive) {
+ $l = \OC::$server->getL10N('lib');
+ $this->assign('application', $l->t('Apps'));
+ }
$this->assign('user_displayname', $userDisplayName);
$this->assign('user_uid', OC_User::getUser());
- $this->assign('appsmanagement_active', strpos(\OC::$server->getRequest()->getRequestUri(), \OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')) === 0 );
+ $this->assign('appsmanagement_active', $appsMgmtActive);
$this->assign('enableAvatars', $this->config->getSystemValue('enable_avatars', true));
$this->assign('userAvatarSet', \OC_Helper::userAvatarSet(OC_User::getUser()));
} else if ($renderAs == 'error') {
@@ -148,7 +153,7 @@ class OC_TemplateLayout extends OC_Template {
} else {
// Add the js files
$jsFiles = self::findJavascriptFiles(OC_Util::$scripts);
- $this->assign('jsfiles', array(), false);
+ $this->assign('jsfiles', array());
if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
$this->append( 'jsfiles', OC_Helper::linkToRoute('js_config', array('v' => self::$versionHash)));
}
diff --git a/lib/public/sabrepluginevent.php b/lib/public/sabrepluginevent.php
new file mode 100644
index 00000000000..fed3237166d
--- /dev/null
+++ b/lib/public/sabrepluginevent.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, 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 OCP;
+
+
+use OCP\AppFramework\Http;
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * @since 8.2.0
+ */
+class SabrePluginEvent extends Event {
+
+ /** @var int */
+ protected $statusCode;
+
+ /** @var string */
+ protected $message;
+
+ /**
+ * @since 8.2.0
+ */
+ public function __construct() {
+ $this->message = '';
+ $this->statusCode = Http::STATUS_OK;
+ }
+
+ /**
+ * @param int $statusCode
+ * @return self
+ * @since 8.2.0
+ */
+ public function setStatusCode($statusCode) {
+ $this->statusCode = (int) $statusCode;
+ return $this;
+ }
+
+ /**
+ * @param string $message
+ * @return self
+ * @since 8.2.0
+ */
+ public function setMessage($message) {
+ $this->message = (string) $message;
+ return $this;
+ }
+
+ /**
+ * @return int
+ * @since 8.2.0
+ */
+ public function getStatusCode() {
+ return $this->statusCode;
+ }
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getMessage() {
+ return $this->message;
+ }
+}
diff --git a/lib/public/sabrepluginexception.php b/lib/public/sabrepluginexception.php
new file mode 100644
index 00000000000..5dba3b90a02
--- /dev/null
+++ b/lib/public/sabrepluginexception.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, 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 OCP;
+
+
+use Sabre\DAV\Exception;
+
+/**
+ * @since 8.2.0
+ */
+class SabrePluginException extends Exception {
+
+ /**
+ * Returns the HTTP statuscode for this exception
+ *
+ * @return int
+ * @since 8.2.0
+ */
+ public function getHTTPCode() {
+ return $this->code;
+ }
+}
diff --git a/settings/admin.php b/settings/admin.php
index 38683438f3a..c8bf1d32749 100644
--- a/settings/admin.php
+++ b/settings/admin.php
@@ -122,6 +122,7 @@ $template->assign('allowPublicUpload', $appConfig->getValue('core', 'shareapi_al
$template->assign('allowResharing', $appConfig->getValue('core', 'shareapi_allow_resharing', 'yes'));
$template->assign('allowPublicMailNotification', $appConfig->getValue('core', 'shareapi_allow_public_notification', 'no'));
$template->assign('allowMailNotification', $appConfig->getValue('core', 'shareapi_allow_mail_notification', 'no'));
+$template->assign('allowShareDialogUserEnumeration', $appConfig->getValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes'));
$template->assign('onlyShareWithGroupMembers', \OC\Share\Share::shareWithGroupMembersOnly());
$databaseOverload = (strpos(\OCP\Config::getSystemValue('dbtype'), 'sqlite') !== false);
$template->assign('databaseOverload', $databaseOverload);
diff --git a/settings/templates/admin.php b/settings/templates/admin.php
index 36088d9f8c2..bfb0d5d364d 100644
--- a/settings/templates/admin.php
+++ b/settings/templates/admin.php
@@ -265,6 +265,11 @@ if ($_['cronErrors']) {
<br />
<em><?php p($l->t('These groups will still be able to receive shares, but not to initiate them.')); ?></em>
</p>
+ <p class="<?php if ($_['shareAPIEnabled'] === 'no') p('hidden');?>">
+ <input type="checkbox" name="shareapi_allow_share_dialog_user_enumeration" value="1" id="shareapi_allow_share_dialog_user_enumeration"
+ <?php if ($_['allowShareDialogUserEnumeration'] === 'yes') print_unescaped('checked="checked"'); ?> />
+ <label for="shareapi_allow_share_dialog_user_enumeration"><?php p($l->t('Allow username autocompletion in share dialog. If this is disabled the full username needs to be entered.'));?></label><br />
+ </p>
<?php print_unescaped($_['fileSharingSettings']); ?>
</div>
diff --git a/tests/lib/db/querybuilder/quotehelpertest.php b/tests/lib/db/querybuilder/quotehelpertest.php
index 904b4c500db..b83d9eed2df 100644
--- a/tests/lib/db/querybuilder/quotehelpertest.php
+++ b/tests/lib/db/querybuilder/quotehelpertest.php
@@ -43,6 +43,10 @@ class QuoteHelperTest extends \Test\TestCase {
[new Literal('literal'), 'literal'],
[new Literal(1), '1'],
[new Parameter(':param'), ':param'],
+
+ // (string) 'null' is Doctrines way to set columns to null
+ // See https://github.com/owncloud/core/issues/19314
+ ['null', 'null'],
];
}
diff --git a/tests/lib/encryption/decryptalltest.php b/tests/lib/encryption/decryptalltest.php
index c2a0711c0a0..ce5bcf1e5ae 100644
--- a/tests/lib/encryption/decryptalltest.php
+++ b/tests/lib/encryption/decryptalltest.php
@@ -82,11 +82,13 @@ class DecryptAllTest extends TestCase {
* @dataProvider dataTrueFalse
* @param bool $prepareResult
*/
- public function testDecryptAll($prepareResult) {
+ public function testDecryptAll($prepareResult, $user) {
- $user = 'user1';
-
- $this->userManager->expects($this->once())->method('userExists')->willReturn(true);
+ if (!empty($user)) {
+ $this->userManager->expects($this->once())->method('userExists')->willReturn(true);
+ } else {
+ $this->userManager->expects($this->never())->method('userExists');
+ }
/** @var DecryptAll | \PHPUnit_Framework_MockObject_MockObject | $instance */
$instance = $this->getMockBuilder('OC\Encryption\DecryptAll')
->setConstructorArgs(
@@ -117,8 +119,10 @@ class DecryptAllTest extends TestCase {
public function dataTrueFalse() {
return [
- [true],
- [false]
+ [true, 'user1'],
+ [false, 'user1'],
+ [true, ''],
+ [true, null]
];
}
diff --git a/tests/lib/files/storage/storage.php b/tests/lib/files/storage/storage.php
index fcd7f73dcde..d381b4cdf40 100644
--- a/tests/lib/files/storage/storage.php
+++ b/tests/lib/files/storage/storage.php
@@ -573,4 +573,29 @@ abstract class Storage extends \Test\TestCase {
$this->assertSameAsLorem($target);
$this->assertTrue($this->instance->file_exists($source), $source . ' was deleted');
}
+
+ public function testIsCreatable() {
+ $this->instance->mkdir('source');
+ $this->assertTrue($this->instance->isCreatable('source'));
+ }
+
+ public function testIsReadable() {
+ $this->instance->mkdir('source');
+ $this->assertTrue($this->instance->isReadable('source'));
+ }
+
+ public function testIsUpdatable() {
+ $this->instance->mkdir('source');
+ $this->assertTrue($this->instance->isUpdatable('source'));
+ }
+
+ public function testIsDeletable() {
+ $this->instance->mkdir('source');
+ $this->assertTrue($this->instance->isDeletable('source'));
+ }
+
+ public function testIsShareable() {
+ $this->instance->mkdir('source');
+ $this->assertTrue($this->instance->isSharable('source'));
+ }
}
diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php
index 83f53833855..ceeb9ba7a94 100644
--- a/tests/lib/files/view.php
+++ b/tests/lib/files/view.php
@@ -193,7 +193,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testGetPath() {
+ public function testGetPath() {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$storage3 = $this->getTestStorage();
@@ -219,7 +219,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testMountPointOverwrite() {
+ public function testMountPointOverwrite() {
$storage1 = $this->getTestStorage(false);
$storage2 = $this->getTestStorage();
$storage1->mkdir('substorage');
@@ -265,7 +265,7 @@ class View extends \Test\TestCase {
$appConfig->setValue('core', 'shareapi_exclude_groups_list', $oldExcludeGroupsList);
}
- function testCacheIncompleteFolder() {
+ public function testCacheIncompleteFolder() {
$storage1 = $this->getTestStorage(false);
\OC\Files\Filesystem::clearMounts();
\OC\Files\Filesystem::mount($storage1, array(), '/incomplete');
@@ -300,7 +300,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testSearch() {
+ public function testSearch() {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$storage3 = $this->getTestStorage();
@@ -350,7 +350,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testWatcher() {
+ public function testWatcher() {
$storage1 = $this->getTestStorage();
\OC\Files\Filesystem::mount($storage1, array(), '/');
$storage1->getWatcher()->setPolicy(Watcher::CHECK_ALWAYS);
@@ -371,7 +371,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testCopyBetweenStorageNoCross() {
+ public function testCopyBetweenStorageNoCross() {
$storage1 = $this->getTestStorage(true, '\Test\Files\TemporaryNoCross');
$storage2 = $this->getTestStorage(true, '\Test\Files\TemporaryNoCross');
$this->copyBetweenStorages($storage1, $storage2);
@@ -380,7 +380,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testCopyBetweenStorageCross() {
+ public function testCopyBetweenStorageCross() {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$this->copyBetweenStorages($storage1, $storage2);
@@ -389,7 +389,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testCopyBetweenStorageCrossNonLocal() {
+ public function testCopyBetweenStorageCrossNonLocal() {
$storage1 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal');
$storage2 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal');
$this->copyBetweenStorages($storage1, $storage2);
@@ -417,7 +417,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testMoveBetweenStorageNoCross() {
+ public function testMoveBetweenStorageNoCross() {
$storage1 = $this->getTestStorage(true, '\Test\Files\TemporaryNoCross');
$storage2 = $this->getTestStorage(true, '\Test\Files\TemporaryNoCross');
$this->moveBetweenStorages($storage1, $storage2);
@@ -426,7 +426,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testMoveBetweenStorageCross() {
+ public function testMoveBetweenStorageCross() {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$this->moveBetweenStorages($storage1, $storage2);
@@ -435,7 +435,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testMoveBetweenStorageCrossNonLocal() {
+ public function testMoveBetweenStorageCrossNonLocal() {
$storage1 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal');
$storage2 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal');
$this->moveBetweenStorages($storage1, $storage2);
@@ -458,7 +458,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testUnlink() {
+ public function testUnlink() {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
\OC\Files\Filesystem::mount($storage1, array(), '/');
@@ -481,7 +481,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testUnlinkRootMustFail() {
+ public function testUnlinkRootMustFail() {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
\OC\Files\Filesystem::mount($storage1, array(), '/');
@@ -500,7 +500,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testTouch() {
+ public function testTouch() {
$storage = $this->getTestStorage(true, '\Test\Files\TemporaryNoTouch');
\OC\Files\Filesystem::mount($storage, array(), '/');
@@ -524,7 +524,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testViewHooks() {
+ public function testViewHooks() {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$defaultRoot = \OC\Files\Filesystem::getRoot();
@@ -590,7 +590,7 @@ class View extends \Test\TestCase {
/**
* @medium
*/
- function testViewHooksIfRootStartsTheSame() {
+ public function testViewHooksIfRootStartsTheSame() {
$storage1 = $this->getTestStorage();
$storage2 = $this->getTestStorage();
$defaultRoot = \OC\Files\Filesystem::getRoot();
@@ -851,24 +851,98 @@ class View extends \Test\TestCase {
}
/**
- * @dataProvider relativePathProvider
+ * @dataProvider chrootRelativePathProvider
*/
- function testGetRelativePath($absolutePath, $expectedPath) {
+ function testChrootGetRelativePath($root, $absolutePath, $expectedPath) {
$view = new \OC\Files\View('/files');
- // simulate a external storage mount point which has a trailing slash
- $view->chroot('/files/');
+ $view->chroot($root);
$this->assertEquals($expectedPath, $view->getRelativePath($absolutePath));
}
- function relativePathProvider() {
+ public function chrootRelativePathProvider() {
+ return $this->relativePathProvider('/');
+ }
+
+ /**
+ * @dataProvider initRelativePathProvider
+ */
+ public function testInitGetRelativePath($root, $absolutePath, $expectedPath) {
+ $view = new \OC\Files\View($root);
+ $this->assertEquals($expectedPath, $view->getRelativePath($absolutePath));
+ }
+
+ public function initRelativePathProvider() {
+ return $this->relativePathProvider(null);
+ }
+
+ public function relativePathProvider($missingRootExpectedPath) {
return array(
- array('/files/', '/'),
- array('/files', '/'),
- array('/files/0', '0'),
- array('/files/false', 'false'),
- array('/files/true', 'true'),
- array('/files/test', 'test'),
- array('/files/test/foo', 'test/foo'),
+ // No root - returns the path
+ array('', '/files', '/files'),
+ array('', '/files/', '/files/'),
+
+ // Root equals path - /
+ array('/files/', '/files/', '/'),
+ array('/files/', '/files', '/'),
+ array('/files', '/files/', '/'),
+ array('/files', '/files', '/'),
+
+ // False negatives: chroot fixes those by adding the leading slash.
+ // But setting them up with this root (instead of chroot($root))
+ // will fail them, although they should be the same.
+ // TODO init should be fixed, so it also adds the leading slash
+ array('files/', '/files/', $missingRootExpectedPath),
+ array('files', '/files/', $missingRootExpectedPath),
+ array('files/', '/files', $missingRootExpectedPath),
+ array('files', '/files', $missingRootExpectedPath),
+
+ // False negatives: Paths provided to the method should have a leading slash
+ // TODO input should be checked to have a leading slash
+ array('/files/', 'files/', null),
+ array('/files', 'files/', null),
+ array('/files/', 'files', null),
+ array('/files', 'files', null),
+
+ // with trailing slashes
+ array('/files/', '/files/0', '0'),
+ array('/files/', '/files/false', 'false'),
+ array('/files/', '/files/true', 'true'),
+ array('/files/', '/files/test', 'test'),
+ array('/files/', '/files/test/foo', 'test/foo'),
+
+ // without trailing slashes
+ // TODO false expectation: Should match "with trailing slashes"
+ array('/files', '/files/0', '/0'),
+ array('/files', '/files/false', '/false'),
+ array('/files', '/files/true', '/true'),
+ array('/files', '/files/test', '/test'),
+ array('/files', '/files/test/foo', '/test/foo'),
+
+ // leading slashes
+ array('/files/', '/files_trashbin/', null),
+ array('/files', '/files_trashbin/', null),
+ array('/files/', '/files_trashbin', null),
+ array('/files', '/files_trashbin', null),
+
+ // no leading slashes
+ array('files/', 'files_trashbin/', null),
+ array('files', 'files_trashbin/', null),
+ array('files/', 'files_trashbin', null),
+ array('files', 'files_trashbin', null),
+
+ // mixed leading slashes
+ array('files/', '/files_trashbin/', null),
+ array('/files/', 'files_trashbin/', null),
+ array('files', '/files_trashbin/', null),
+ array('/files', 'files_trashbin/', null),
+ array('files/', '/files_trashbin', null),
+ array('/files/', 'files_trashbin', null),
+ array('files', '/files_trashbin', null),
+ array('/files', 'files_trashbin', null),
+
+ array('files', 'files_trashbin/test', null),
+ array('/files', '/files_trashbin/test', null),
+ array('/files', 'files_trashbin/test', null),
);
}
@@ -1012,6 +1086,7 @@ class View extends \Test\TestCase {
$storage2->expects($this->any())
->method('fopen')
->will($this->returnCallback(function ($path, $mode) use ($storage2) {
+ /** @var \PHPUnit_Framework_MockObject_MockObject | \OC\Files\Storage\Temporary $storage2 */
$source = fopen($storage2->getSourcePath($path), $mode);
return \OC\Files\Stream\Quota::wrap($source, 9);
}));
@@ -1020,7 +1095,7 @@ class View extends \Test\TestCase {
$storage1->file_put_contents('foo.txt', '0123456789ABCDEFGH');
$storage1->mkdir('dirtomove');
$storage1->file_put_contents('dirtomove/indir1.txt', '0123456'); // fits
- $storage1->file_put_contents('dirtomove/indir2.txt', '0123456789ABCDEFGH'); // doesn't fit
+ $storage1->file_put_contents('dirtomove/indir2.txt', '0123456789ABCDEFGH'); // doesn't fit
$storage2->file_put_contents('existing.txt', '0123');
$storage1->getScanner()->scan('');
$storage2->getScanner()->scan('');
@@ -1296,7 +1371,7 @@ class View extends \Test\TestCase {
$thrown = false;
try {
- // this actually acquires two locks, one on the mount point and one no the storage root,
+ // this actually acquires two locks, one on the mount point and one on the storage root,
// but the one on the storage root will fail
$view->lockFile('/mountpoint.txt', ILockingProvider::LOCK_SHARED);
} catch (\OCP\Lock\LockedException $e) {