diff options
Diffstat (limited to 'apps')
29 files changed, 1084 insertions, 405 deletions
diff --git a/apps/files_encryption/lib/hooks.php b/apps/files_encryption/lib/hooks.php index bddfb7b2544..7ddde0a3112 100644 --- a/apps/files_encryption/lib/hooks.php +++ b/apps/files_encryption/lib/hooks.php @@ -25,8 +25,6 @@ namespace OCA\Files_Encryption;
-use OC\Files\Filesystem;
-
/**
* Class for hook specific logic
*/
@@ -364,15 +362,16 @@ class Hooks { if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
$view = new \OC\Files\View('/');
- $userId = \OCP\User::getUser();
+ $userId = $params['uidOwner'];
+ $userView = new \OC\Files\View('/' . $userId . '/files');
$util = new Util($view, $userId);
- $path = \OC\Files\Filesystem::getPath($params['fileSource']);
+ $path = $userView->getPath($params['fileSource']);
// for group shares get a list of the group members
if ($params['shareType'] === \OCP\Share::SHARE_TYPE_GROUP) {
$userIds = \OC_Group::usersInGroup($params['shareWith']);
} else {
- if ($params['shareType'] === \OCP\Share::SHARE_TYPE_LINK) {
+ if ($params['shareType'] === \OCP\Share::SHARE_TYPE_LINK || $params['shareType'] === \OCP\Share::SHARE_TYPE_REMOTE) {
$userIds = array($util->getPublicShareKeyId());
} else {
$userIds = array($params['shareWith']);
@@ -619,8 +618,8 @@ class Hooks { // check if the user still has access to the file, otherwise delete share key
$sharingUsers = \OCP\Share::getUsersSharingFile($path, $user);
- if (!in_array(\OCP\User::getUser(), $sharingUsers['users'])) {
- Keymanager::delShareKey($view, array(\OCP\User::getUser()), $keyPath, $owner, $ownerPath);
+ if (!in_array($user, $sharingUsers['users'])) {
+ Keymanager::delShareKey($view, array($user), $keyPath, $owner, $ownerPath);
}
}
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index ad6948b95a6..4aaf7aa2571 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -1207,13 +1207,7 @@ class Util { // handle public access if ($this->isPublic) { - $filename = $path; - $fileOwnerUid = $this->userId; - - return array( - $fileOwnerUid, - $filename - ); + return array($this->userId, $path); } else { // Check that UID is valid diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index 9c53c73aafa..d29e6a191c8 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -115,6 +115,91 @@ class Share extends TestCase { parent::tearDownAfterClass(); } + /** + * @medium + */ + function testDeclineServer2ServerShare() { + + $config = $this->getMockBuilder('\OCP\IConfig') + ->disableOriginalConstructor()->getMock(); + $certificateManager = $this->getMock('\OCP\ICertificateManager'); + $httpHelperMock = $this->getMockBuilder('\OC\HTTPHelper') + ->setConstructorArgs(array($config, $certificateManager)) + ->getMock(); + $httpHelperMock->expects($this->once())->method('post')->with($this->anything())->will($this->returnValue(true)); + + self::loginHelper(self::TEST_ENCRYPTION_SHARE_USER1); + + // save file with content + $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort); + + // test that data was successfully written + $this->assertTrue(is_int($cryptedFile)); + + // get the file info from previous created file + $fileInfo = $this->view->getFileInfo( + '/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename); + + + // share the file + $token = \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, '', \OCP\Constants::PERMISSION_ALL); + $this->assertTrue(is_string($token)); + + $publicShareKeyId = \OC::$server->getConfig()->getAppValue('files_encryption', 'publicShareKeyId'); + + // check if share key for public exists + $this->assertTrue($this->view->file_exists( + '/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/' + . $this->filename . '/' . $publicShareKeyId . '.shareKey')); + + // manipulate share + $query = \OC::$server->getDatabaseConnection()->prepare('UPDATE `*PREFIX*share` SET `share_type` = ?, `share_with` = ? WHERE `token`=?'); + $this->assertTrue($query->execute(array(\OCP\Share::SHARE_TYPE_REMOTE, 'foo@bar', $token))); + + // check if share key not exists + $this->assertTrue($this->view->file_exists( + '/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/' + . $this->filename . '/' . $publicShareKeyId . '.shareKey')); + + + $query = \OC::$server->getDatabaseConnection()->prepare('SELECT * FROM `*PREFIX*share` WHERE `token`=?'); + $query->execute(array($token)); + + $share = $query->fetch(); + + $this->registerHttpHelper($httpHelperMock); + $_POST['token'] = $token; + $s2s = new \OCA\Files_Sharing\API\Server2Server(); + $s2s->declineShare(array('id' => $share['id'])); + $this->restoreHttpHelper(); + + $this->assertFalse($this->view->file_exists( + '/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/' + . $this->filename . '/' . $publicShareKeyId . '.shareKey')); + + } + + + /** + * Register an http helper mock for testing purposes. + * @param $httpHelper http helper mock + */ + private function registerHttpHelper($httpHelper) { + $this->oldHttpHelper = \OC::$server->query('HTTPHelper'); + \OC::$server->registerService('HTTPHelper', function ($c) use ($httpHelper) { + return $httpHelper; + }); + } + + /** + * Restore the original http helper + */ + private function restoreHttpHelper() { + $oldHttpHelper = $this->oldHttpHelper; + \OC::$server->registerService('HTTPHelper', function ($c) use ($oldHttpHelper) { + return $oldHttpHelper; + }); + } /** * @medium @@ -285,7 +370,7 @@ class Share extends TestCase { // save file with content $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' - . $this->filename, $this->dataShort); + . $this->filename, $this->dataShort); // test that data was successfully written $this->assertTrue(is_int($cryptedFile)); @@ -677,7 +762,7 @@ class Share extends TestCase { // save file with content $cryptedFile1 = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort); $cryptedFile2 = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' - . $this->filename, $this->dataShort); + . $this->filename, $this->dataShort); // test that data was successfully written $this->assertTrue(is_int($cryptedFile1)); @@ -784,7 +869,7 @@ class Share extends TestCase { // save file with content $cryptedFile1 = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER2. '/files/' . $this->filename, $this->dataShort); $cryptedFile2 = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' - . $this->filename, $this->dataShort); + . $this->filename, $this->dataShort); // test that data was successfully written $this->assertTrue(is_int($cryptedFile1)); @@ -925,8 +1010,8 @@ class Share extends TestCase { // remove share file $this->view->unlink('/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/' - . $this->filename . '/' . self::TEST_ENCRYPTION_SHARE_USER3 - . '.shareKey'); + . $this->filename . '/' . self::TEST_ENCRYPTION_SHARE_USER3 + . '.shareKey'); // re-enable the file proxy \OC_FileProxy::$enabled = $proxyStatus; @@ -990,7 +1075,7 @@ class Share extends TestCase { // move the file to a subfolder $this->view->rename('/' . self::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename, - '/' . self::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->filename); + '/' . self::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->filename); // check if we can read the moved file $retrievedRenamedFile = $this->view->file_get_contents( @@ -1122,4 +1207,4 @@ class Share extends TestCase { \OC\Files\Filesystem::unlink($folder); } -} +}
\ No newline at end of file diff --git a/apps/files_sharing/ajax/external.php b/apps/files_sharing/ajax/external.php index 6d68b5f7f82..1a709eda07c 100644 --- a/apps/files_sharing/ajax/external.php +++ b/apps/files_sharing/ajax/external.php @@ -31,10 +31,11 @@ if(!\OCP\Util::isValidFileName($name)) { } $externalManager = new \OCA\Files_Sharing\External\Manager( - \OC::$server->getDatabaseConnection(), - \OC\Files\Filesystem::getMountManager(), - \OC\Files\Filesystem::getLoader(), - \OC::$server->getUserSession() + \OC::$server->getDatabaseConnection(), + \OC\Files\Filesystem::getMountManager(), + \OC\Files\Filesystem::getLoader(), + \OC::$server->getUserSession(), + \OC::$server->getHTTPHelper() ); $name = OCP\Files::buildNotExistingFileName('/', $name); @@ -44,7 +45,7 @@ if (substr($remote, 0, 5) === 'https' and !OC_Util::getUrlContent($remote)) { \OCP\JSON::error(array('data' => array('message' => $l->t("Invalid or untrusted SSL certificate")))); exit; } else { - $mount = $externalManager->addShare($remote, $token, $password, $name, $owner); + $mount = $externalManager->addShare($remote, $token, $password, $name, $owner, true); /** * @var \OCA\Files_Sharing\External\Storage $storage */ diff --git a/apps/files_sharing/api/server2server.php b/apps/files_sharing/api/server2server.php index 2949e2dd09c..f78d64caa73 100644 --- a/apps/files_sharing/api/server2server.php +++ b/apps/files_sharing/api/server2server.php @@ -34,7 +34,7 @@ class Server2Server { public function createShare($params) { if (!$this->isS2SEnabled(true)) { - return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing'); + return new \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing'); } $remote = isset($_POST['remote']) ? $_POST['remote'] : null; @@ -42,7 +42,7 @@ class Server2Server { $name = isset($_POST['name']) ? $_POST['name'] : null; $owner = isset($_POST['owner']) ? $_POST['owner'] : null; $shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null; - $remoteId = isset($_POST['remote_id']) ? (int)$_POST['remote_id'] : null; + $remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null; if ($remote && $token && $name && $owner && $remoteId && $shareWith) { @@ -56,19 +56,28 @@ class Server2Server { \OC_Util::setupFS($shareWith); - $mountPoint = \OC\Files\Filesystem::normalizePath('/' . $name); + $externalManager = new \OCA\Files_Sharing\External\Manager( + \OC::$server->getDatabaseConnection(), + \OC\Files\Filesystem::getMountManager(), + \OC\Files\Filesystem::getLoader(), + \OC::$server->getUserSession(), + \OC::$server->getHTTPHelper()); + $name = \OCP\Files::buildNotExistingFileName('/', $name); try { - \OCA\Files_Sharing\Helper::addServer2ServerShare($remote, $token, $name, $mountPoint, $owner, $shareWith, '', $remoteId); + $externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId); + + $user = $owner . '@' . $this->cleanupRemote($remote); \OC::$server->getActivityManager()->publishActivity( - 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_RECEIVED, array($owner), '', array(), - '', '', $shareWith, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW); + 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_RECEIVED, array($user), '', array(), + '', '', $shareWith, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW); return new \OC_OCS_Result(); } catch (\Exception $e) { - return new \OC_OCS_Result(null, 500, 'server can not add remote share, ' . $e->getMessage()); + \OCP\Util::writeLog('files_sharing', 'server can not add remote share, ' . $e->getMessage(), \OCP\Util::ERROR); + return new \OC_OCS_Result(null, 500, 'internal server error, was not able to add share from ' . $remote); } } @@ -84,7 +93,7 @@ class Server2Server { public function acceptShare($params) { if (!$this->isS2SEnabled()) { - return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing'); + return new \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing'); } $id = $params['id']; @@ -95,8 +104,8 @@ class Server2Server { list($file, $link) = self::getFile($share['uid_owner'], $share['file_source']); \OC::$server->getActivityManager()->publishActivity( - 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_ACCEPTED, array($share['share_with'], basename($file)), '', array(), - $file, $link, $share['uid_owner'], \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW); + 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_ACCEPTED, array($share['share_with'], basename($file)), '', array(), + $file, $link, $share['uid_owner'], \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW); } return new \OC_OCS_Result(); @@ -111,7 +120,7 @@ class Server2Server { public function declineShare($params) { if (!$this->isS2SEnabled()) { - return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing'); + return new \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing'); } $id = $params['id']; @@ -126,8 +135,8 @@ class Server2Server { list($file, $link) = $this->getFile($share['uid_owner'], $share['file_source']); \OC::$server->getActivityManager()->publishActivity( - 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_DECLINED, array($share['share_with'], basename($file)), '', array(), - $file, $link, $share['uid_owner'], \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW); + 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_DECLINED, array($share['share_with'], basename($file)), '', array(), + $file, $link, $share['uid_owner'], \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW); } return new \OC_OCS_Result(); @@ -142,7 +151,7 @@ class Server2Server { public function unshare($params) { if (!$this->isS2SEnabled()) { - return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing'); + return new \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing'); } $id = $params['id']; @@ -154,7 +163,9 @@ class Server2Server { if ($token && $id && !empty($share)) { - $owner = $share['owner'] . '@' . $share['remote']; + $remote = $this->cleanupRemote($share['remote']); + + $owner = $share['owner'] . '@' . $remote; $mountpoint = $share['mountpoint']; $user = $share['user']; @@ -162,13 +173,19 @@ class Server2Server { $query->execute(array($id, $token)); \OC::$server->getActivityManager()->publishActivity( - 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_DECLINED, array($owner, $mountpoint), '', array(), - '', '', $user, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_MEDIUM); + 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_UNSHARED, array($owner, $mountpoint), '', array(), + '', '', $user, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_MEDIUM); } return new \OC_OCS_Result(); } + private function cleanupRemote($remote) { + $remote = substr($remote, strpos($remote, '://') + 3); + + return rtrim($remote, '/'); + } + /** * get share * diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php index 41bdf554fc5..dd9509575b7 100644 --- a/apps/files_sharing/appinfo/routes.php +++ b/apps/files_sharing/appinfo/routes.php @@ -1,5 +1,16 @@ <?php +namespace OCA\Files_Sharing\AppInfo; + +use OCA\Files_Sharing\Application; + +$application = new Application(); +$application->registerRoutes($this, [ + 'resources' => [ + 'ExternalShares' => ['url' => '/api/externalShares'], + ] +]); + /** @var $this \OCP\Route\IRouter */ $this->create('core_ajax_public_preview', '/publicpreview')->action( function() { @@ -16,31 +27,32 @@ $this->create('sharing_external_add', '/external') ->actionInclude('files_sharing/ajax/external.php'); $this->create('sharing_external_test_remote', '/testremote') ->actionInclude('files_sharing/ajax/testremote.php'); + // OCS API //TODO: SET: mail notification, waiting for PR #4689 to be accepted -OC_API::register('get', +\OC_API::register('get', '/apps/files_sharing/api/v1/shares', array('\OCA\Files_Sharing\API\Local', 'getAllShares'), 'files_sharing'); -OC_API::register('post', +\OC_API::register('post', '/apps/files_sharing/api/v1/shares', array('\OCA\Files_Sharing\API\Local', 'createShare'), 'files_sharing'); -OC_API::register('get', +\OC_API::register('get', '/apps/files_sharing/api/v1/shares/{id}', array('\OCA\Files_Sharing\API\Local', 'getShare'), 'files_sharing'); -OC_API::register('put', +\OC_API::register('put', '/apps/files_sharing/api/v1/shares/{id}', array('\OCA\Files_Sharing\API\Local', 'updateShare'), 'files_sharing'); -OC_API::register('delete', +\OC_API::register('delete', '/apps/files_sharing/api/v1/shares/{id}', array('\OCA\Files_Sharing\API\Local', 'deleteShare'), 'files_sharing'); diff --git a/apps/files_sharing/application.php b/apps/files_sharing/application.php index 089ed6afbda..9fe8785df0b 100644 --- a/apps/files_sharing/application.php +++ b/apps/files_sharing/application.php @@ -11,6 +11,7 @@ namespace OCA\Files_Sharing; use OC\AppFramework\Utility\SimpleContainer; +use OCA\Files_Sharing\Controllers\ExternalSharesController; use OCA\Files_Sharing\Controllers\ShareController; use OCA\Files_Sharing\Middleware\SharingCheckMiddleware; use \OCP\AppFramework\App; @@ -44,6 +45,14 @@ class Application extends App { $c->query('ServerContainer')->getLogger() ); }); + $container->registerService('ExternalSharesController', function(SimpleContainer $c) { + return new ExternalSharesController( + $c->query('AppName'), + $c->query('Request'), + $c->query('IsIncomingShareEnabled'), + $c->query('ExternalManager') + ); + }); /** * Core class wrappers @@ -54,6 +63,18 @@ class Application extends App { $container->registerService('URLGenerator', function(SimpleContainer $c) { return $c->query('ServerContainer')->getUrlGenerator(); }); + $container->registerService('IsIncomingShareEnabled', function(SimpleContainer $c) { + return Helper::isIncomingServer2serverShareEnabled(); + }); + $container->registerService('ExternalManager', function(SimpleContainer $c) { + return new \OCA\Files_Sharing\External\Manager( + \OC::$server->getDatabaseConnection(), + \OC\Files\Filesystem::getMountManager(), + \OC\Files\Filesystem::getLoader(), + \OC::$server->getUserSession(), + \OC::$server->getHTTPHelper() + ); + }); /** * Middleware diff --git a/apps/files_sharing/js/external.js b/apps/files_sharing/js/external.js index 6ede2584cd9..aeb4b2461f8 100644 --- a/apps/files_sharing/js/external.js +++ b/apps/files_sharing/js/external.js @@ -8,16 +8,6 @@ * */ (function () { - var addExternalShare = function (remote, token, owner, name, password) { - return $.post(OC.generateUrl('apps/files_sharing/external'), { - remote: remote, - token: token, - owner: owner, - name: name, - password: password - }); - }; - /** * Shows "add external share" dialog. * @@ -27,20 +17,12 @@ * @param {String} token authentication token * @param {bool} passwordProtected true if the share is password protected */ - OCA.Sharing.showAddExternalDialog = function (remote, token, owner, name, passwordProtected) { + OCA.Sharing.showAddExternalDialog = function (share, passwordProtected, callback) { + var remote = share.remote; + var owner = share.owner; + var name = share.name; var remoteClean = (remote.substr(0, 8) === 'https://') ? remote.substr(8) : remote.substr(7); - var callback = function (add, password) { - password = password || ''; - if (add) { - addExternalShare(remote, token, owner, name, password).then(function (result) { - if (result.status === 'error') { - OC.Notification.show(result.data.message); - } else { - FileList.reload(); - } - }); - } - }; + if (!passwordProtected) { OC.dialogs.confirm( t( @@ -49,7 +31,9 @@ {name: name, owner: owner, remote: remoteClean} ), t('files_sharing','Remote share'), - callback, + function (result) { + callback(result, share); + }, true ).then(this._adjustDialog); } else { @@ -60,7 +44,9 @@ {name: name, owner: owner, remote: remoteClean} ), t('files_sharing','Remote share'), - callback, + function (result) { + callback(result, share); + }, true, t('files_sharing','Remote share password'), true @@ -82,17 +68,66 @@ $(document).ready(function () { // FIXME: HACK: do not init when running unit tests, need a better way if (!window.TESTING && OCA.Files) {// only run in the files app var params = OC.Util.History.parseUrlQuery(); + + //manually add server-to-server share if (params.remote && params.token && params.owner && params.name) { + + var callbackAddShare = function(result, share) { + var password = share.password || ''; + if (result) { + //$.post(OC.generateUrl('/apps/files_sharing/api/externalShares'), {id: share.id}); + $.post(OC.generateUrl('apps/files_sharing/external'), { + remote: share.remote, + token: share.token, + owner: share.owner, + name: share.name, + password: password}, function(result) { + if (result.status === 'error') { + OC.Notification.show(result.data.message); + } else { + FileList.reload(); + } + }); + } + }; + // clear hash, it is unlikely that it contain any extra parameters location.hash = ''; params.passwordProtected = parseInt(params.protected, 10) === 1; OCA.Sharing.showAddExternalDialog( - params.remote, - params.token, - params.owner, - params.name, - params.passwordProtected + params, + params.passwordProtected, + callbackAddShare ); } + + // check for new server-to-server shares which need to be approved + $.get(OC.generateUrl('/apps/files_sharing/api/externalShares'), + {}, + function(shares) { + var index; + for (index = 0; index < shares.length; ++index) { + OCA.Sharing.showAddExternalDialog( + shares[index], + false, + function(result, share) { + if (result) { + // Accept + $.post(OC.generateUrl('/apps/files_sharing/api/externalShares'), {id: share.id}); + FileList.reload(); + } else { + // Delete + $.ajax({ + url: OC.generateUrl('/apps/files_sharing/api/externalShares/'+share.id), + type: 'DELETE' + }); + } + } + ); + } + + }); + } + }); diff --git a/apps/files_sharing/lib/activity.php b/apps/files_sharing/lib/activity.php index 979df1c1da6..868830d80cd 100644 --- a/apps/files_sharing/lib/activity.php +++ b/apps/files_sharing/lib/activity.php @@ -98,7 +98,7 @@ class Activity implements \OCP\Activity\IExtension { case self::SUBJECT_REMOTE_SHARE_DECLINED: return $l->t('%1$s declined remote share %2$s', $params)->__toString(); case self::SUBJECT_REMOTE_SHARE_UNSHARED: - return $l->t('%1$s unshared %2$s', $params)->__toString(); + return $l->t('%1$s unshared %2$s from you', $params)->__toString(); } } } diff --git a/apps/files_sharing/lib/connector/publicauth.php b/apps/files_sharing/lib/connector/publicauth.php index 4144dafa379..a630d091fd4 100644 --- a/apps/files_sharing/lib/connector/publicauth.php +++ b/apps/files_sharing/lib/connector/publicauth.php @@ -69,6 +69,8 @@ class PublicAuth extends \Sabre\DAV\Auth\Backend\AbstractBasic { } else { return false; } + } elseif ($linkItem['share_type'] == \OCP\Share::SHARE_TYPE_REMOTE) { + return true; } else { return false; } diff --git a/apps/files_sharing/lib/controllers/externalsharescontroller.php b/apps/files_sharing/lib/controllers/externalsharescontroller.php new file mode 100644 index 00000000000..773ff8ce981 --- /dev/null +++ b/apps/files_sharing/lib/controllers/externalsharescontroller.php @@ -0,0 +1,86 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * @copyright 2014 Lukas Reschke + * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\Files_Sharing\Controllers; + +use OC; +use OCP; +use OCP\AppFramework\Controller; +use OCP\IRequest; +use OCP\AppFramework\Http\JSONResponse; + +/** + * Class ExternalSharesController + * + * @package OCA\Files_Sharing\Controllers + */ +class ExternalSharesController extends Controller { + + /** @var bool */ + private $incomingShareEnabled; + /** @var \OCA\Files_Sharing\External\Manager */ + private $externalManager; + + /** + * @param string $appName + * @param IRequest $request + * @param \OCA\Files_Sharing\External\Manager $externalManager + */ + public function __construct($appName, + IRequest $request, + $incomingShareEnabled, + \OCA\Files_Sharing\External\Manager $externalManager) { + parent::__construct($appName, $request); + $this->incomingShareEnabled = $incomingShareEnabled; + $this->externalManager = $externalManager; + } + + /** + * @NoAdminRequired + * + * @return JSONResponse + */ + public function index() { + $shares = []; + if ($this->incomingShareEnabled) { + $shares = $this->externalManager->getOpenShares(); + } + return new JSONResponse($shares); + } + + /** + * @NoAdminRequired + * + * @param int $id + * @return JSONResponse + */ + public function create($id) { + if ($this->incomingShareEnabled) { + $this->externalManager->acceptShare($id); + } + + return new JSONResponse(); + } + + /** + * @NoAdminRequired + * + * @param $id + * @return JSONResponse + */ + public function destroy($id) { + if ($this->incomingShareEnabled) { + $this->externalManager->declineShare($id); + } + + return new JSONResponse(); + } + +} diff --git a/apps/files_sharing/lib/external/manager.php b/apps/files_sharing/lib/external/manager.php index b52e1a5044e..665e47c0fe9 100644 --- a/apps/files_sharing/lib/external/manager.php +++ b/apps/files_sharing/lib/external/manager.php @@ -34,25 +34,41 @@ class Manager { private $userSession; /** + * @var \OC\HTTPHelper + */ + private $httpHelper; + + /** * @param \OCP\IDBConnection $connection * @param \OC\Files\Mount\Manager $mountManager * @param \OC\User\Session $userSession * @param \OC\Files\Storage\StorageFactory $storageLoader */ public function __construct(\OCP\IDBConnection $connection, \OC\Files\Mount\Manager $mountManager, - \OC\Files\Storage\StorageFactory $storageLoader, \OC\User\Session $userSession) { + \OC\Files\Storage\StorageFactory $storageLoader, \OC\User\Session $userSession, \OC\HTTPHelper $httpHelper) { $this->connection = $connection; $this->mountManager = $mountManager; $this->userSession = $userSession; $this->storageLoader = $storageLoader; + $this->httpHelper = $httpHelper; } - public function addShare($remote, $token, $password, $name, $owner) { - $user = $this->userSession->getUser(); - if ($user) { - $mountPoint = Filesystem::normalizePath('/' . $name); - \OCA\Files_Sharing\Helper::addServer2ServerShare($remote, $token, $name, $mountPoint, $owner, $user->getUID(), $password, -1, true); + public function addShare($remote, $token, $password, $name, $owner, $accepted=false, $user = null, $remoteId = -1) { + + $user = $user ? $user: $this->userSession->getUser()->getUID(); + $accepted = $accepted ? 1 : 0; + $mountPoint = Filesystem::normalizePath('/' . $name); + + $query = $this->connection->prepare(' + INSERT INTO `*PREFIX*share_external` + (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + '); + $hash = md5($mountPoint); + $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId)); + + if ($accepted) { $options = array( 'remote' => $remote, 'token' => $token, @@ -87,12 +103,85 @@ class Manager { } } + /** + * get share + * + * @param int $id share id + * @return mixed share of false + */ + private function getShare($id) { + $getShare = $this->connection->prepare(' + SELECT `remote`, `share_token` + FROM `*PREFIX*share_external` + WHERE `id` = ? AND `user` = ?'); + $result = $getShare->execute(array($id, $this->userSession->getUser()->getUID())); + + return $result ? $getShare->fetch() : false; + } + + /** + * accept server-to-server share + * + * @param int $id + */ + public function acceptShare($id) { + + $share = $this->getShare($id); + + if ($share) { + $acceptShare = $this->connection->prepare(' + UPDATE `*PREFIX*share_external` + SET `accepted` = ? + WHERE `id` = ? AND `user` = ?'); + $acceptShare->execute(array(1, $id, $this->userSession->getUser()->getUID())); + $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $id, 'accept'); + } + } + + /** + * decline server-to-server share + * + * @param int $id + */ + public function declineShare($id) { + + $share = $this->getShare($id); + + if ($share) { + $removeShare = $this->connection->prepare(' + DELETE FROM `*PREFIX*share_external` WHERE `id` = ? AND `user` = ?'); + $removeShare->execute(array($id, $this->userSession->getUser()->getUID())); + $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $id, 'decline'); + } + } + + /** + * inform remote server whether server-to-server share was accepted/declined + * + * @param string $remote + * @param string $token + * @param int $id + * @param string $feedback + * @return boolean + */ + private function sendFeedbackToRemote($remote, $token, $id, $feedback) { + + $url = $remote . \OCP\Share::BASE_PATH_TO_SHARE_API . '/' . $id . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT; + $fields = array('token' => $token); + + $result = $this->httpHelper->post($url, $fields); + $status = json_decode($result['result'], true); + + return ($result['success'] && $status['ocs']['meta']['statuscode'] === 100); + } + public static function setup() { $externalManager = new \OCA\Files_Sharing\External\Manager( - \OC::$server->getDatabaseConnection(), - \OC\Files\Filesystem::getMountManager(), - \OC\Files\Filesystem::getLoader(), - \OC::$server->getUserSession() + \OC::$server->getDatabaseConnection(), + \OC\Files\Filesystem::getMountManager(), + \OC\Files\Filesystem::getLoader(), + \OC::$server->getUserSession(), + \OC::$server->getHTTPHelper() ); $externalManager->setupMounts(); } @@ -151,6 +240,18 @@ class Manager { $user = $this->userSession->getUser(); $mountPoint = $this->stripPath($mountPoint); $hash = md5($mountPoint); + + $getShare = $this->connection->prepare(' + SELECT `remote`, `share_token`, `remote_id` + FROM `*PREFIX*share_external` + WHERE `mountpoint_hash` = ? AND `user` = ?'); + $result = $getShare->execute(array($hash, $user->getUID())); + + if ($result) { + $share = $getShare->fetch(); + $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); + } + $query = $this->connection->prepare(' DELETE FROM `*PREFIX*share_external` WHERE `mountpoint_hash` = ? @@ -158,4 +259,17 @@ class Manager { '); return (bool)$query->execute(array($hash, $user->getUID())); } -} + + /** + * return a list of shares which are not yet accepted by the user + * + * @return array list of open server-to-server shares + */ + public function getOpenShares() { + $openShares = $this->connection->prepare('SELECT * FROM `*PREFIX*share_external` WHERE `accepted` = ? AND `user` = ?'); + $result = $openShares->execute(array(0, $this->userSession->getUser()->getUID())); + + return $result ? $openShares->fetchAll() : array(); + + } +}
\ No newline at end of file diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php index 71519bd1d4a..001d0387fa4 100644 --- a/apps/files_sharing/lib/helper.php +++ b/apps/files_sharing/lib/helper.php @@ -2,8 +2,6 @@ namespace OCA\Files_Sharing; -use OC_Config; - class Helper { public static function registerHooks() { @@ -21,30 +19,6 @@ class Helper { } /** - * add server-to-server share to database - * - * @param string $remote - * @param string $token - * @param string $name - * @param string $mountPoint - * @param string $owner - * @param string $user - * @param string $password - * @param int $remoteId - * @param bool $accepted - */ - public static function addServer2ServerShare($remote, $token, $name, $mountPoint, $owner, $user, $password='', $remoteId=-1, $accepted = false) { - $accepted = $accepted ? 1 : 0; - $query = \OCP\DB::prepare(' - INSERT INTO `*PREFIX*share_external` - (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - '); - $hash = md5($mountPoint); - $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId)); - } - - /** * Sets up the filesystem and user for public sharing * @param string $token string share token * @param string $relativePath optional path relative to the share @@ -89,7 +63,7 @@ class Helper { exit(); } - if (isset($linkItem['share_with'])) { + if (isset($linkItem['share_with']) && (int)$linkItem['share_type'] === \OCP\Share::SHARE_TYPE_LINK) { if (!self::authenticate($linkItem, $password)) { \OC_Response::setStatus(403); \OCP\JSON::error(array('success' => false)); diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php index a5b4e75bceb..93e4af3c393 100644 --- a/apps/files_sharing/lib/share/file.php +++ b/apps/files_sharing/lib/share/file.php @@ -160,6 +160,20 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { } /** + * check if server2server share is enabled + * + * @param int $shareType + * @return boolean + */ + public function isShareTypeAllowed($shareType) { + if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { + return \OCA\Files_Sharing\Helper::isOutgoingServer2serverShareEnabled(); + } + + return true; + } + + /** * resolve reshares to return the correct source item * @param array $source * @return array source item diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php index a34140f5a35..9d8ae7cbb4f 100644 --- a/apps/files_sharing/lib/updater.php +++ b/apps/files_sharing/lib/updater.php @@ -161,7 +161,10 @@ class Shared_Updater { */ static public function postUnshareHook($params) { - if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') { + // only update etags for file/folders shared to local users/groups + if (($params['itemType'] === 'file' || $params['itemType'] === 'folder') && + $params['shareType'] !== \OCP\Share::SHARE_TYPE_LINK && + $params['shareType'] !== \OCP\Share::SHARE_TYPE_REMOTE) { $deletedShares = isset($params['deletedShares']) ? $params['deletedShares'] : array(); @@ -212,7 +215,7 @@ class Shared_Updater { /** * rename mount point from the children if the parent was renamed - * + * * @param string $oldPath old path relative to data/user/files * @param string $newPath new path relative to data/user/files */ diff --git a/apps/files_sharing/tests/server2server.php b/apps/files_sharing/tests/server2server.php index 7aec0c4951f..0400d357b82 100644 --- a/apps/files_sharing/tests/server2server.php +++ b/apps/files_sharing/tests/server2server.php @@ -38,6 +38,16 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase { self::loginHelper(self::TEST_FILES_SHARING_API_USER1); \OCP\Share::registerBackend('test', 'Test_Share_Backend'); + $config = $this->getMockBuilder('\OCP\IConfig') + ->disableOriginalConstructor()->getMock(); + $certificateManager = $this->getMock('\OCP\ICertificateManager'); + $httpHelperMock = $this->getMockBuilder('\OC\HTTPHelper') + ->setConstructorArgs(array($config, $certificateManager)) + ->getMock(); + $httpHelperMock->expects($this->any())->method('post')->with($this->anything())->will($this->returnValue(true)); + + $this->registerHttpHelper($httpHelperMock); + $this->s2s = new \OCA\Files_Sharing\API\Server2Server(); } @@ -45,10 +55,33 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase { $query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share_external`'); $query->execute(); + $this->restoreHttpHelper(); + parent::tearDown(); } /** + * Register an http helper mock for testing purposes. + * @param $httpHelper http helper mock + */ + private function registerHttpHelper($httpHelper) { + $this->oldHttpHelper = \OC::$server->query('HTTPHelper'); + \OC::$server->registerService('HTTPHelper', function ($c) use ($httpHelper) { + return $httpHelper; + }); + } + + /** + * Restore the original http helper + */ + private function restoreHttpHelper() { + $oldHttpHelper = $this->oldHttpHelper; + \OC::$server->registerService('HTTPHelper', function ($c) use ($oldHttpHelper) { + return $oldHttpHelper; + }); + } + + /** * @medium */ function testCreateShare() { @@ -58,7 +91,7 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase { $_POST['name'] = 'name'; $_POST['owner'] = 'owner'; $_POST['shareWith'] = self::TEST_FILES_SHARING_API_USER2; - $_POST['remote_id'] = 1; + $_POST['remoteId'] = 1; $result = $this->s2s->createShare(null); @@ -81,10 +114,10 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase { function testDeclineShare() { $dummy = \OCP\DB::prepare(' INSERT INTO `*PREFIX*share` - (`share_type`, `uid_owner`, `item_type`, `item_source`, `item_target`, `file_source`, `file_target`, `permissions`, `stime`, `token`) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + (`share_type`, `uid_owner`, `item_type`, `item_source`, `item_target`, `file_source`, `file_target`, `permissions`, `stime`, `token`, `share_with`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) '); - $dummy->execute(array(\OCP\Share::SHARE_TYPE_REMOTE, self::TEST_FILES_SHARING_API_USER1, 'test', '1', '/1', '1', '/test.txt', '1', time(), 'token')); + $dummy->execute(array(\OCP\Share::SHARE_TYPE_REMOTE, self::TEST_FILES_SHARING_API_USER1, 'test', '1', '/1', '1', '/test.txt', '1', time(), 'token', 'foo@bar')); $verify = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share`'); $result = $verify->execute(); diff --git a/apps/user_ldap/ajax/clearMappings.php b/apps/user_ldap/ajax/clearMappings.php index 4e713c59f96..e6f3d32e84f 100644 --- a/apps/user_ldap/ajax/clearMappings.php +++ b/apps/user_ldap/ajax/clearMappings.php @@ -21,15 +21,27 @@ * */ +use OCA\User_LDAP\Mapping\UserMapping; +use OCA\User_LDAP\Mapping\GroupMapping; + // Check user and app status OCP\JSON::checkAdminUser(); OCP\JSON::checkAppEnabled('user_ldap'); OCP\JSON::callCheck(); $subject = $_POST['ldap_clear_mapping']; -if(\OCA\user_ldap\lib\Helper::clearMapping($subject)) { +$mapping = null; +if($subject === 'user') { + $mapping = new UserMapping(\OC::$server->getDatabaseConnection()); +} else if($subject === 'group') { + $mapping = new GroupMapping(\OC::$server->getDatabaseConnection()); +} +try { + if(is_null($mapping) || !$mapping->clear()) { + $l = \OC::$server->getL10N('user_ldap'); + throw new \Exception($l->t('Failed to clear the mappings.')); + } OCP\JSON::success(); -} else { - $l = \OC::$server->getL10N('user_ldap'); - OCP\JSON::error(array('message' => $l->t('Failed to clear the mappings.'))); +} catch (\Exception $e) { + OCP\JSON::error(array('message' => $e->getMessage())); } diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php index 8f9fbc5129b..98d5fb60183 100644 --- a/apps/user_ldap/appinfo/app.php +++ b/apps/user_ldap/appinfo/app.php @@ -34,6 +34,9 @@ if(count($configPrefixes) === 1) { new \OCP\Image()); $connector = new OCA\user_ldap\lib\Connection($ldapWrapper, $configPrefixes[0]); $ldapAccess = new OCA\user_ldap\lib\Access($connector, $ldapWrapper, $userManager); + $dbc = \OC::$server->getDatabaseConnection(); + $ldapAccess->setUserMapper(new OCA\User_LDAP\Mapping\UserMapping($dbc)); + $ldapAccess->setGroupMapper(new OCA\User_LDAP\Mapping\GroupMapping($dbc)); $userBackend = new OCA\user_ldap\USER_LDAP($ldapAccess); $groupBackend = new OCA\user_ldap\GROUP_LDAP($ldapAccess); } else if(count($configPrefixes) > 1) { diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 22510302061..5d0910320bf 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -23,6 +23,8 @@ namespace OCA\user_ldap\lib; +use OCA\User_LDAP\Mapping\AbstractMapping; + /** * Class Access * @package OCA\user_ldap\lib @@ -47,6 +49,16 @@ class Access extends LDAPUtility implements user\IUserTools { */ protected $lastCookie = ''; + /** + * @var AbstractMapping $userMapper + */ + protected $userMapper; + + /** + * @var AbstractMapping $userMapper + */ + protected $groupMapper; + public function __construct(Connection $connection, ILDAPWrapper $ldap, user\Manager $userManager) { parent::__construct($ldap); @@ -56,6 +68,22 @@ class Access extends LDAPUtility implements user\IUserTools { } /** + * sets the User Mapper + * @param AbstractMapping $mapper + */ + public function setUserMapper(AbstractMapping $mapper) { + $this->userMapper = $mapper; + } + + /** + * sets the Group Mapper + * @param AbstractMapping $mapper + */ + public function setGroupMapper(AbstractMapping $mapper) { + $this->groupMapper = $mapper; + } + + /** * @return bool */ private function checkConnection() { @@ -236,31 +264,12 @@ class Access extends LDAPUtility implements user\IUserTools { } /** - * gives back the database table for the query - * @param bool $isUser - * @return string - */ - private function getMapTable($isUser) { - if($isUser) { - return '*PREFIX*ldap_user_mapping'; - } else { - return '*PREFIX*ldap_group_mapping'; - } - } - - /** * returns the LDAP DN for the given internal ownCloud name of the group * @param string $name the ownCloud name in question - * @return string with the LDAP DN on success, otherwise false + * @return string|false LDAP DN on success, otherwise false */ public function groupname2dn($name) { - $dn = $this->ocname2dn($name, false); - - if($dn) { - return $dn; - } - - return false; + return $this->groupMapper->getDNbyName($name); } /** @@ -269,50 +278,32 @@ class Access extends LDAPUtility implements user\IUserTools { * @return string with the LDAP DN on success, otherwise false */ public function username2dn($name) { - $dn = $this->ocname2dn($name, true); + $fdn = $this->userMapper->getDNbyName($name); + //Check whether the DN belongs to the Base, to avoid issues on multi- //server setups - if($dn && $this->isDNPartOfBase($dn, $this->connection->ldapBaseUsers)) { - return $dn; + if(is_string($fdn) && $this->isDNPartOfBase($fdn, $this->connection->ldapBaseUsers)) { + return $fdn; } return false; } /** - * returns the LDAP DN for the given internal ownCloud name - * @param string $name the ownCloud name in question - * @param boolean $isUser is it a user? otherwise group - * @return string with the LDAP DN on success, otherwise false - */ - private function ocname2dn($name, $isUser) { - $table = $this->getMapTable($isUser); - - $query = \OCP\DB::prepare(' - SELECT `ldap_dn` - FROM `'.$table.'` - WHERE `owncloud_name` = ? - '); - - $record = $query->execute(array($name))->fetchOne(); - return $record; - } - - /** * returns the internal ownCloud name for the given LDAP DN of the group, false on DN outside of search DN or failure - * @param string $dn the dn of the group object + * @param string $fdn the dn of the group object * @param string $ldapName optional, the display name of the object * @return string with the name to use in ownCloud, false on DN outside of search DN */ - public function dn2groupname($dn, $ldapName = null) { + public function dn2groupname($fdn, $ldapName = null) { //To avoid bypassing the base DN settings under certain circumstances //with the group support, check whether the provided DN matches one of //the given Bases - if(!$this->isDNPartOfBase($dn, $this->connection->ldapBaseGroups)) { + if(!$this->isDNPartOfBase($fdn, $this->connection->ldapBaseGroups)) { return false; } - return $this->dn2ocname($dn, $ldapName, false); + return $this->dn2ocname($fdn, $ldapName, false); } /** @@ -321,15 +312,15 @@ class Access extends LDAPUtility implements user\IUserTools { * @param string $ldapName optional, the display name of the object * @return string with with the name to use in ownCloud */ - public function dn2username($dn, $ldapName = null) { + public function dn2username($fdn, $ldapName = null) { //To avoid bypassing the base DN settings under certain circumstances //with the group support, check whether the provided DN matches one of //the given Bases - if(!$this->isDNPartOfBase($dn, $this->connection->ldapBaseUsers)) { + if(!$this->isDNPartOfBase($fdn, $this->connection->ldapBaseUsers)) { return false; } - return $this->dn2ocname($dn, $ldapName, true); + return $this->dn2ocname($fdn, $ldapName, true); } /** @@ -339,50 +330,39 @@ class Access extends LDAPUtility implements user\IUserTools { * @param bool $isUser optional, whether it is a user object (otherwise group assumed) * @return string with with the name to use in ownCloud */ - public function dn2ocname($dn, $ldapName = null, $isUser = true) { - $table = $this->getMapTable($isUser); + public function dn2ocname($fdn, $ldapName = null, $isUser = true) { if($isUser) { - $fncFindMappedName = 'findMappedUser'; + $mapper = $this->userMapper; $nameAttribute = $this->connection->ldapUserDisplayName; } else { - $fncFindMappedName = 'findMappedGroup'; + $mapper = $this->groupMapper; $nameAttribute = $this->connection->ldapGroupDisplayName; } //let's try to retrieve the ownCloud name from the mappings table - $ocName = $this->$fncFindMappedName($dn); - if($ocName) { + $ocName = $mapper->getNameByDN($fdn); + if(is_string($ocName)) { return $ocName; } //second try: get the UUID and check if it is known. Then, update the DN and return the name. - $uuid = $this->getUUID($dn, $isUser); - if($uuid) { - $query = \OCP\DB::prepare(' - SELECT `owncloud_name` - FROM `'.$table.'` - WHERE `directory_uuid` = ? - '); - $component = $query->execute(array($uuid))->fetchOne(); - if($component) { - $query = \OCP\DB::prepare(' - UPDATE `'.$table.'` - SET `ldap_dn` = ? - WHERE `directory_uuid` = ? - '); - $query->execute(array($dn, $uuid)); - return $component; + $uuid = $this->getUUID($fdn, $isUser); + if(is_string($uuid)) { + $ocName = $mapper->getNameByUUID($uuid); + if(is_string($ocName)) { + $mapper->setDNbyUUID($fdn, $uuid); + return $ocName; } } else { //If the UUID can't be detected something is foul. - \OCP\Util::writeLog('user_ldap', 'Cannot determine UUID for '.$dn.'. Skipping.', \OCP\Util::INFO); + \OCP\Util::writeLog('user_ldap', 'Cannot determine UUID for '.$fdn.'. Skipping.', \OCP\Util::INFO); return false; } if(is_null($ldapName)) { - $ldapName = $this->readAttribute($dn, $nameAttribute); + $ldapName = $this->readAttribute($fdn, $nameAttribute); if(!isset($ldapName[0]) && empty($ldapName[0])) { - \OCP\Util::writeLog('user_ldap', 'No or empty name for '.$dn.'.', \OCP\Util::INFO); + \OCP\Util::writeLog('user_ldap', 'No or empty name for '.$fdn.'.', \OCP\Util::INFO); return false; } $ldapName = $ldapName[0]; @@ -390,8 +370,8 @@ class Access extends LDAPUtility implements user\IUserTools { if($isUser) { $usernameAttribute = $this->connection->ldapExpertUsernameAttr; - if(!emptY($usernameAttribute)) { - $username = $this->readAttribute($dn, $usernameAttribute); + if(!empty($usernameAttribute)) { + $username = $this->readAttribute($fdn, $usernameAttribute); $username = $username[0]; } else { $username = $uuid; @@ -409,7 +389,7 @@ class Access extends LDAPUtility implements user\IUserTools { $this->connection->setConfiguration(array('ldapCacheTTL' => 0)); if(($isUser && !\OCP\User::userExists($intName)) || (!$isUser && !\OC_Group::groupExists($intName))) { - if($this->mapComponent($dn, $intName, $isUser)) { + if($mapper->map($fdn, $intName, $uuid)) { $this->connection->setConfiguration(array('ldapCacheTTL' => $originalTTL)); return $intName; } @@ -417,12 +397,12 @@ class Access extends LDAPUtility implements user\IUserTools { $this->connection->setConfiguration(array('ldapCacheTTL' => $originalTTL)); $altName = $this->createAltInternalOwnCloudName($intName, $isUser); - if($this->mapComponent($dn, $altName, $isUser)) { + if(is_string($altName) && $mapper->map($fdn, $altName, $uuid)) { return $altName; } //if everything else did not help.. - \OCP\Util::writeLog('user_ldap', 'Could not create unique name for '.$dn.'.', \OCP\Util::INFO); + \OCP\Util::writeLog('user_ldap', 'Could not create unique name for '.$fdn.'.', \OCP\Util::INFO); return false; } @@ -449,46 +429,6 @@ class Access extends LDAPUtility implements user\IUserTools { } /** - * @param string $dn - * @return bool|string - */ - private function findMappedUser($dn) { - static $query = null; - if(is_null($query)) { - $query = \OCP\DB::prepare(' - SELECT `owncloud_name` - FROM `'.$this->getMapTable(true).'` - WHERE `ldap_dn` = ?' - ); - } - $res = $query->execute(array($dn))->fetchOne(); - if($res) { - return $res; - } - return false; - } - - /** - * @param string $dn - * @return bool|string - */ - private function findMappedGroup($dn) { - static $query = null; - if(is_null($query)) { - $query = \OCP\DB::prepare(' - SELECT `owncloud_name` - FROM `'.$this->getMapTable(false).'` - WHERE `ldap_dn` = ?' - ); - } - $res = $query->execute(array($dn))->fetchOne(); - if($res) { - return $res; - } - return false; - } - - /** * @param array $ldapObjects * @param bool $isUsers * @return array @@ -571,17 +511,7 @@ class Access extends LDAPUtility implements user\IUserTools { * "Developers" */ private function _createAltInternalOwnCloudNameForGroups($name) { - $query = \OCP\DB::prepare(' - SELECT `owncloud_name` - FROM `'.$this->getMapTable(false).'` - WHERE `owncloud_name` LIKE ? - '); - - $usedNames = array(); - $res = $query->execute(array($name.'_%')); - while($row = $res->fetchRow()) { - $usedNames[] = $row['owncloud_name']; - } + $usedNames = $this->groupMapper->getNamesBySearch($name.'_%'); if(!($usedNames) || count($usedNames) === 0) { $lastNo = 1; //will become name_2 } else { @@ -626,92 +556,6 @@ class Access extends LDAPUtility implements user\IUserTools { } /** - * retrieves all known groups from the mappings table - * @return array with the results - * - * retrieves all known groups from the mappings table - */ - private function mappedGroups() { - return $this->mappedComponents(false); - } - - /** - * retrieves all known users from the mappings table - * @return array with the results - * - * retrieves all known users from the mappings table - */ - private function mappedUsers() { - return $this->mappedComponents(true); - } - - /** - * @param boolean $isUsers - * @return array - */ - private function mappedComponents($isUsers) { - $table = $this->getMapTable($isUsers); - - $query = \OCP\DB::prepare(' - SELECT `ldap_dn`, `owncloud_name` - FROM `'. $table . '`' - ); - - return $query->execute()->fetchAll(); - } - - /** - * inserts a new user or group into the mappings table - * @param string $dn the record in question - * @param string $ocName the name to use in ownCloud - * @param bool $isUser is it a user or a group? - * @return bool true on success, false otherwise - * - * inserts a new user or group into the mappings table - */ - private function mapComponent($dn, $ocName, $isUser = true) { - $table = $this->getMapTable($isUser); - - $sqlAdjustment = ''; - $dbType = \OC::$server->getConfig()->getSystemValue('dbtype', null); - if($dbType === 'mysql' || $dbType == 'oci') { - $sqlAdjustment = 'FROM DUAL'; - } - - $insert = \OCP\DB::prepare(' - INSERT INTO `'.$table.'` (`ldap_dn`, `owncloud_name`, `directory_uuid`) - SELECT ?,?,? - '.$sqlAdjustment.' - WHERE NOT EXISTS ( - SELECT 1 - FROM `'.$table.'` - WHERE `ldap_dn` = ? - OR `owncloud_name` = ?) - '); - - //feed the DB - $insRows = $insert->execute(array($dn, $ocName, - $this->getUUID($dn, $isUser), $dn, - $ocName)); - - if(\OCP\DB::isError($insRows)) { - return false; - } - - if($insRows === 0) { - return false; - } - - if($isUser) { - //make sure that email address is retrieved prior to login, so user - //will be notified when something is shared with him - $this->userManager->get($ocName)->update(); - } - - return true; - } - - /** * @param string $filter * @param string|string[] $attr * @param int $limit @@ -1305,7 +1149,7 @@ class Access extends LDAPUtility implements user\IUserTools { /** * @param string $dn * @param bool $isUser - * @return array|bool|false + * @return string|bool */ public function getUUID($dn, $isUser = true) { if($isUser) { diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 336ea7b3bbc..54aafb93410 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -29,6 +29,7 @@ namespace OCA\user_ldap\lib; * @property string ldapUserFilter * @property string ldapUserDisplayName * @property boolean hasPagedResultSupport + * @property string[] ldapBaseUsers */ class Connection extends LDAPUtility { private $ldapConnectionRes = null; diff --git a/apps/user_ldap/lib/helper.php b/apps/user_ldap/lib/helper.php index 282f4549e3b..fa36e304171 100644 --- a/apps/user_ldap/lib/helper.php +++ b/apps/user_ldap/lib/helper.php @@ -142,33 +142,6 @@ class Helper { } /** - * Truncate's the given mapping table - * - * @param string $mapping either 'user' or 'group' - * @return bool true on success, false otherwise - */ - static public function clearMapping($mapping) { - if($mapping === 'user') { - $table = '`*PREFIX*ldap_user_mapping`'; - } else if ($mapping === 'group') { - $table = '`*PREFIX*ldap_group_mapping`'; - } else { - return false; - } - - $connection = \OC_DB::getConnection(); - $sql = $connection->getDatabasePlatform()->getTruncateTableSQL($table); - $query = \OCP\DB::prepare($sql); - $res = $query->execute(); - - if(\OCP\DB::isError($res)) { - return false; - } - - return true; - } - - /** * extracts the domain from a given URL * @param string $url the URL * @return string|false domain as string on success, false otherwise diff --git a/apps/user_ldap/lib/mapping/abstractmapping.php b/apps/user_ldap/lib/mapping/abstractmapping.php new file mode 100644 index 00000000000..2c45c6bb1c1 --- /dev/null +++ b/apps/user_ldap/lib/mapping/abstractmapping.php @@ -0,0 +1,201 @@ +<?php +/** +* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com> +* This file is licensed under the Affero General Public License version 3 or +* later. +* See the COPYING-README file. +*/ + +namespace OCA\User_LDAP\Mapping; + +/** +* Class AbstractMapping +* @package OCA\User_LDAP\Mapping +*/ +abstract class AbstractMapping { + /** + * @var \OCP\IDBConnection $dbc + */ + protected $dbc; + + /** + * returns the DB table name which holds the mappings + * @return string + */ + abstract protected function getTableName(); + + /** + * @param \OCP\IDBConnection $dbc + */ + public function __construct(\OCP\IDBConnection $dbc) { + $this->dbc = $dbc; + } + + /** + * checks whether a provided string represents an exisiting table col + * @param string $col + * @return bool + */ + public function isColNameValid($col) { + switch($col) { + case 'ldap_dn': + case 'owncloud_name': + case 'directory_uuid': + return true; + default: + return false; + } + } + + /** + * Gets the value of one column based on a provided value of another column + * @param string $fetchCol + * @param string $compareCol + * @param string $search + * @throws \Exception + * @return string|false + */ + protected function getXbyY($fetchCol, $compareCol, $search) { + if(!$this->isColNameValid($fetchCol)) { + //this is used internally only, but we don't want to risk + //having SQL injection at all. + throw new \Exception('Invalid Column Name'); + } + $query = $this->dbc->prepare(' + SELECT `' . $fetchCol . '` + FROM `'. $this->getTableName() .'` + WHERE `' . $compareCol . '` = ? + '); + + $res = $query->execute(array($search)); + if($res !== false) { + return $query->fetchColumn(); + } + + return false; + } + + /** + * Performs a DELETE or UPDATE query to the database. + * @param \Doctrine\DBAL\Driver\Statement $query + * @param array $parameters + * @return bool true if at least one row was modified, false otherwise + */ + protected function modify($query, $parameters) { + $result = $query->execute($parameters); + return ($result === true && $query->rowCount() > 0); + } + + /** + * Gets the LDAP DN based on the provided name. + * Replaces Access::ocname2dn + * @param string $name + * @return string|false + */ + public function getDNByName($name) { + return $this->getXbyY('ldap_dn', 'owncloud_name', $name); + } + + /** + * Updates the DN based on the given UUID + * @param string $fdn + * @param string $uuid + * @return bool + */ + public function setDNbyUUID($fdn, $uuid) { + $query = $this->dbc->prepare(' + UPDATE `' . $this->getTableName() . '` + SET `ldap_dn` = ? + WHERE `directory_uuid` = ? + '); + + return $this->modify($query, array($fdn, $uuid)); + } + + /** + * Gets the name based on the provided LDAP DN. + * @param string $fdn + * @return string|false + */ + public function getNameByDN($fdn) { + return $this->getXbyY('owncloud_name', 'ldap_dn', $fdn); + } + + /** + * Searches mapped names by the giving string in the name column + * @param string $search + * @return string[] + */ + public function getNamesBySearch($search) { + $query = $this->dbc->prepare(' + SELECT `owncloud_name` + FROM `'. $this->getTableName() .'` + WHERE `owncloud_name` LIKE ? + '); + + $res = $query->execute(array($search)); + $names = array(); + if($res !== false) { + while($row = $query->fetch()) { + $names[] = $row['owncloud_name']; + } + } + return $names; + } + + /** + * Gets the name based on the provided LDAP DN. + * @param string $uuid + * @return string|false + */ + public function getNameByUUID($uuid) { + return $this->getXbyY('owncloud_name', 'directory_uuid', $uuid); + } + + /** + * attempts to map the given entry + * @param string $fdn fully distinguished name (from LDAP) + * @param string $name + * @param string $uuid a unique identifier as used in LDAP + * @return bool + */ + public function map($fdn, $name, $uuid) { + $row = array( + 'ldap_dn' => $fdn, + 'owncloud_name' => $name, + 'directory_uuid' => $uuid + ); + + try { + $result = $this->dbc->insertIfNotExist($this->getTableName(), $row); + // insertIfNotExist returns values as int + return (bool)$result; + } catch (\Exception $e) { + return false; + } + } + + /** + * removes a mapping based on the owncloud_name of the entry + * @param string $name + * @return bool + */ + public function unmap($name) { + $query = $this->dbc->prepare(' + DELETE FROM `'. $this->getTableName() .'` + WHERE `owncloud_name` = ?'); + + return $this->modify($query, array($name)); + } + + /** + * Truncate's the mapping table + * @return bool + */ + public function clear() { + $sql = $this->dbc + ->getDatabasePlatform() + ->getTruncateTableSQL('`' . $this->getTableName() . '`'); + return $this->dbc->prepare($sql)->execute(); + } +} diff --git a/apps/user_ldap/lib/mapping/groupmapping.php b/apps/user_ldap/lib/mapping/groupmapping.php new file mode 100644 index 00000000000..af8a4bb4623 --- /dev/null +++ b/apps/user_ldap/lib/mapping/groupmapping.php @@ -0,0 +1,25 @@ +<?php +/** +* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com> +* This file is licensed under the Affero General Public License version 3 or +* later. +* See the COPYING-README file. +*/ + +namespace OCA\User_LDAP\Mapping; + +/** +* Class UserMapping +* @package OCA\User_LDAP\Mapping +*/ +class GroupMapping extends AbstractMapping { + + /** + * returns the DB table name which holds the mappings + * @return string + */ + protected function getTableName() { + return '*PREFIX*ldap_group_mapping'; + } + +} diff --git a/apps/user_ldap/lib/mapping/usermapping.php b/apps/user_ldap/lib/mapping/usermapping.php new file mode 100644 index 00000000000..dd24f338b96 --- /dev/null +++ b/apps/user_ldap/lib/mapping/usermapping.php @@ -0,0 +1,25 @@ +<?php +/** +* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com> +* This file is licensed under the Affero General Public License version 3 or +* later. +* See the COPYING-README file. +*/ + +namespace OCA\User_LDAP\Mapping; + +/** +* Class UserMapping +* @package OCA\User_LDAP\Mapping +*/ +class UserMapping extends AbstractMapping { + + /** + * returns the DB table name which holds the mappings + * @return string + */ + protected function getTableName() { + return '*PREFIX*ldap_user_mapping'; + } + +} diff --git a/apps/user_ldap/lib/proxy.php b/apps/user_ldap/lib/proxy.php index 73a52a7ddd9..39d4b36c8bb 100644 --- a/apps/user_ldap/lib/proxy.php +++ b/apps/user_ldap/lib/proxy.php @@ -24,6 +24,8 @@ namespace OCA\user_ldap\lib; use OCA\user_ldap\lib\Access; +use OCA\User_LDAP\Mapping\UserMapping; +use OCA\User_LDAP\Mapping\GroupMapping; abstract class Proxy { static private $accesses = array(); @@ -45,17 +47,23 @@ abstract class Proxy { static $fs; static $log; static $avatarM; + static $userMap; + static $groupMap; if(is_null($fs)) { $ocConfig = \OC::$server->getConfig(); $fs = new FilesystemHelper(); $log = new LogWrapper(); $avatarM = \OC::$server->getAvatarManager(); + $userMap = new UserMapping(\OC::$server->getDatabaseConnection()); + $groupMap = new GroupMapping(\OC::$server->getDatabaseConnection()); } $userManager = new user\Manager($ocConfig, $fs, $log, $avatarM, new \OCP\Image()); $connector = new Connection($this->ldap, $configPrefix); - self::$accesses[$configPrefix] = - new Access($connector, $this->ldap, $userManager); + $access = new Access($connector, $this->ldap, $userManager); + $access->setUserMapper($userMap); + $access->setGroupMapper($groupMap); + self::$accesses[$configPrefix] = $access; } /** diff --git a/apps/user_ldap/tests/helper.php b/apps/user_ldap/tests/helper.php deleted file mode 100644 index a70a57051c8..00000000000 --- a/apps/user_ldap/tests/helper.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php -/** -* ownCloud -* -* @author Thomas Müller -* @copyright 2014 Thomas Müller deepdiver@owncloud.com -* -*/ - -namespace OCA\user_ldap\tests; - -use OCA\user_ldap\lib\Helper; - -class Test_Helper extends \Test\TestCase { - - public function testTableTruncate() { - - $statement = \OCP\DB::prepare('INSERT INTO `*PREFIX*ldap_user_mapping` (`ldap_dn`, `owncloud_name`, `directory_uuid`) VALUES (?, ?, ?)'); - $statement->execute(array('db01', 'oc1', '000-0000-0000')); - $statement->execute(array('db02', 'oc2', '000-0000-0001')); - - $statement = \OCP\DB::prepare('SELECT count(*) FROM `*PREFIX*ldap_user_mapping`'); - $result = $statement->execute(); - $this->assertEquals(2, $result->fetchOne()); - - Helper::clearMapping('user'); - - $result = $statement->execute(); - $this->assertEquals(0, $result->fetchOne()); - } -} diff --git a/apps/user_ldap/tests/mapping/abstractmappingtest.php b/apps/user_ldap/tests/mapping/abstractmappingtest.php new file mode 100644 index 00000000000..a5cb62253af --- /dev/null +++ b/apps/user_ldap/tests/mapping/abstractmappingtest.php @@ -0,0 +1,194 @@ +<?php +/** +* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com> +* This file is licensed under the Affero General Public License version 3 or +* later. +* See the COPYING-README file. +*/ + +namespace OCA\user_ldap\tests\mapping; + +abstract class AbstractMappingTest extends \Test\TestCase { + abstract public function getMapper(\OCP\IDBConnection $dbMock); + + /** + * kiss test on isColNameValid + */ + public function testIsColNameValid() { + $dbMock = $this->getMock('\OCP\IDBConnection'); + $mapper = $this->getMapper($dbMock); + + $this->assertTrue($mapper->isColNameValid('ldap_dn')); + $this->assertFalse($mapper->isColNameValid('foobar')); + } + + /** + * returns an array of test entries with dn, name and uuid as keys + * @return array + */ + protected function getTestData() { + $data = array( + array( + 'dn' => 'uid=foobar,dc=example,dc=org', + 'name' => 'Foobar', + 'uuid' => '1111-AAAA-1234-CDEF', + ), + array( + 'dn' => 'uid=barfoo,dc=example,dc=org', + 'name' => 'Barfoo', + 'uuid' => '2222-BBBB-1234-CDEF', + ), + array( + 'dn' => 'uid=barabara,dc=example,dc=org', + 'name' => 'BaraBara', + 'uuid' => '3333-CCCC-1234-CDEF', + ) + ); + + return $data; + } + + /** + * calls map() on the given mapper and asserts result for true + * @param \OCA\User_LDAP\Mapping\AbstractMapping $mapper + * @param array $data + */ + protected function mapEntries($mapper, $data) { + foreach($data as $entry) { + $done = $mapper->map($entry['dn'], $entry['name'], $entry['uuid']); + $this->assertTrue($done); + } + } + + /** + * initalizes environment for a test run and returns an array with + * test objects. Preparing environment means that all mappings are cleared + * first and then filled with test entries. + * @return array 0 = \OCA\User_LDAP\Mapping\AbstractMapping, 1 = array of + * users or groups + */ + private function initTest() { + $dbc = \OC::$server->getDatabaseConnection(); + $mapper = $this->getMapper($dbc); + $data = $this->getTestData(); + // make sure DB is pristine, then fill it with test entries + $mapper->clear(); + $this->mapEntries($mapper, $data); + + return array($mapper, $data); + } + + /** + * tests map() method with input that should result in not-mapping. + * Hint: successful mapping is tested inherently with mapEntries(). + */ + public function testMap() { + list($mapper, $data) = $this->initTest(); + + // test that mapping will not happen when it shall not + $paramKeys = array('', 'dn', 'name', 'uuid'); + foreach($paramKeys as $key) { + $failEntry = $data[0]; + if(!empty($key)) { + $failEntry[$key] = 'do-not-get-mapped'; + } + $isMapped = $mapper->map($failEntry['dn'], $failEntry['name'], $failEntry['uuid']); + $this->assertFalse($isMapped); + } + } + + /** + * tests unmap() for both successfuly and not successful removing of + * mapping entries + */ + public function testUnmap() { + list($mapper, $data) = $this->initTest(); + + foreach($data as $entry) { + $result = $mapper->unmap($entry['name']); + $this->assertTrue($result); + } + + $result = $mapper->unmap('notAnEntry'); + $this->assertFalse($result); + } + + /** + * tests getDNByName(), getNameByDN() and getNameByUUID() for successful + * and unsuccessful requests. + */ + public function testGetMethods() { + list($mapper, $data) = $this->initTest(); + + foreach($data as $entry) { + $fdn = $mapper->getDNByName($entry['name']); + $this->assertSame($fdn, $entry['dn']); + } + $fdn = $mapper->getDNByName('nosuchname'); + $this->assertFalse($fdn); + + foreach($data as $entry) { + $name = $mapper->getNameByDN($entry['dn']); + $this->assertSame($name, $entry['name']); + } + $name = $mapper->getNameByDN('nosuchdn'); + $this->assertFalse($name); + + foreach($data as $entry) { + $name = $mapper->getNameByUUID($entry['uuid']); + $this->assertSame($name, $entry['name']); + } + $name = $mapper->getNameByUUID('nosuchuuid'); + $this->assertFalse($name); + } + + /** + * tests getNamesBySearch() for successful and unsuccessful requests. + */ + public function testSearch() { + list($mapper,) = $this->initTest(); + + $names = $mapper->getNamesBySearch('%oo%'); + $this->assertTrue(is_array($names)); + $this->assertSame(2, count($names)); + $this->assertTrue(in_array('Foobar', $names)); + $this->assertTrue(in_array('Barfoo', $names)); + $names = $mapper->getNamesBySearch('nada'); + $this->assertTrue(is_array($names)); + $this->assertSame(0, count($names)); + } + + /** + * tests setDNbyUUID() for successful and unsuccessful update. + */ + public function testSetMethod() { + list($mapper, $data) = $this->initTest(); + + $newDN = 'uid=modified,dc=example,dc=org'; + $done = $mapper->setDNbyUUID($newDN, $data[0]['uuid']); + $this->assertTrue($done); + $fdn = $mapper->getDNByName($data[0]['name']); + $this->assertSame($fdn, $newDN); + + $newDN = 'uid=notme,dc=example,dc=org'; + $done = $mapper->setDNbyUUID($newDN, 'iamnothere'); + $this->assertFalse($done); + $name = $mapper->getNameByDN($newDN); + $this->assertFalse($name); + + } + + /** + * tests clear() for successful update. + */ + public function testClear() { + list($mapper, $data) = $this->initTest(); + + $done = $mapper->clear(); + $this->assertTrue($done); + foreach($data as $entry) { + $name = $mapper->getNameByUUID($entry['uuid']); + $this->assertFalse($name); + } + } +} diff --git a/apps/user_ldap/tests/mapping/groupmapping.php b/apps/user_ldap/tests/mapping/groupmapping.php new file mode 100644 index 00000000000..11bb3f40e3a --- /dev/null +++ b/apps/user_ldap/tests/mapping/groupmapping.php @@ -0,0 +1,17 @@ +<?php +/** +* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com> +* This file is licensed under the Affero General Public License version 3 or +* later. +* See the COPYING-README file. +*/ + +namespace OCA\user_ldap\tests\mapping; + +use OCA\User_LDAP\Mapping\GroupMapping; + +class Test_GroupMapping extends AbstractMappingTest { + public function getMapper(\OCP\IDBConnection $dbMock) { + return new GroupMapping($dbMock); + } +} diff --git a/apps/user_ldap/tests/mapping/usermapping.php b/apps/user_ldap/tests/mapping/usermapping.php new file mode 100644 index 00000000000..2debcecf397 --- /dev/null +++ b/apps/user_ldap/tests/mapping/usermapping.php @@ -0,0 +1,17 @@ +<?php +/** +* Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com> +* This file is licensed under the Affero General Public License version 3 or +* later. +* See the COPYING-README file. +*/ + +namespace OCA\user_ldap\tests\mapping; + +use OCA\User_LDAP\Mapping\UserMapping; + +class Test_UserMapping extends AbstractMappingTest { + public function getMapper(\OCP\IDBConnection $dbMock) { + return new UserMapping($dbMock); + } +} |