diff options
Diffstat (limited to 'lib')
25 files changed, 1014 insertions, 75 deletions
diff --git a/lib/private/allconfig.php b/lib/private/allconfig.php index af7ffa4168e..3c85bfacbb8 100644 --- a/lib/private/allconfig.php +++ b/lib/private/allconfig.php @@ -205,57 +205,28 @@ class AllConfig implements \OCP\IConfig { // TODO - FIXME $this->fixDIInit(); - // Check if the key does exist - $sql = 'SELECT `configvalue` FROM `*PREFIX*preferences` '. - 'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'; - $result = $this->connection->executeQuery($sql, array($userId, $appName, $key)); - $oldValue = $result->fetchColumn(); - $result->closeCursor(); - $exists = $oldValue !== false; - - if($oldValue === strval($value)) { - // no changes - return; + $preconditionArray = []; + if (isset($preCondition)) { + $preconditionArray = [ + 'configvalue' => $preCondition, + ]; } - $affectedRows = 0; - if (!$exists && $preCondition === null) { - $this->connection->insertIfNotExist('*PREFIX*preferences', [ - 'configvalue' => $value, - 'userid' => $userId, - 'appid' => $appName, - 'configkey' => $key, - ], ['configkey', 'userid', 'appid']); - $affectedRows = 1; - } elseif ($exists) { - $data = array($value, $userId, $appName, $key); - - $sql = 'UPDATE `*PREFIX*preferences` SET `configvalue` = ? '. - 'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? '; - - if($preCondition !== null) { - if($this->getSystemValue('dbtype', 'sqlite') === 'oci') { - //oracle hack: need to explicitly cast CLOB to CHAR for comparison - $sql .= 'AND to_char(`configvalue`) = ?'; - } else { - $sql .= 'AND `configvalue` = ?'; - } - $data[] = $preCondition; - } - $affectedRows = $this->connection->executeUpdate($sql, $data); - } + $this->connection->setValues('preferences', [ + 'userid' => $userId, + 'appid' => $appName, + 'configkey' => $key, + ], [ + 'configvalue' => $value, + ], $preconditionArray); // only add to the cache if we already loaded data for the user - if ($affectedRows > 0 && isset($this->userCache[$userId])) { + if (isset($this->userCache[$userId])) { if (!isset($this->userCache[$userId][$appName])) { $this->userCache[$userId][$appName] = array(); } $this->userCache[$userId][$appName][$key] = $value; } - - if ($preCondition !== null && $affectedRows === 0) { - throw new PreConditionNotMetException; - } } /** diff --git a/lib/private/appframework/db/db.php b/lib/private/appframework/db/db.php index 812649daa78..5fdc5d1066c 100644 --- a/lib/private/appframework/db/db.php +++ b/lib/private/appframework/db/db.php @@ -147,6 +147,21 @@ class Db implements IDb { } /** + * Insert or update a row value + * + * @param string $table + * @param array $keys (column name => value) + * @param array $values (column name => value) + * @param array $updatePreconditionValues ensure values match preconditions (column name => value) + * @return int number of new rows + * @throws \Doctrine\DBAL\DBALException + * @throws PreconditionNotMetException + */ + public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []) { + return $this->connection->setValues($table, $keys, $values, $updatePreconditionValues); + } + + /** * Start a transaction */ public function beginTransaction() { diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php index 10cff1b68a2..175d6c747e4 100644 --- a/lib/private/appframework/dependencyinjection/dicontainer.php +++ b/lib/private/appframework/dependencyinjection/dicontainer.php @@ -219,6 +219,10 @@ class DIContainer extends SimpleContainer implements IAppContainer { return $this->getServer()->getHasher(); }); + $this->registerService('OCP\\Security\\ICredentialsManager', function($c) { + return $this->getServer()->getCredentialsManager(); + }); + $this->registerService('OCP\\Security\\ISecureRandom', function($c) { return $this->getServer()->getSecureRandom(); }); diff --git a/lib/private/db/connection.php b/lib/private/db/connection.php index 28bf3b6e05b..6c4f518dfb5 100644 --- a/lib/private/db/connection.php +++ b/lib/private/db/connection.php @@ -32,6 +32,7 @@ use Doctrine\Common\EventManager; use OC\DB\QueryBuilder\ExpressionBuilder; use OC\DB\QueryBuilder\QueryBuilder; use OCP\IDBConnection; +use OCP\PreconditionNotMetException; class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { /** @@ -241,6 +242,64 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection { return $this->adapter->insertIfNotExist($table, $input, $compare); } + private function getType($value) { + if (is_bool($value)) { + return \PDO::PARAM_BOOL; + } else if (is_int($value)) { + return \PDO::PARAM_INT; + } else { + return \PDO::PARAM_STR; + } + } + + /** + * Insert or update a row value + * + * @param string $table + * @param array $keys (column name => value) + * @param array $values (column name => value) + * @param array $updatePreconditionValues ensure values match preconditions (column name => value) + * @return int number of new rows + * @throws \Doctrine\DBAL\DBALException + * @throws PreconditionNotMetException + */ + public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []) { + try { + $insertQb = $this->getQueryBuilder(); + $insertQb->insert($table) + ->values( + array_map(function($value) use ($insertQb) { + return $insertQb->createNamedParameter($value, $this->getType($value)); + }, array_merge($keys, $values)) + ); + return $insertQb->execute(); + } catch (\Doctrine\DBAL\Exception\ConstraintViolationException $e) { + // value already exists, try update + $updateQb = $this->getQueryBuilder(); + $updateQb->update($table); + foreach ($values as $name => $value) { + $updateQb->set($name, $updateQb->createNamedParameter($value), $this->getType($value)); + } + $where = $updateQb->expr()->andx(); + $whereValues = array_merge($keys, $updatePreconditionValues); + foreach ($whereValues as $name => $value) { + $where->add($updateQb->expr()->eq( + $name, + $updateQb->createNamedParameter($value, $this->getType($value)), + $this->getType($value) + )); + } + $updateQb->where($where); + $affected = $updateQb->execute(); + + if ($affected === 0) { + throw new PreconditionNotMetException(); + } + + return 0; + } + } + /** * returns the error code and message as a string for logging * works with DoctrineException diff --git a/lib/private/db/querybuilder/expressionbuilder.php b/lib/private/db/querybuilder/expressionbuilder.php index de10f69b361..1e86db5a081 100644 --- a/lib/private/db/querybuilder/expressionbuilder.php +++ b/lib/private/db/querybuilder/expressionbuilder.php @@ -27,10 +27,10 @@ use OCP\IDBConnection; class ExpressionBuilder implements IExpressionBuilder { /** @var \Doctrine\DBAL\Query\Expression\ExpressionBuilder */ - private $expressionBuilder; + protected $expressionBuilder; /** @var QuoteHelper */ - private $helper; + protected $helper; /** * Initializes a new <tt>ExpressionBuilder</tt>. @@ -109,10 +109,12 @@ class ExpressionBuilder implements IExpressionBuilder { * * @param mixed $x The left expression. * @param mixed $y The right expression. + * @param int|null $type one of the \PDO::PARAM_* constants + * required when comparing text fields for oci compatibility * * @return string */ - public function eq($x, $y) { + public function eq($x, $y, $type = null) { $x = $this->helper->quoteColumnName($x); $y = $this->helper->quoteColumnName($y); return $this->expressionBuilder->eq($x, $y); diff --git a/lib/private/db/querybuilder/ociexpressionbuilder.php b/lib/private/db/querybuilder/ociexpressionbuilder.php new file mode 100644 index 00000000000..742611bf719 --- /dev/null +++ b/lib/private/db/querybuilder/ociexpressionbuilder.php @@ -0,0 +1,33 @@ +<?php +/** + * @author Joas Schilling <nickvergessen@owncloud.com> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OC\DB\QueryBuilder; + +class OCIExpressionBuilder extends ExpressionBuilder { + public function eq($x, $y, $type = null) { + $x = $this->helper->quoteColumnName($x); + $y = $this->helper->quoteColumnName($y); + if ($type === \PDO::PARAM_STR) { + $x = new QueryFunction('to_char(' . $x . ')'); + } + return $this->expressionBuilder->eq($x, $y); + } +} diff --git a/lib/private/db/querybuilder/querybuilder.php b/lib/private/db/querybuilder/querybuilder.php index 492e9bc9abf..42b290b90e7 100644 --- a/lib/private/db/querybuilder/querybuilder.php +++ b/lib/private/db/querybuilder/querybuilder.php @@ -21,6 +21,7 @@ namespace OC\DB\QueryBuilder; +use OC\DB\OracleConnection; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryFunction; use OCP\DB\QueryBuilder\IParameter; @@ -82,7 +83,11 @@ class QueryBuilder implements IQueryBuilder { * @return \OCP\DB\QueryBuilder\IExpressionBuilder */ public function expr() { - return new ExpressionBuilder($this->connection); + if ($this->connection instanceof OracleConnection) { + return new OCIExpressionBuilder($this->connection); + } else { + return new ExpressionBuilder($this->connection); + } } /** diff --git a/lib/private/files/config/cachedmountinfo.php b/lib/private/files/config/cachedmountinfo.php new file mode 100644 index 00000000000..dba07715edc --- /dev/null +++ b/lib/private/files/config/cachedmountinfo.php @@ -0,0 +1,107 @@ +<?php +/** + * @author Robin Appelman <icewind@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 OC\Files\Config; + +use OC\Files\Filesystem; +use OCP\Files\Config\ICachedMountInfo; +use OCP\Files\Node; +use OCP\IUser; + +class CachedMountInfo implements ICachedMountInfo { + /** + * @var IUser + */ + private $user; + + /** + * @var int + */ + private $storageId; + + /** + * @var int + */ + private $rootId; + + /** + * @var string + */ + private $mountPoint; + + /** + * CachedMountInfo constructor. + * + * @param IUser $user + * @param int $storageId + * @param int $rootId + * @param string $mountPoint + */ + public function __construct(IUser $user, $storageId, $rootId, $mountPoint) { + $this->user = $user; + $this->storageId = $storageId; + $this->rootId = $rootId; + $this->mountPoint = $mountPoint; + } + + /** + * @return IUser + */ + public function getUser() { + return $this->user; + } + + /** + * @return int the numeric storage id of the mount + */ + public function getStorageId() { + return $this->storageId; + } + + /** + * @return int the fileid of the root of the mount + */ + public function getRootId() { + return $this->rootId; + } + + /** + * @return Node the root node of the mount + */ + public function getMountPointNode() { + // TODO injection etc + Filesystem::initMountPoints($this->user->getUID()); + $userNode = \OC::$server->getUserFolder($this->user->getUID()); + $nodes = $userNode->getById($this->rootId); + if (count($nodes) > 0) { + return $nodes[0]; + } else { + return null; + } + } + + /** + * @return string the mount point of the mount for the user + */ + public function getMountPoint() { + return $this->mountPoint; + } +} diff --git a/lib/private/files/config/mountprovidercollection.php b/lib/private/files/config/mountprovidercollection.php index eb61ec3f5d5..499fa576fbc 100644 --- a/lib/private/files/config/mountprovidercollection.php +++ b/lib/private/files/config/mountprovidercollection.php @@ -26,6 +26,8 @@ use OC\Hooks\Emitter; use OC\Hooks\EmitterTrait; use OCP\Files\Config\IMountProviderCollection; use OCP\Files\Config\IMountProvider; +use OCP\Files\Config\IUserMountCache; +use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage\IStorageFactory; use OCP\IUser; @@ -43,10 +45,17 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { private $loader; /** + * @var \OCP\Files\Config\IUserMountCache + */ + private $mountCache; + + /** * @param \OCP\Files\Storage\IStorageFactory $loader + * @param IUserMountCache $mountCache */ - public function __construct(IStorageFactory $loader) { + public function __construct(IStorageFactory $loader, IUserMountCache $mountCache) { $this->loader = $loader; + $this->mountCache = $mountCache; } /** @@ -77,4 +86,23 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { $this->providers[] = $provider; $this->emit('\OC\Files\Config', 'registerMountProvider', [$provider]); } + + /** + * Cache mounts for user + * + * @param IUser $user + * @param IMountPoint[] $mountPoints + */ + public function registerMounts(IUser $user, array $mountPoints) { + $this->mountCache->registerMounts($user, $mountPoints); + } + + /** + * Get the mount cache which can be used to search for mounts without setting up the filesystem + * + * @return IUserMountCache + */ + public function getMountCache() { + return $this->mountCache; + } } diff --git a/lib/private/files/config/usermountcache.php b/lib/private/files/config/usermountcache.php new file mode 100644 index 00000000000..e3a494e93a1 --- /dev/null +++ b/lib/private/files/config/usermountcache.php @@ -0,0 +1,232 @@ +<?php +/** + * @author Robin Appelman <icewind@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 OC\Files\Config; + +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; +use OCP\Files\Config\ICachedMountInfo; +use OCP\Files\Config\IUserMountCache; +use OCP\Files\Mount\IMountPoint; +use OCP\ICache; +use OCP\IDBConnection; +use OCP\ILogger; +use OCP\IUser; +use OCP\IUserManager; + +/** + * Cache mounts points per user in the cache so we can easilly look them up + */ +class UserMountCache implements IUserMountCache { + /** + * @var IDBConnection + */ + private $connection; + + /** + * @var IUserManager + */ + private $userManager; + + /** @var ICachedMountInfo[][] [$userId => [$cachedMountInfo, ....], ...] */ + private $mountsForUsers = []; + + /** + * @var ILogger + */ + private $logger; + + /** + * UserMountCache constructor. + * + * @param IDBConnection $connection + * @param IUserManager $userManager + * @param ILogger $logger + */ + public function __construct(IDBConnection $connection, IUserManager $userManager, ILogger $logger) { + $this->connection = $connection; + $this->userManager = $userManager; + $this->logger = $logger; + } + + public function registerMounts(IUser $user, array $mounts) { + // filter out non-proper storages coming from unit tests + $mounts = array_filter($mounts, function (IMountPoint $mount) { + return $mount->getStorage()->getCache(); + }); + /** @var ICachedMountInfo[] $newMounts */ + $newMounts = array_map(function (IMountPoint $mount) use ($user) { + $storage = $mount->getStorage(); + $rootId = (int)$storage->getCache()->getId(''); + $storageId = (int)$storage->getStorageCache()->getNumericId(); + // filter out any storages which aren't scanned yet since we aren't interested in files from those storages (yet) + if ($rootId === -1) { + return null; + } else { + return new CachedMountInfo($user, $storageId, $rootId, $mount->getMountPoint()); + } + }, $mounts); + $newMounts = array_values(array_filter($newMounts)); + + $cachedMounts = $this->getMountsForUser($user); + $mountDiff = function (ICachedMountInfo $mount1, ICachedMountInfo $mount2) { + // since we are only looking for mounts for a specific user comparing on root id is enough + return $mount1->getRootId() - $mount2->getRootId(); + }; + + /** @var ICachedMountInfo[] $addedMounts */ + $addedMounts = array_udiff($newMounts, $cachedMounts, $mountDiff); + /** @var ICachedMountInfo[] $removedMounts */ + $removedMounts = array_udiff($cachedMounts, $newMounts, $mountDiff); + + $changedMounts = array_uintersect($newMounts, $cachedMounts, function (ICachedMountInfo $mount1, ICachedMountInfo $mount2) { + // filter mounts with the same root id and different mountpoints + if ($mount1->getRootId() !== $mount2->getRootId()) { + return -1; + } + return ($mount1->getMountPoint() !== $mount2->getMountPoint()) ? 0 : 1; + }); + + foreach ($addedMounts as $mount) { + $this->addToCache($mount); + $this->mountsForUsers[$user->getUID()][] = $mount; + } + foreach ($removedMounts as $mount) { + $this->removeFromCache($mount); + $index = array_search($mount, $this->mountsForUsers[$user->getUID()]); + unset($this->mountsForUsers[$user->getUID()][$index]); + } + foreach ($changedMounts as $mount) { + $this->setMountPoint($mount); + } + } + + private function addToCache(ICachedMountInfo $mount) { + $this->connection->insertIfNotExist('*PREFIX*mounts', [ + 'storage_id' => $mount->getStorageId(), + 'root_id' => $mount->getRootId(), + 'user_id' => $mount->getUser()->getUID(), + 'mount_point' => $mount->getMountPoint() + ]); + } + + private function setMountPoint(ICachedMountInfo $mount) { + $builder = $this->connection->getQueryBuilder(); + + $query = $builder->update('mounts') + ->set('mount_point', $builder->createNamedParameter($mount->getMountPoint())) + ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID()))) + ->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), \PDO::PARAM_INT))); + + $query->execute(); + } + + private function removeFromCache(ICachedMountInfo $mount) { + $builder = $this->connection->getQueryBuilder(); + + $query = $builder->delete('mounts') + ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID()))) + ->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), \PDO::PARAM_INT))); + $query->execute(); + } + + private function dbRowToMountInfo(array $row) { + $user = $this->userManager->get($row['user_id']); + return new CachedMountInfo($user, (int)$row['storage_id'], (int)$row['root_id'], $row['mount_point']); + } + + /** + * @param IUser $user + * @return ICachedMountInfo[] + */ + public function getMountsForUser(IUser $user) { + if (!isset($this->mountsForUsers[$user->getUID()])) { + $builder = $this->connection->getQueryBuilder(); + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point') + ->from('mounts') + ->where($builder->expr()->eq('user_id', $builder->createPositionalParameter($user->getUID()))); + + $rows = $query->execute()->fetchAll(); + + $this->mountsForUsers[$user->getUID()] = array_map([$this, 'dbRowToMountInfo'], $rows); + } + return $this->mountsForUsers[$user->getUID()]; + } + + /** + * @param int $numericStorageId + * @return CachedMountInfo[] + */ + public function getMountsForStorageId($numericStorageId) { + $builder = $this->connection->getQueryBuilder(); + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point') + ->from('mounts') + ->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($numericStorageId, \PDO::PARAM_INT))); + + $rows = $query->execute()->fetchAll(); + + return array_map([$this, 'dbRowToMountInfo'], $rows); + } + + /** + * @param int $rootFileId + * @return CachedMountInfo[] + */ + public function getMountsForRootId($rootFileId) { + $builder = $this->connection->getQueryBuilder(); + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point') + ->from('mounts') + ->where($builder->expr()->eq('root_id', $builder->createPositionalParameter($rootFileId, \PDO::PARAM_INT))); + + $rows = $query->execute()->fetchAll(); + + return array_map([$this, 'dbRowToMountInfo'], $rows); + } + + /** + * Remove all cached mounts for a user + * + * @param IUser $user + */ + public function removeUserMounts(IUser $user) { + $builder = $this->connection->getQueryBuilder(); + + $query = $builder->delete('mounts') + ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($user->getUID()))); + $query->execute(); + } + + public function removeUserStorageMount($storageId, $userId) { + $builder = $this->connection->getQueryBuilder(); + + $query = $builder->delete('mounts') + ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($userId))) + ->andWhere($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, \PDO::PARAM_INT))); + $query->execute(); + } + + public function remoteStorageMounts($storageId) { + $builder = $this->connection->getQueryBuilder(); + + $query = $builder->delete('mounts') + ->where($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, \PDO::PARAM_INT))); + $query->execute(); + } +} diff --git a/lib/private/files/config/usermountcachelistener.php b/lib/private/files/config/usermountcachelistener.php new file mode 100644 index 00000000000..344bebe342d --- /dev/null +++ b/lib/private/files/config/usermountcachelistener.php @@ -0,0 +1,48 @@ +<?php +/** + * @author Robin Appelman <icewind@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 OC\Files\Config; + +use OC\User\Manager; +use OCP\Files\Config\IUserMountCache; + +/** + * Listen to hooks and update the mount cache as needed + */ +class UserMountCacheListener { + /** + * @var IUserMountCache + */ + private $userMountCache; + + /** + * UserMountCacheListener constructor. + * + * @param IUserMountCache $userMountCache + */ + public function __construct(IUserMountCache $userMountCache) { + $this->userMountCache = $userMountCache; + } + + public function listen(Manager $manager) { + $manager->listen('\OC\User', 'postDelete', [$this->userMountCache, 'removeUserMounts']); + } +} diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php index ffe3a594ba8..9d4a2c0aa05 100644 --- a/lib/private/files/filesystem.php +++ b/lib/private/files/filesystem.php @@ -59,8 +59,10 @@ namespace OC\Files; use OC\Files\Config\MountProviderCollection; +use OC\Files\Mount\MountPoint; use OC\Files\Storage\StorageFactory; use OCP\Files\Config\IMountProvider; +use OCP\Files\Mount\IMountPoint; use OCP\Files\NotFoundException; use OCP\IUserManager; @@ -412,7 +414,8 @@ class Filesystem { $homeStorage['arguments']['legacy'] = true; } - self::mount($homeStorage['class'], $homeStorage['arguments'], $user); + $mount = new MountPoint($homeStorage['class'], '/' . $user, $homeStorage['arguments'], self::getLoader()); + self::getMountManager()->addMount($mount); $home = \OC\Files\Filesystem::getStorage($user); @@ -424,6 +427,8 @@ class Filesystem { if ($userObject) { $mounts = $mountConfigManager->getMountsForUser($userObject); array_walk($mounts, array(self::$mounts, 'addMount')); + $mounts[] = $mount; + $mountConfigManager->registerMounts($userObject, $mounts); } self::listenForNewMountProviders($mountConfigManager, $userManager); diff --git a/lib/private/integritycheck/checker.php b/lib/private/integritycheck/checker.php index 0cd01df7fe1..c256fe66d32 100644 --- a/lib/private/integritycheck/checker.php +++ b/lib/private/integritycheck/checker.php @@ -114,6 +114,7 @@ class Checker { * * @param string $folderToIterate * @return \RecursiveIteratorIterator + * @throws \Exception */ private function getFolderIterator($folderToIterate) { $dirItr = new \RecursiveDirectoryIterator( @@ -149,16 +150,33 @@ class Checker { } $relativeFileName = substr($filename, $baseDirectoryLength); + $relativeFileName = ltrim($relativeFileName, '/'); // Exclude signature.json files in the appinfo and root folder - if($relativeFileName === '/appinfo/signature.json') { + if($relativeFileName === 'appinfo/signature.json') { continue; } // Exclude signature.json files in the appinfo and core folder - if($relativeFileName === '/core/signature.json') { + if($relativeFileName === 'core/signature.json') { continue; } + // The .htaccess file in the root folder of ownCloud can contain + // custom content after the installation due to the fact that dynamic + // content is written into it at installation time as well. This + // includes for example the 404 and 403 instructions. + // Thus we ignore everything below the first occurrence of + // "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####" and have the + // hash generated based on this. + if($filename === $this->environmentHelper->getServerRoot() . '/.htaccess') { + $fileContent = file_get_contents($filename); + $explodedArray = explode('#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####', $fileContent); + if(count($explodedArray) === 2) { + $hashes[$relativeFileName] = hash('sha512', $explodedArray[0]); + continue; + } + } + $hashes[$relativeFileName] = hash_file('sha512', $filename); } return $hashes; @@ -189,17 +207,19 @@ class Checker { } /** - * Write the signature of the specified app + * Write the signature of the app in the specified folder * - * @param string $appId + * @param string $path * @param X509 $certificate * @param RSA $privateKey * @throws \Exception */ - public function writeAppSignature($appId, + public function writeAppSignature($path, X509 $certificate, RSA $privateKey) { - $path = $this->appLocator->getAppPath($appId); + if(!is_dir($path)) { + throw new \Exception('Directory does not exist.'); + } $iterator = $this->getFolderIterator($path); $hashes = $this->generateHashes($iterator, $path); $signature = $this->createSignatureData($hashes, $certificate, $privateKey); diff --git a/lib/private/integritycheck/helpers/environmenthelper.php b/lib/private/integritycheck/helpers/environmenthelper.php index 8bddcb3d794..f56f07486c2 100644 --- a/lib/private/integritycheck/helpers/environmenthelper.php +++ b/lib/private/integritycheck/helpers/environmenthelper.php @@ -34,7 +34,7 @@ class EnvironmentHelper { * @return string */ public function getServerRoot() { - return \OC::$SERVERROOT; + return rtrim(\OC::$SERVERROOT, '/'); } /** diff --git a/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php b/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php index efe7c114d9e..c3994197fc6 100644 --- a/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php +++ b/lib/private/integritycheck/iterator/excludefoldersbypathfilteriterator.php @@ -35,6 +35,7 @@ class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator { $this->excludedFolders = array_merge([ rtrim(\OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data'), '/'), rtrim(\OC::$SERVERROOT.'/themes', '/'), + rtrim(\OC::$SERVERROOT.'/config', '/'), ], $appFolders); } diff --git a/lib/private/security/credentialsmanager.php b/lib/private/security/credentialsmanager.php new file mode 100644 index 00000000000..405922847be --- /dev/null +++ b/lib/private/security/credentialsmanager.php @@ -0,0 +1,125 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@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 OC\Security; + +use OCP\Security\ICrypto; +use OCP\IDBConnection; +use OCP\Security\ICredentialsManager; +use OCP\IConfig; + +/** + * Store and retrieve credentials for external services + * + * @package OC\Security + */ +class CredentialsManager implements ICredentialsManager { + + const DB_TABLE = 'credentials'; + + /** @var ICrypto */ + protected $crypto; + + /** @var IDBConnection */ + protected $dbConnection; + + /** + * @param ICrypto $crypto + * @param IDBConnection $dbConnection + */ + public function __construct(ICrypto $crypto, IDBConnection $dbConnection) { + $this->crypto = $crypto; + $this->dbConnection = $dbConnection; + } + + /** + * Store a set of credentials + * + * @param string|null $userId Null for system-wide credentials + * @param string $identifier + * @param mixed $credentials + */ + public function store($userId, $identifier, $credentials) { + $value = $this->crypto->encrypt(json_encode($credentials)); + + $this->dbConnection->setValues(self::DB_TABLE, [ + 'user' => $userId, + 'identifier' => $identifier, + ], [ + 'credentials' => $value, + ]); + } + + /** + * Retrieve a set of credentials + * + * @param string|null $userId Null for system-wide credentials + * @param string $identifier + * @return mixed + */ + public function retrieve($userId, $identifier) { + $qb = $this->dbConnection->getQueryBuilder(); + $qb->select('credentials') + ->from(self::DB_TABLE) + ->where($qb->expr()->eq('user', $qb->createNamedParameter($userId))) + ->andWhere($qb->expr()->eq('identifier', $qb->createNamedParameter($identifier))) + ; + $result = $qb->execute()->fetch(); + + if (!$result) { + return null; + } + $value = $result['credentials']; + + return json_decode($this->crypto->decrypt($value), true); + } + + /** + * Delete a set of credentials + * + * @param string|null $userId Null for system-wide credentials + * @param string $identifier + * @return int rows removed + */ + public function delete($userId, $identifier) { + $qb = $this->dbConnection->getQueryBuilder(); + $qb->delete(self::DB_TABLE) + ->where($qb->expr()->eq('user', $qb->createNamedParameter($userId))) + ->andWhere($qb->expr()->eq('identifier', $qb->createNamedParameter($identifier))) + ; + return $qb->execute(); + } + + /** + * Erase all credentials stored for a user + * + * @param string $userId + * @return int rows removed + */ + public function erase($userId) { + $qb = $this->dbConnection->getQueryBuilder(); + $qb->delete(self::DB_TABLE) + ->where($qb->expr()->eq('user', $qb->createNamedParameter($userId))) + ; + return $qb->execute(); + } + +} diff --git a/lib/private/server.php b/lib/private/server.php index 0cb52b79184..6e9c5ca0c68 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -47,6 +47,8 @@ use OC\Diagnostics\EventLogger; use OC\Diagnostics\NullEventLogger; use OC\Diagnostics\NullQueryLogger; use OC\Diagnostics\QueryLogger; +use OC\Files\Config\UserMountCache; +use OC\Files\Config\UserMountCacheListener; use OC\Files\Node\HookConnector; use OC\Files\Node\Root; use OC\Files\View; @@ -63,6 +65,7 @@ use OC\Notification\Manager; use OC\Security\CertificateManager; use OC\Security\Crypto; use OC\Security\Hasher; +use OC\Security\CredentialsManager; use OC\Security\SecureRandom; use OC\Security\TrustedDomainHelper; use OC\Session\CryptoWrapper; @@ -136,7 +139,7 @@ class Server extends ServerContainer implements IServerContainer { return new Encryption\Keys\Storage($view, $util); }); - $this->registerService('TagMapper', function(Server $c) { + $this->registerService('TagMapper', function (Server $c) { return new TagMapper($c->getDatabaseConnection()); }); $this->registerService('TagManager', function (Server $c) { @@ -276,13 +279,13 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('MemCacheFactory', function (Server $c) { $config = $c->getConfig(); - if($config->getSystemValue('installed', false) && !(defined('PHPUNIT_RUN') && PHPUNIT_RUN)) { + if ($config->getSystemValue('installed', false) && !(defined('PHPUNIT_RUN') && PHPUNIT_RUN)) { $v = \OC_App::getAppVersions(); $v['core'] = md5(file_get_contents(\OC::$SERVERROOT . '/version.php')); $version = implode(',', $v); $instanceId = \OC_Util::getInstanceId(); $path = \OC::$SERVERROOT; - $prefix = md5($instanceId.'-'.$version.'-'.$path); + $prefix = md5($instanceId . '-' . $version . '-' . $path); return new \OC\Memcache\Factory($prefix, $c->getLogger(), $config->getSystemValue('memcache.local', null), $config->getSystemValue('memcache.distributed', null), @@ -343,6 +346,9 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('Hasher', function (Server $c) { return new Hasher($c->getConfig()); }); + $this->registerService('CredentialsManager', function (Server $c) { + return new CredentialsManager($c->getCrypto(), $c->getDatabaseConnection()); + }); $this->registerService('DatabaseConnection', function (Server $c) { $factory = new \OC\DB\ConnectionFactory(); $systemConfig = $c->getSystemConfig(); @@ -393,7 +399,7 @@ class Server extends ServerContainer implements IServerContainer { $c->getConfig() ); }); - $this->registerService('AppManager', function(Server $c) { + $this->registerService('AppManager', function (Server $c) { return new \OC\App\AppManager( $c->getUserSession(), $c->getAppConfig(), @@ -401,13 +407,13 @@ class Server extends ServerContainer implements IServerContainer { $c->getMemCacheFactory() ); }); - $this->registerService('DateTimeZone', function(Server $c) { + $this->registerService('DateTimeZone', function (Server $c) { return new DateTimeZone( $c->getConfig(), $c->getSession() ); }); - $this->registerService('DateTimeFormatter', function(Server $c) { + $this->registerService('DateTimeFormatter', function (Server $c) { $language = $c->getConfig()->getUserValue($c->getSession()->get('user_id'), 'core', 'lang', null); return new DateTimeFormatter( @@ -415,9 +421,16 @@ class Server extends ServerContainer implements IServerContainer { $c->getL10N('lib', $language) ); }); - $this->registerService('MountConfigManager', function () { + $this->registerService('UserMountCache', function (Server $c) { + $mountCache = new UserMountCache($c->getDatabaseConnection(), $c->getUserManager(), $c->getLogger()); + $listener = new UserMountCacheListener($mountCache); + $listener->listen($c->getUserManager()); + return $mountCache; + }); + $this->registerService('MountConfigManager', function (Server $c) { $loader = \OC\Files\Filesystem::getLoader(); - return new \OC\Files\Config\MountProviderCollection($loader); + $mountCache = $c->query('UserMountCache'); + return new \OC\Files\Config\MountProviderCollection($loader, $mountCache); }); $this->registerService('IniWrapper', function ($c) { return new IniGetWrapper(); @@ -489,14 +502,14 @@ class Server extends ServerContainer implements IServerContainer { $stream ); }); - $this->registerService('Mailer', function(Server $c) { + $this->registerService('Mailer', function (Server $c) { return new Mailer( $c->getConfig(), $c->getLogger(), new \OC_Defaults() ); }); - $this->registerService('OcsClient', function(Server $c) { + $this->registerService('OcsClient', function (Server $c) { return new OCSClient( $this->getHTTPClientService(), $this->getConfig(), @@ -518,24 +531,24 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('MountManager', function () { return new \OC\Files\Mount\Manager(); }); - $this->registerService('MimeTypeDetector', function(Server $c) { + $this->registerService('MimeTypeDetector', function (Server $c) { return new \OC\Files\Type\Detection( $c->getURLGenerator(), \OC::$SERVERROOT . '/config/', \OC::$SERVERROOT . '/resources/config/' - ); + ); }); - $this->registerService('MimeTypeLoader', function(Server $c) { + $this->registerService('MimeTypeLoader', function (Server $c) { return new \OC\Files\Type\Loader( $c->getDatabaseConnection() ); }); - $this->registerService('NotificationManager', function() { + $this->registerService('NotificationManager', function () { return new Manager(); }); $this->registerService('CapabilitiesManager', function (Server $c) { $manager = new \OC\CapabilitiesManager(); - $manager->registerCapability(function() use ($c) { + $manager->registerCapability(function () use ($c) { return new \OC\OCS\CoreCapabilities($c->getConfig()); }); return $manager; @@ -547,7 +560,7 @@ class Server extends ServerContainer implements IServerContainer { $factory = new $factoryClass($this); return $factory->getManager(); }); - $this->registerService('EventDispatcher', function() { + $this->registerService('EventDispatcher', function () { return new EventDispatcher(); }); $this->registerService('CryptoWrapper', function (Server $c) { @@ -931,7 +944,17 @@ class Server extends ServerContainer implements IServerContainer { } /** + * Returns a CredentialsManager instance + * + * @return \OCP\Security\ICredentialsManager + */ + public function getCredentialsManager() { + return $this->query('CredentialsManager'); + } + + /** * Returns an instance of the db facade + * * @deprecated use getDatabaseConnection, will be removed in ownCloud 10 * @return \OCP\IDb */ @@ -941,6 +964,7 @@ class Server extends ServerContainer implements IServerContainer { /** * Returns an instance of the HTTP helper class + * * @deprecated Use getHTTPClientService() * @return \OC\HTTPHelper */ @@ -1066,7 +1090,7 @@ class Server extends ServerContainer implements IServerContainer { /** * @return \OCP\Files\Config\IMountProviderCollection */ - public function getMountProviderCollection(){ + public function getMountProviderCollection() { return $this->query('MountConfigManager'); } @@ -1082,7 +1106,7 @@ class Server extends ServerContainer implements IServerContainer { /** * @return \OCP\Command\IBus */ - public function getCommandBus(){ + public function getCommandBus() { return $this->query('AsyncCommandBus'); } @@ -1182,6 +1206,7 @@ class Server extends ServerContainer implements IServerContainer { /** * Not a public API as of 8.2, wait for 9.0 + * * @return \OCA\Files_External\Service\BackendService */ public function getStoragesBackendService() { @@ -1190,6 +1215,7 @@ class Server extends ServerContainer implements IServerContainer { /** * Not a public API as of 8.2, wait for 9.0 + * * @return \OCA\Files_External\Service\GlobalStoragesService */ public function getGlobalStoragesService() { @@ -1198,6 +1224,7 @@ class Server extends ServerContainer implements IServerContainer { /** * Not a public API as of 8.2, wait for 9.0 + * * @return \OCA\Files_External\Service\UserGlobalStoragesService */ public function getUserGlobalStoragesService() { @@ -1206,6 +1233,7 @@ class Server extends ServerContainer implements IServerContainer { /** * Not a public API as of 8.2, wait for 9.0 + * * @return \OCA\Files_External\Service\UserStoragesService */ public function getUserStoragesService() { @@ -1219,4 +1247,5 @@ class Server extends ServerContainer implements IServerContainer { public function getShareManager() { return $this->query('ShareManager'); } + } diff --git a/lib/private/setup.php b/lib/private/setup.php index 7903b94ccde..a96dade0665 100644 --- a/lib/private/setup.php +++ b/lib/private/setup.php @@ -408,7 +408,7 @@ class Setup { \OC::$server->getSecureRandom()); $htaccessContent = file_get_contents($setupHelper->pathToHtaccess()); - $content = ''; + $content = "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####\n"; if (strpos($htaccessContent, 'ErrorDocument 403') === false) { //custom 403 error page $content.= "\nErrorDocument 403 ".\OC::$WEBROOT."/core/templates/403.php"; diff --git a/lib/public/db/querybuilder/iexpressionbuilder.php b/lib/public/db/querybuilder/iexpressionbuilder.php index ae62694fcaf..0549d3f0125 100644 --- a/lib/public/db/querybuilder/iexpressionbuilder.php +++ b/lib/public/db/querybuilder/iexpressionbuilder.php @@ -84,11 +84,13 @@ interface IExpressionBuilder { * * @param mixed $x The left expression. * @param mixed $y The right expression. + * @param int|null $type @since 9.0.0 one of the \PDO::PARAM_* constants + * required when comparing text fields for oci compatibility. * * @return string * @since 8.2.0 */ - public function eq($x, $y); + public function eq($x, $y, $type = null); /** * Creates a non equality comparison expression with the given arguments. diff --git a/lib/public/files/config/icachedmountinfo.php b/lib/public/files/config/icachedmountinfo.php new file mode 100644 index 00000000000..a587427f1f2 --- /dev/null +++ b/lib/public/files/config/icachedmountinfo.php @@ -0,0 +1,62 @@ +<?php +/** + * @author Robin Appelman <icewind@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\Files\Config; + +use OCP\Files\Node; +use OCP\IUser; + +/** + * Holds information about a mount for a user + * + * @since 9.0.0 + */ +interface ICachedMountInfo { + /** + * @return IUser + * @since 9.0.0 + */ + public function getUser(); + + /** + * @return int the numeric storage id of the mount + * @since 9.0.0 + */ + public function getStorageId(); + + /** + * @return int the fileid of the root of the mount + * @since 9.0.0 + */ + public function getRootId(); + + /** + * @return Node the root node of the mount + * @since 9.0.0 + */ + public function getMountPointNode(); + + /** + * @return string the mount point of the mount for the user + * @since 9.0.0 + */ + public function getMountPoint(); +} diff --git a/lib/public/files/config/imountprovidercollection.php b/lib/public/files/config/imountprovidercollection.php index 43b4bd0ce00..39da61812a9 100644 --- a/lib/public/files/config/imountprovidercollection.php +++ b/lib/public/files/config/imountprovidercollection.php @@ -22,6 +22,7 @@ namespace OCP\Files\Config; +use OCP\Files\Mount\IMountPoint; use OCP\IUser; /** @@ -45,4 +46,12 @@ interface IMountProviderCollection { * @since 8.0.0 */ public function registerProvider(IMountProvider $provider); + + /** + * Get the mount cache which can be used to search for mounts without setting up the filesystem + * + * @return IUserMountCache + * @since 9.0.0 + */ + public function getMountCache(); } diff --git a/lib/public/files/config/iusermountcache.php b/lib/public/files/config/iusermountcache.php new file mode 100644 index 00000000000..f722ad16310 --- /dev/null +++ b/lib/public/files/config/iusermountcache.php @@ -0,0 +1,89 @@ +<?php +/** + * @author Robin Appelman <icewind@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\Files\Config; + +use OCP\Files\Mount\IMountPoint; +use OCP\IUser; + +/** + * Cache mounts points per user in the cache so we can easily look them up + * + * @since 9.0.0 + */ +interface IUserMountCache { + /** + * Register mounts for a user to the cache + * + * @param IUser $user + * @param IMountPoint[] $mounts + * @since 9.0.0 + */ + public function registerMounts(IUser $user, array $mounts); + + /** + * @param IUser $user + * @return ICachedMountInfo[] + * @since 9.0.0 + */ + public function getMountsForUser(IUser $user); + + /** + * @param int $numericStorageId + * @return ICachedMountInfo[] + * @since 9.0.0 + */ + public function getMountsForStorageId($numericStorageId); + + /** + * @param int $rootFileId + * @return ICachedMountInfo[] + * @since 9.0.0 + */ + public function getMountsForRootId($rootFileId); + + /** + * Remove all cached mounts for a user + * + * @param IUser $user + * @since 9.0.0 + */ + public function removeUserMounts(IUser $user); + + /** + * Remove all mounts for a user and storage + * + * @param $storageId + * @param string $userId + * @return mixed + * @since 9.0.0 + */ + public function removeUserStorageMount($storageId, $userId); + + /** + * Remove all cached mounts for a storage + * + * @param $storageId + * @return mixed + * @since 9.0.0 + */ + public function remoteStorageMounts($storageId); +} diff --git a/lib/public/idbconnection.php b/lib/public/idbconnection.php index 49856fb78a5..c5767e65a82 100644 --- a/lib/public/idbconnection.php +++ b/lib/public/idbconnection.php @@ -109,6 +109,20 @@ interface IDBConnection { public function insertIfNotExist($table, $input, array $compare = null); /** + * Insert or update a row value + * + * @param string $table + * @param array $keys (column name => value) + * @param array $values (column name => value) + * @param array $updatePreconditionValues ensure values match preconditions (column name => value) + * @return int number of new rows + * @throws \Doctrine\DBAL\DBALException + * @throws PreconditionNotMetException + * @since 9.0.0 + */ + public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []); + + /** * Start a transaction * @since 6.0.0 */ diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index eb4498a1a24..e21c9fb8e4b 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -181,6 +181,14 @@ interface IServerContainer { public function getSecureRandom(); /** + * Returns a CredentialsManager instance + * + * @return \OCP\Security\ICredentialsManager + * @since 9.0.0 + */ + public function getCredentialsManager(); + + /** * Returns an instance of the db facade * @deprecated 8.1.0 use getDatabaseConnection, will be removed in ownCloud 10 * @return \OCP\IDb diff --git a/lib/public/security/icredentialsmanager.php b/lib/public/security/icredentialsmanager.php new file mode 100644 index 00000000000..d3d076f043e --- /dev/null +++ b/lib/public/security/icredentialsmanager.php @@ -0,0 +1,71 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@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\Security; + +/** + * Store and retrieve credentials for external services + * + * @package OCP\Security + * @since 8.2.0 + */ +interface ICredentialsManager { + + /** + * Store a set of credentials + * + * @param string|null $userId Null for system-wide credentials + * @param string $identifier + * @param mixed $credentials + * @since 8.2.0 + */ + public function store($userId, $identifier, $credentials); + + /** + * Retrieve a set of credentials + * + * @param string|null $userId Null for system-wide credentials + * @param string $identifier + * @return mixed + * @since 8.2.0 + */ + public function retrieve($userId, $identifier); + + /** + * Delete a set of credentials + * + * @param string|null $userId Null for system-wide credentials + * @param string $identifier + * @return int rows removed + * @since 8.2.0 + */ + public function delete($userId, $identifier); + + /** + * Erase all credentials stored for a user + * + * @param string $userId + * @return int rows removed + * @since 8.2.0 + */ + public function erase($userId); + +} |