Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorLukas Reschke <lukas@statuscode.ch>2014-03-20 19:31:12 +0400
committerLukas Reschke <lukas@statuscode.ch>2014-03-20 19:31:12 +0400
commit2c561c9c5072ce82e06bd5ab2c4ee81bc5d09d59 (patch)
treea34586bf389cc8011490031bba497129361655a3 /apps
parent316a22b46315a389e38cd9f1e320f3e1f0541d68 (diff)
parentd95fde39248e8c4083c14788fe3a327a60611b47 (diff)
Merge pull request #7794 from owncloud/extstorage-obfuscatepasswords
Obfuscate passwords in ext storage config
Diffstat (limited to 'apps')
-rw-r--r--apps/files_external/appinfo/app.php3
-rwxr-xr-xapps/files_external/lib/config.php188
-rw-r--r--apps/files_external/lib/smb.php2
-rw-r--r--apps/files_external/tests/mountconfig.php309
4 files changed, 486 insertions, 16 deletions
diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php
index 5b1cd86a170..0e83660f845 100644
--- a/apps/files_external/appinfo/app.php
+++ b/apps/files_external/appinfo/app.php
@@ -25,5 +25,6 @@ if (OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') == '
}
// connecting hooks
-OCP\Util::connectHook( 'OC_User', 'post_login', 'OC\Files\Storage\iRODS', 'login' );
+OCP\Util::connectHook('OC_Filesystem', 'post_initMountPoints', '\OC_Mount_Config', 'initMountPointsHook');
+OCP\Util::connectHook('OC_User', 'post_login', 'OC\Files\Storage\iRODS', 'login');
diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php
index 2c8828c4d51..ffbab7bca80 100755
--- a/apps/files_external/lib/config.php
+++ b/apps/files_external/lib/config.php
@@ -4,6 +4,7 @@
*
* @author Michael Gapczynski
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
+* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@@ -19,10 +20,16 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+set_include_path(
+ get_include_path() . PATH_SEPARATOR .
+ \OC_App::getAppPath('files_external') . '/3rdparty/phpseclib/phpseclib'
+);
+
/**
-* Class to configure the config/mount.php and data/$user/mount.php files
-*/
+ * Class to configure mount.json globally and for users
+ */
class OC_Mount_Config {
+ // TODO: make this class non-static and give it a proper namespace
const MOUNT_TYPE_GLOBAL = 'global';
const MOUNT_TYPE_GROUP = 'group';
@@ -42,6 +49,7 @@ class OC_Mount_Config {
*/
public static function getBackends() {
+ // FIXME: do not rely on php key order for the options order in the UI
$backends['\OC\Files\Storage\Local']=array(
'backend' => 'Local',
'configuration' => array(
@@ -159,6 +167,96 @@ class OC_Mount_Config {
}
/**
+ * Hook that mounts the given user's visible mount points
+ * @param array $data
+ */
+ public static function initMountPointsHook($data) {
+ $mountPoints = self::getAbsoluteMountPoints($data['user']);
+ foreach ($mountPoints as $mountPoint => $options) {
+ \OC\Files\Filesystem::mount($options['class'], $options['options'], $mountPoint);
+ }
+ }
+
+ /**
+ * Returns the mount points for the given user.
+ * The mount point is relative to the data directory.
+ *
+ * @param string $user user
+ * @return array of mount point string as key, mountpoint config as value
+ */
+ public static function getAbsoluteMountPoints($user) {
+ $mountPoints = array();
+
+ $datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data");
+ $mount_file = \OC_Config::getValue("mount_file", $datadir . "/mount.json");
+
+ //move config file to it's new position
+ if (is_file(\OC::$SERVERROOT . '/config/mount.json')) {
+ rename(\OC::$SERVERROOT . '/config/mount.json', $mount_file);
+ }
+
+ // Load system mount points
+ $mountConfig = self::readData(false);
+ if (isset($mountConfig[self::MOUNT_TYPE_GLOBAL])) {
+ foreach ($mountConfig[self::MOUNT_TYPE_GLOBAL] as $mountPoint => $options) {
+ $options['options'] = self::decryptPasswords($options['options']);
+ $mountPoints[$mountPoint] = $options;
+ }
+ }
+ if (isset($mountConfig[self::MOUNT_TYPE_GROUP])) {
+ foreach ($mountConfig[self::MOUNT_TYPE_GROUP] as $group => $mounts) {
+ if (\OC_Group::inGroup($user, $group)) {
+ foreach ($mounts as $mountPoint => $options) {
+ $mountPoint = self::setUserVars($user, $mountPoint);
+ foreach ($options as &$option) {
+ $option = self::setUserVars($user, $option);
+ }
+ $options['options'] = self::decryptPasswords($options['options']);
+ $mountPoints[$mountPoint] = $options;
+ }
+ }
+ }
+ }
+ if (isset($mountConfig[self::MOUNT_TYPE_USER])) {
+ foreach ($mountConfig[self::MOUNT_TYPE_USER] as $mountUser => $mounts) {
+ if ($mountUser === 'all' or strtolower($mountUser) === strtolower($user)) {
+ foreach ($mounts as $mountPoint => $options) {
+ $mountPoint = self::setUserVars($user, $mountPoint);
+ foreach ($options as &$option) {
+ $option = self::setUserVars($user, $option);
+ }
+ $options['options'] = self::decryptPasswords($options['options']);
+ $mountPoints[$mountPoint] = $options;
+ }
+ }
+ }
+ }
+
+ // Load personal mount points
+ $mountConfig = self::readData(true);
+ if (isset($mountConfig[self::MOUNT_TYPE_USER][$user])) {
+ foreach ($mountConfig[self::MOUNT_TYPE_USER][$user] as $mountPoint => $options) {
+ $options['options'] = self::decryptPasswords($options['options']);
+ $mountPoints[$mountPoint] = $options;
+ }
+ }
+
+ return $mountPoints;
+ }
+
+ /**
+ * fill in the correct values for $user
+ *
+ * @param string $user
+ * @param string $input
+ * @return string
+ */
+ private static function setUserVars($user, $input) {
+ return str_replace('$user', $user, $input);
+ }
+
+
+ /**
* Get details on each of the external storage backends, used for the mount config UI
* Some backends are not available as a personal backend, f.e. Local and such that have
* been disabled by the admin.
@@ -203,6 +301,7 @@ class OC_Mount_Config {
if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
$mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15);
}
+ $mount['options'] = self::decryptPasswords($mount['options']);
// Remove '/$user/files/' from mount point
$mountPoint = substr($mountPoint, 13);
// Merge the mount point into the current mount points
@@ -228,6 +327,7 @@ class OC_Mount_Config {
if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
$mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15);
}
+ $mount['options'] = self::decryptPasswords($mount['options']);
// Remove '/$user/files/' from mount point
$mountPoint = substr($mountPoint, 13);
// Merge the mount point into the current mount points
@@ -265,6 +365,7 @@ class OC_Mount_Config {
if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
$mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15);
}
+ $mount['options'] = self::decryptPasswords($mount['options']);
// Remove '/uid/files/' from mount point
$personal[substr($mountPoint, strlen($uid) + 8)] = array(
'class' => $mount['class'],
@@ -277,12 +378,18 @@ class OC_Mount_Config {
return $personal;
}
+ /**
+ * Test connecting using the given backend configuration
+ * @param string $class backend class name
+ * @param array $options backend configuration options
+ * @return bool true if the connection succeeded, false otherwise
+ */
private static function getBackendStatus($class, $options) {
if (self::$skipTest) {
return true;
}
foreach ($options as &$option) {
- $option = str_replace('$user', OCP\User::getUser(), $option);
+ $option = self::setUserVars(OCP\User::getUser(), $option);
}
if (class_exists($class)) {
try {
@@ -334,7 +441,13 @@ class OC_Mount_Config {
} else {
$mountPoint = '/$user/files/'.ltrim($mountPoint, '/');
}
- $mount = array($applicable => array($mountPoint => array('class' => $class, 'options' => $classOptions)));
+
+ $mount = array($applicable => array(
+ $mountPoint => array(
+ 'class' => $class,
+ 'options' => self::encryptPasswords($classOptions))
+ )
+ );
$mountPoints = self::readData($isPersonal);
// Merge the new mount point into the current mount points
if (isset($mountPoints[$mountType])) {
@@ -527,4 +640,71 @@ class OC_Mount_Config {
return $txt;
}
+
+ /**
+ * Encrypt passwords in the given config options
+ * @param array $options mount options
+ * @return array updated options
+ */
+ private static function encryptPasswords($options) {
+ if (isset($options['password'])) {
+ $options['password_encrypted'] = self::encryptPassword($options['password']);
+ // do not unset the password, we want to keep the keys order
+ // on load... because that's how the UI currently works
+ $options['password'] = '';
+ }
+ return $options;
+ }
+
+ /**
+ * Decrypt passwords in the given config options
+ * @param array $options mount options
+ * @return array updated options
+ */
+ private static function decryptPasswords($options) {
+ // note: legacy options might still have the unencrypted password in the "password" field
+ if (isset($options['password_encrypted'])) {
+ $options['password'] = self::decryptPassword($options['password_encrypted']);
+ unset($options['password_encrypted']);
+ }
+ return $options;
+ }
+
+ /**
+ * Encrypt a single password
+ * @param string $password plain text password
+ * @return encrypted password
+ */
+ private static function encryptPassword($password) {
+ $cipher = self::getCipher();
+ $iv = \OCP\Util::generateRandomBytes(16);
+ $cipher->setIV($iv);
+ return base64_encode($iv . $cipher->encrypt($password));
+ }
+
+ /**
+ * Decrypts a single password
+ * @param string $encryptedPassword encrypted password
+ * @return plain text password
+ */
+ private static function decryptPassword($encryptedPassword) {
+ $cipher = self::getCipher();
+ $binaryPassword = base64_decode($encryptedPassword);
+ $iv = substr($binaryPassword, 0, 16);
+ $cipher->setIV($iv);
+ $binaryPassword = substr($binaryPassword, 16);
+ return $cipher->decrypt($binaryPassword);
+ }
+
+ /**
+ * Returns the encryption cipher
+ */
+ private static function getCipher() {
+ if (!class_exists('Crypt_AES', false)) {
+ include('Crypt/AES.php');
+ }
+ $cipher = new Crypt_AES(CRYPT_AES_MODE_CBC);
+ $cipher->setKey(\OCP\Config::getSystemValue('passwordsalt'));
+ return $cipher;
+ }
}
diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php
index c5fba92ee68..f3f3b3ed7f3 100644
--- a/apps/files_external/lib/smb.php
+++ b/apps/files_external/lib/smb.php
@@ -37,7 +37,7 @@ class SMB extends \OC\Files\Storage\StreamWrapper{
$this->share = substr($this->share, 0, -1);
}
} else {
- throw new \Exception();
+ throw new \Exception('Invalid configuration');
}
}
diff --git a/apps/files_external/tests/mountconfig.php b/apps/files_external/tests/mountconfig.php
index a22c7424c69..bf43bb31c38 100644
--- a/apps/files_external/tests/mountconfig.php
+++ b/apps/files_external/tests/mountconfig.php
@@ -40,9 +40,22 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
private $oldAllowedBackends;
private $allBackends;
+ const TEST_USER1 = 'user1';
+ const TEST_USER2 = 'user2';
+ const TEST_GROUP1 = 'group1';
+ const TEST_GROUP2 = 'group2';
+
public function setUp() {
- \OC_User::setUserId('test');
- $this->userHome = \OC_User::getHome('test');
+ \OC_User::createUser(self::TEST_USER1, self::TEST_USER1);
+ \OC_User::createUser(self::TEST_USER2, self::TEST_USER2);
+
+ \OC_Group::createGroup(self::TEST_GROUP1);
+ \OC_Group::addToGroup(self::TEST_USER1, self::TEST_GROUP1);
+ \OC_Group::createGroup(self::TEST_GROUP2);
+ \OC_Group::addToGroup(self::TEST_USER2, self::TEST_GROUP2);
+
+ \OC_User::setUserId(self::TEST_USER1);
+ $this->userHome = \OC_User::getHome(self::TEST_USER1);
mkdir($this->userHome);
$this->dataDir = \OC_Config::getValue(
@@ -67,9 +80,12 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
public function tearDown() {
OC_Mount_Config::$skipTest = false;
+ \OC_User::deleteUser(self::TEST_USER2);
+ \OC_User::deleteUser(self::TEST_USER1);
+ \OC_Group::deleteGroup(self::TEST_GROUP1);
+ \OC_Group::deleteGroup(self::TEST_GROUP2);
+
@unlink($this->dataDir . '/mount.json');
- @unlink($this->userHome . '/mount.json');
- rmdir($this->userHome);
OCP\Config::setAppValue(
'files_external',
@@ -95,6 +111,14 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
}
/**
+ * Write the user config, to simulate existing files
+ */
+ private function writeUserConfig($config) {
+ $configFile = $this->userHome . '/mount.json';
+ file_put_contents($configFile, json_encode($config));
+ }
+
+ /**
* Test mount point validation
*/
public function testAddMountPointValidation() {
@@ -113,7 +137,7 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
* Test adding a global mount point
*/
public function testAddGlobalMountPoint() {
- $mountType = OC_Mount_Config::MOUNT_TYPE_GLOBAL;
+ $mountType = OC_Mount_Config::MOUNT_TYPE_USER;
$applicable = 'all';
$isPersonal = false;
@@ -135,7 +159,7 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
*/
public function testAddMountPointSingleUser() {
$mountType = OC_Mount_Config::MOUNT_TYPE_USER;
- $applicable = 'test';
+ $applicable = self::TEST_USER1;
$isPersonal = true;
$this->assertEquals(true, OC_Mount_Config::addMountPoint('/ext', '\OC\Files\Storage\SFTP', array(), $mountType, $applicable, $isPersonal));
@@ -144,10 +168,10 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
$this->assertEquals(1, count($config));
$this->assertTrue(isset($config[$mountType]));
$this->assertTrue(isset($config[$mountType][$applicable]));
- $this->assertTrue(isset($config[$mountType][$applicable]['/test/files/ext']));
+ $this->assertTrue(isset($config[$mountType][$applicable]['/' . self::TEST_USER1 . '/files/ext']));
$this->assertEquals(
'\OC\Files\Storage\SFTP',
- $config[$mountType][$applicable]['/test/files/ext']['class']
+ $config[$mountType][$applicable]['/' . self::TEST_USER1 . '/files/ext']['class']
);
}
@@ -156,7 +180,7 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
*/
public function testAddDisallowedBackendMountPointSingleUser() {
$mountType = OC_Mount_Config::MOUNT_TYPE_USER;
- $applicable = 'test';
+ $applicable = self::TEST_USER1;
$isPersonal = true;
// local
@@ -181,9 +205,274 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
public function testAddMountPointUnexistClass() {
$storageClass = 'Unexist_Storage';
$mountType = OC_Mount_Config::MOUNT_TYPE_USER;
- $applicable = 'test';
+ $applicable = self::TEST_USER1;
$isPersonal = false;
$this->assertFalse(OC_Mount_Config::addMountPoint('/ext', $storageClass, array(), $mountType, $applicable, $isPersonal));
}
+
+ /**
+ * Test reading and writing global config
+ */
+ public function testReadWriteGlobalConfig() {
+ $mountType = OC_Mount_Config::MOUNT_TYPE_USER;
+ $applicable = 'all';
+ $isPersonal = false;
+ $mountConfig = array(
+ 'host' => 'smbhost',
+ 'user' => 'smbuser',
+ 'password' => 'smbpassword',
+ 'share' => 'smbshare',
+ 'root' => 'smbroot'
+ );
+
+ // write config
+ $this->assertTrue(
+ OC_Mount_Config::addMountPoint(
+ '/ext',
+ '\OC\Files\Storage\SMB',
+ $mountConfig,
+ $mountType,
+ $applicable,
+ $isPersonal
+ )
+ );
+
+ // re-read config
+ $config = OC_Mount_Config::getSystemMountPoints();
+ $this->assertEquals(1, count($config));
+ $this->assertTrue(isset($config['ext']));
+ $this->assertEquals('\OC\Files\Storage\SMB', $config['ext']['class']);
+ $savedMountConfig = $config['ext']['configuration'];
+ $this->assertEquals($mountConfig, $savedMountConfig);
+ // key order needs to be preserved for the UI...
+ $this->assertEquals(array_keys($mountConfig), array_keys($savedMountConfig));
+ }
+
+ /**
+ * Test reading and writing config
+ */
+ public function testReadWritePersonalConfig() {
+ $mountType = OC_Mount_Config::MOUNT_TYPE_USER;
+ $applicable = self::TEST_USER1;
+ $isPersonal = true;
+ $mountConfig = array(
+ 'host' => 'smbhost',
+ 'user' => 'smbuser',
+ 'password' => 'smbpassword',
+ 'share' => 'smbshare',
+ 'root' => 'smbroot'
+ );
+
+ // write config
+ $this->assertTrue(
+ OC_Mount_Config::addMountPoint(
+ '/ext',
+ '\OC\Files\Storage\SMB',
+ $mountConfig,
+ $mountType,
+ $applicable,
+ $isPersonal
+ )
+ );
+
+ // re-read config
+ $config = OC_Mount_Config::getPersonalMountPoints();
+ $this->assertEquals(1, count($config));
+ $this->assertTrue(isset($config['ext']));
+ $this->assertEquals('\OC\Files\Storage\SMB', $config['ext']['class']);
+ $savedMountConfig = $config['ext']['configuration'];
+ $this->assertEquals($mountConfig, $savedMountConfig);
+ // key order needs to be preserved for the UI...
+ $this->assertEquals(array_keys($mountConfig), array_keys($savedMountConfig));
+ }
+
+ /**
+ * Test password obfuscation
+ */
+ public function testPasswordObfuscation() {
+ $mountType = OC_Mount_Config::MOUNT_TYPE_USER;
+ $applicable = self::TEST_USER1;
+ $isPersonal = true;
+ $mountConfig = array(
+ 'host' => 'smbhost',
+ 'user' => 'smbuser',
+ 'password' => 'smbpassword',
+ 'share' => 'smbshare',
+ 'root' => 'smbroot'
+ );
+
+ // write config
+ $this->assertTrue(
+ OC_Mount_Config::addMountPoint(
+ '/ext',
+ '\OC\Files\Storage\SMB',
+ $mountConfig,
+ $mountType,
+ $applicable,
+ $isPersonal
+ )
+ );
+
+ // note: password re-reading is covered by testReadWritePersonalConfig
+
+ // check that password inside the file is NOT in plain text
+ $config = $this->readUserConfig();
+ $savedConfig = $config[$mountType][$applicable]['/' . self::TEST_USER1 . '/files/ext']['options'];
+
+ // no more clear text password in file (kept because of key order)
+ $this->assertEquals('', $savedConfig['password']);
+
+ // encrypted password is present
+ $this->assertNotEquals($mountConfig['password'], $savedConfig['password_encrypted']);
+ }
+
+ /**
+ * Test read legacy passwords
+ */
+ public function testReadLegacyPassword() {
+ $mountType = OC_Mount_Config::MOUNT_TYPE_USER;
+ $applicable = self::TEST_USER1;
+ $isPersonal = true;
+ $mountConfig = array(
+ 'host' => 'smbhost',
+ 'user' => 'smbuser',
+ 'password' => 'smbpassword',
+ 'share' => 'smbshare',
+ 'root' => 'smbroot'
+ );
+
+ // write config
+ $this->assertTrue(
+ OC_Mount_Config::addMountPoint(
+ '/ext',
+ '\OC\Files\Storage\SMB',
+ $mountConfig,
+ $mountType,
+ $applicable,
+ $isPersonal
+ )
+ );
+
+ $config = $this->readUserConfig();
+ // simulate non-encrypted password situation
+ $config[$mountType][$applicable]['/' . self::TEST_USER1 . '/files/ext']['options']['password'] = 'smbpasswd';
+
+ $this->writeUserConfig($config);
+
+ // re-read config, password was read correctly
+ $config = OC_Mount_Config::getPersonalMountPoints();
+ $savedMountConfig = $config['ext']['configuration'];
+ $this->assertEquals($mountConfig, $savedMountConfig);
+ }
+
+ public function mountDataProvider() {
+ return array(
+ // Tests for visible mount points
+ // system mount point for all users
+ array(
+ false,
+ OC_Mount_Config::MOUNT_TYPE_USER,
+ 'all',
+ self::TEST_USER1,
+ true,
+ ),
+ // system mount point for a specific user
+ array(
+ false,
+ OC_Mount_Config::MOUNT_TYPE_USER,
+ self::TEST_USER1,
+ self::TEST_USER1,
+ true,
+ ),
+ // system mount point for a specific group
+ array(
+ false,
+ OC_Mount_Config::MOUNT_TYPE_GROUP,
+ self::TEST_GROUP1,
+ self::TEST_USER1,
+ true,
+ ),
+ // user mount point
+ array(
+ true,
+ OC_Mount_Config::MOUNT_TYPE_USER,
+ self::TEST_USER1,
+ self::TEST_USER1,
+ true,
+ ),
+
+ // Tests for non-visible mount points
+ // system mount point for another user
+ array(
+ false,
+ OC_Mount_Config::MOUNT_TYPE_USER,
+ self::TEST_USER2,
+ self::TEST_USER1,
+ false,
+ ),
+ // system mount point for a specific group
+ array(
+ false,
+ OC_Mount_Config::MOUNT_TYPE_GROUP,
+ self::TEST_GROUP2,
+ self::TEST_USER1,
+ false,
+ ),
+ // user mount point
+ array(
+ true,
+ OC_Mount_Config::MOUNT_TYPE_USER,
+ self::TEST_USER1,
+ self::TEST_USER2,
+ false,
+ ),
+ );
+ }
+
+ /**
+ * Test mount points used at mount time, making sure
+ * the configuration is prepared properly.
+ *
+ * @dataProvider mountDataProvider
+ * @param bool $isPersonal true for personal mount point, false for system mount point
+ * @param string $mountType mount type
+ * @param string $applicable target user/group or "all"
+ * @param string $testUser user for which to retrieve the mount points
+ * @param bool $expectVisible whether to expect the mount point to be visible for $testUser
+ */
+ public function testMount($isPersonal, $mountType, $applicable, $testUser, $expectVisible) {
+ $mountConfig = array(
+ 'host' => 'someost',
+ 'user' => 'someuser',
+ 'password' => 'somepassword',
+ 'root' => 'someroot'
+ );
+
+ // add mount point as "test" user
+ $this->assertTrue(
+ OC_Mount_Config::addMountPoint(
+ '/ext',
+ '\OC\Files\Storage\SMB',
+ $mountConfig,
+ $mountType,
+ $applicable,
+ $isPersonal
+ )
+ );
+
+ // check mount points in the perspective of user $testUser
+ \OC_User::setUserId($testUser);
+
+ $mountPoints = OC_Mount_Config::getAbsoluteMountPoints($testUser);
+ if ($expectVisible) {
+ $this->assertEquals(1, count($mountPoints));
+ $this->assertTrue(isset($mountPoints['/' . self::TEST_USER1 . '/files/ext']));
+ $this->assertEquals('\OC\Files\Storage\SMB', $mountPoints['/' . self::TEST_USER1 . '/files/ext']['class']);
+ $this->assertEquals($mountConfig, $mountPoints['/' . self::TEST_USER1 . '/files/ext']['options']);
+ }
+ else {
+ $this->assertEquals(0, count($mountPoints));
+ }
+ }
}