summaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
authorLukas Reschke <lukas@owncloud.com>2016-06-21 11:18:22 +0200
committerLukas Reschke <lukas@owncloud.com>2016-06-21 11:18:22 +0200
commit2b493e2f9dca674ba11f88a1d182d6872e04eaaa (patch)
treeef7fa75d1b4da812de80e93c3590dbb5404d7f06 /lib/private
parentb4df57f3f02f65ed71d1072280751170379a53e8 (diff)
parent0e575c7eeadc6c8eb11b0be2ed1d39cdcf6cfcb8 (diff)
downloadnextcloud-server-2b493e2f9dca674ba11f88a1d182d6872e04eaaa.tar.gz
nextcloud-server-2b493e2f9dca674ba11f88a1d182d6872e04eaaa.zip
Merge remote-tracking branch 'upstream/master' into master-sync-upstream
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/AllConfig.php6
-rw-r--r--lib/private/AppFramework/Middleware/Security/CORSMiddleware.php9
-rw-r--r--lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php29
-rw-r--r--lib/private/Authentication/Token/DefaultTokenMapper.php1
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Manager.php13
-rw-r--r--lib/private/Files/Cache/Updater.php18
-rw-r--r--lib/private/Files/Config/LazyStorageMountInfo.php8
-rw-r--r--lib/private/Files/Config/UserMountCache.php33
-rw-r--r--lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php1
-rw-r--r--lib/private/Preview.php21
-rw-r--r--lib/private/Repair.php4
-rw-r--r--lib/private/Repair/CleanTags.php57
-rw-r--r--lib/private/Repair/RemoveRootShares.php157
-rw-r--r--lib/private/Share20/Manager.php36
-rw-r--r--lib/private/User/Session.php53
15 files changed, 388 insertions, 58 deletions
diff --git a/lib/private/AllConfig.php b/lib/private/AllConfig.php
index e082cea3305..c8b2009fcc7 100644
--- a/lib/private/AllConfig.php
+++ b/lib/private/AllConfig.php
@@ -27,6 +27,7 @@
*/
namespace OC;
+use OC\Cache\CappedMemoryCache;
use OCP\IDBConnection;
use OCP\PreConditionNotMetException;
@@ -58,14 +59,15 @@ class AllConfig implements \OCP\IConfig {
* - deleteAllUserValues
* - deleteAppFromAllUsers
*
- * @var array $userCache
+ * @var CappedMemoryCache $userCache
*/
- private $userCache = array();
+ private $userCache;
/**
* @param SystemConfig $systemConfig
*/
function __construct(SystemConfig $systemConfig) {
+ $this->userCache = new CappedMemoryCache();
$this->systemConfig = $systemConfig;
}
diff --git a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php
index d84e9963436..32a507623e3 100644
--- a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php
@@ -26,6 +26,7 @@ namespace OC\AppFramework\Middleware\Security;
use OC\AppFramework\Middleware\Security\Exceptions\SecurityException;
use OC\AppFramework\Utility\ControllerMethodReflector;
+use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
use OC\User\Session;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
@@ -89,8 +90,12 @@ class CORSMiddleware extends Middleware {
$pass = $this->request->server['PHP_AUTH_PW'];
$this->session->logout();
- if(!$this->session->logClientIn($user, $pass)) {
- throw new SecurityException('CORS requires basic auth', Http::STATUS_UNAUTHORIZED);
+ try {
+ if (!$this->session->logClientIn($user, $pass, $this->request)) {
+ throw new SecurityException('CORS requires basic auth', Http::STATUS_UNAUTHORIZED);
+ }
+ } catch (PasswordLoginForbiddenException $ex) {
+ throw new SecurityException('Password login forbidden, use token instead', Http::STATUS_UNAUTHORIZED);
}
}
}
diff --git a/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php b/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php
new file mode 100644
index 00000000000..2e9f9534dbd
--- /dev/null
+++ b/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@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\Authentication\Exceptions;
+
+use Exception;
+
+class PasswordLoginForbiddenException extends Exception {
+
+}
diff --git a/lib/private/Authentication/Token/DefaultTokenMapper.php b/lib/private/Authentication/Token/DefaultTokenMapper.php
index c56a513b94c..9450ed6b9f3 100644
--- a/lib/private/Authentication/Token/DefaultTokenMapper.php
+++ b/lib/private/Authentication/Token/DefaultTokenMapper.php
@@ -77,6 +77,7 @@ class DefaultTokenMapper extends Mapper {
->execute();
$data = $result->fetch();
+ $result->closeCursor();
if ($data === false) {
throw new DoesNotExistException('token does not exist');
}
diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php
index 805735bd1b8..6ca4fd065a6 100644
--- a/lib/private/Authentication/TwoFactorAuth/Manager.php
+++ b/lib/private/Authentication/TwoFactorAuth/Manager.php
@@ -24,6 +24,7 @@ namespace OC\Authentication\TwoFactorAuth;
use Exception;
use OC;
use OC\App\AppManager;
+use OC_App;
use OCP\AppFramework\QueryException;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\IConfig;
@@ -110,6 +111,7 @@ class Manager {
$providerClasses = $info['two-factor-providers'];
foreach ($providerClasses as $class) {
try {
+ $this->loadTwoFactorApp($appId);
$provider = OC::$server->query($class);
$providers[$provider->getId()] = $provider;
} catch (QueryException $exc) {
@@ -126,6 +128,17 @@ class Manager {
}
/**
+ * Load an app by ID if it has not been loaded yet
+ *
+ * @param string $appId
+ */
+ protected function loadTwoFactorApp($appId) {
+ if (!OC_App::isAppLoaded($appId)) {
+ OC_App::loadApp($appId);
+ }
+ }
+
+ /**
* Verify the given challenge
*
* @param string $providerId
diff --git a/lib/private/Files/Cache/Updater.php b/lib/private/Files/Cache/Updater.php
index 4e17c4d778d..361db4b3f85 100644
--- a/lib/private/Files/Cache/Updater.php
+++ b/lib/private/Files/Cache/Updater.php
@@ -25,6 +25,8 @@
*/
namespace OC\Files\Cache;
+
+use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Cache\IUpdater;
use OCP\Files\Storage\IStorage;
@@ -150,12 +152,20 @@ class Updater implements IUpdater {
$parent = '';
}
+ $entry = $this->cache->get($path);
+
$this->cache->remove($path);
- if ($this->cache instanceof Cache) {
- $this->cache->correctFolderSize($parent);
- }
+
$this->correctParentStorageMtime($path);
- $this->propagator->propagateChange($path, time());
+ if ($entry instanceof ICacheEntry) {
+ $this->propagator->propagateChange($path, time(), -$entry->getSize());
+ } else {
+ $this->propagator->propagateChange($path, time());
+ if ($this->cache instanceof Cache) {
+ $this->cache->correctFolderSize($parent);
+ }
+ }
+
}
/**
diff --git a/lib/private/Files/Config/LazyStorageMountInfo.php b/lib/private/Files/Config/LazyStorageMountInfo.php
index 654c5b2b23e..5df04c4b78e 100644
--- a/lib/private/Files/Config/LazyStorageMountInfo.php
+++ b/lib/private/Files/Config/LazyStorageMountInfo.php
@@ -28,7 +28,7 @@ use OCP\Files\Node;
use OCP\IUser;
class LazyStorageMountInfo extends CachedMountInfo {
- /** @var IMountPoint */
+ /** @var IMountPoint */
private $mount;
/**
@@ -47,7 +47,11 @@ class LazyStorageMountInfo extends CachedMountInfo {
*/
public function getStorageId() {
if (!$this->storageId) {
- $this->storageId = $this->mount->getStorage()->getStorageCache()->getNumericId();
+ $storage = $this->mount->getStorage();
+ if (!$storage) {
+ return -1;
+ }
+ $this->storageId = $storage->getStorageCache()->getNumericId();
}
return parent::getStorageId();
}
diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php
index edb1525b276..bc6ad1b34f0 100644
--- a/lib/private/Files/Config/UserMountCache.php
+++ b/lib/private/Files/Config/UserMountCache.php
@@ -36,6 +36,7 @@ use OCP\IDBConnection;
use OCP\ILogger;
use OCP\IUser;
use OCP\IUserManager;
+use OC\Cache\CappedMemoryCache;
/**
* Cache mounts points per user in the cache so we can easilly look them up
@@ -51,15 +52,23 @@ class UserMountCache implements IUserMountCache {
*/
private $userManager;
- /** @var ICachedMountInfo[][] [$userId => [$cachedMountInfo, ....], ...] */
- private $mountsForUsers = [];
+ /**
+ * Cached mount info.
+ * Map of $userId to ICachedMountInfo.
+ *
+ * @var ICache
+ **/
+ private $mountsForUsers;
/**
* @var ILogger
*/
private $logger;
- private $cacheInfoCache = [];
+ /**
+ * @var ICache
+ */
+ private $cacheInfoCache;
/**
* UserMountCache constructor.
@@ -72,6 +81,8 @@ class UserMountCache implements IUserMountCache {
$this->connection = $connection;
$this->userManager = $userManager;
$this->logger = $logger;
+ $this->cacheInfoCache = new CappedMemoryCache();
+ $this->mountsForUsers = new CappedMemoryCache();
}
public function registerMounts(IUser $user, array $mounts) {
@@ -124,12 +135,16 @@ class UserMountCache implements IUserMountCache {
}
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()
- ], ['root_id', 'user_id']);
+ if ($mount->getStorageId() !== -1) {
+ $this->connection->insertIfNotExist('*PREFIX*mounts', [
+ 'storage_id' => $mount->getStorageId(),
+ 'root_id' => $mount->getRootId(),
+ 'user_id' => $mount->getUser()->getUID(),
+ 'mount_point' => $mount->getMountPoint()
+ ], ['root_id', 'user_id']);
+ } else {
+ $this->logger->error('Error getting storage info for mount at ' . $mount->getMountPoint());
+ }
}
private function setMountPoint(ICachedMountInfo $mount) {
diff --git a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php
index 1f31e849446..5c72bfaa57c 100644
--- a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php
+++ b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php
@@ -39,6 +39,7 @@ class ExcludeFileByNameFilterIterator extends \RecursiveFilterIterator {
'.DS_Store', // Mac OS X
'Thumbs.db', // Microsoft Windows
'.directory', // Dolphin (KDE)
+ '.webapp', // Gentoo/Funtoo & derivatives use a tool known as webapp-config to manager wep-apps.
];
/**
diff --git a/lib/private/Preview.php b/lib/private/Preview.php
index f5e2f6b57e1..8bc262d7047 100644
--- a/lib/private/Preview.php
+++ b/lib/private/Preview.php
@@ -136,9 +136,9 @@ class Preview {
//check if there are preview backends
if (!\OC::$server->getPreviewManager()
- ->hasProviders()
+ ->hasProviders()
&& \OC::$server->getConfig()
- ->getSystemValue('enable_previews', true)
+ ->getSystemValue('enable_previews', true)
) {
\OCP\Util::writeLog('core', 'No preview providers exist', \OCP\Util::ERROR);
throw new \Exception('No preview providers');
@@ -410,6 +410,10 @@ class Preview {
* Deletes all previews of a file
*/
public function deleteAllPreviews() {
+ $thumbnailMount = $this->userView->getMount($this->getThumbnailsFolder());
+ $propagator = $thumbnailMount->getStorage()->getPropagator();
+ $propagator->beginBatch();
+
$toDelete = $this->getChildren();
$toDelete[] = $this->getFileInfo();
@@ -422,11 +426,12 @@ class Preview {
// .ocTransferId*.part file from chunked file upload.
if (!empty($fileId)) {
$previewPath = $this->getPreviewPath($fileId);
- $this->userView->deleteAll($previewPath);
$this->userView->rmdir($previewPath);
}
}
}
+
+ $propagator->commitBatch();
}
/**
@@ -573,8 +578,8 @@ class Preview {
* @return integer[]
*/
private function applyAspectRatio($askedWidth, $askedHeight, $originalWidth = 0, $originalHeight = 0) {
- if(!$originalWidth){
- $originalWidth= $this->maxPreviewWidth;
+ if (!$originalWidth) {
+ $originalWidth = $this->maxPreviewWidth;
}
if (!$originalHeight) {
$originalHeight = $this->maxPreviewHeight;
@@ -1113,7 +1118,7 @@ class Preview {
$preview = null;
$previewProviders = \OC::$server->getPreviewManager()
- ->getProviders();
+ ->getProviders();
foreach ($previewProviders as $supportedMimeType => $providers) {
if (!preg_match($supportedMimeType, $this->mimeType)) {
continue;
@@ -1127,7 +1132,7 @@ class Preview {
\OCP\Util::writeLog(
'core', 'Generating preview for "' . $file . '" with "' . get_class($provider)
- . '"', \OCP\Util::DEBUG
+ . '"', \OCP\Util::DEBUG
);
/** @var $provider Provider */
@@ -1261,7 +1266,7 @@ class Preview {
$absPath = Files\Filesystem::normalizePath($view->getAbsolutePath($path));
$fileInfo = $view->getFileInfo($path);
- if($fileInfo === false) {
+ if ($fileInfo === false) {
return;
}
self::addPathToDeleteFileMapper($absPath, $fileInfo);
diff --git a/lib/private/Repair.php b/lib/private/Repair.php
index bb2967d7e6e..2b33dc413b4 100644
--- a/lib/private/Repair.php
+++ b/lib/private/Repair.php
@@ -36,6 +36,7 @@ use OC\Repair\DropOldJobs;
use OC\Repair\OldGroupMembershipShares;
use OC\Repair\RemoveGetETagEntries;
use OC\Repair\RemoveOldShares;
+use OC\Repair\RemoveRootShares;
use OC\Repair\SharePropagation;
use OC\Repair\SqliteAutoincrement;
use OC\Repair\DropOldTables;
@@ -127,7 +128,7 @@ class Repair implements IOutput{
new RepairLegacyStorages(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
new AssetCache(),
new FillETags(\OC::$server->getDatabaseConnection()),
- new CleanTags(\OC::$server->getDatabaseConnection()),
+ new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()),
new DropOldTables(\OC::$server->getDatabaseConnection()),
new DropOldJobs(\OC::$server->getJobList()),
new RemoveGetETagEntries(\OC::$server->getDatabaseConnection()),
@@ -136,6 +137,7 @@ class Repair implements IOutput{
new SharePropagation(\OC::$server->getConfig()),
new RemoveOldShares(\OC::$server->getDatabaseConnection()),
new AvatarPermissions(\OC::$server->getDatabaseConnection()),
+ new RemoveRootShares(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager(), \OC::$server->getLazyRootFolder()),
];
}
diff --git a/lib/private/Repair/CleanTags.php b/lib/private/Repair/CleanTags.php
index 60ddeff08f3..4241fa6da3a 100644
--- a/lib/private/Repair/CleanTags.php
+++ b/lib/private/Repair/CleanTags.php
@@ -25,6 +25,7 @@ namespace OC\Repair;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
+use OCP\IUserManager;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
@@ -38,11 +39,18 @@ class CleanTags implements IRepairStep {
/** @var IDBConnection */
protected $connection;
+ /** @var IUserManager */
+ protected $userManager;
+
+ protected $deletedTags = 0;
+
/**
* @param IDBConnection $connection
+ * @param IUserManager $userManager
*/
- public function __construct(IDBConnection $connection) {
+ public function __construct(IDBConnection $connection, IUserManager $userManager) {
$this->connection = $connection;
+ $this->userManager = $userManager;
}
/**
@@ -56,12 +64,59 @@ class CleanTags implements IRepairStep {
* Updates the configuration after running an update
*/
public function run(IOutput $output) {
+ $this->deleteOrphanTags($output);
$this->deleteOrphanFileEntries($output);
$this->deleteOrphanTagEntries($output);
$this->deleteOrphanCategoryEntries($output);
}
/**
+ * Delete tags for deleted users
+ */
+ protected function deleteOrphanTags(IOutput $output) {
+ $offset = 0;
+ while ($this->checkTags($offset)) {
+ $offset += 50;
+ }
+
+ $output->info(sprintf('%d tags of deleted users have been removed.', $this->deletedTags));
+ }
+
+ protected function checkTags($offset) {
+ $query = $this->connection->getQueryBuilder();
+ $query->select('uid')
+ ->from('vcategory')
+ ->groupBy('uid')
+ ->orderBy('uid')
+ ->setMaxResults(50)
+ ->setFirstResult($offset);
+ $result = $query->execute();
+
+ $users = [];
+ $hadResults = false;
+ while ($row = $result->fetch()) {
+ $hadResults = true;
+ if (!$this->userManager->userExists($row['uid'])) {
+ $users[] = $row['uid'];
+ }
+ }
+ $result->closeCursor();
+
+ if (!$hadResults) {
+ // No more tags, stop looping
+ return false;
+ }
+
+ if (!empty($users)) {
+ $query = $this->connection->getQueryBuilder();
+ $query->delete('vcategory')
+ ->where($query->expr()->in('uid', $query->createNamedParameter($users, IQueryBuilder::PARAM_STR_ARRAY)));
+ $this->deletedTags += $query->execute();
+ }
+ return true;
+ }
+
+ /**
* Delete tag entries for deleted files
*/
protected function deleteOrphanFileEntries(IOutput $output) {
diff --git a/lib/private/Repair/RemoveRootShares.php b/lib/private/Repair/RemoveRootShares.php
new file mode 100644
index 00000000000..89f797e3ef0
--- /dev/null
+++ b/lib/private/Repair/RemoveRootShares.php
@@ -0,0 +1,157 @@
+<?php
+/**
+ * @author Roeland Jago Douma <rullzer@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\Repair;
+
+use OCP\Files\IRootFolder;
+use OCP\IDBConnection;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+/**
+ * Class RemoveRootShares
+ *
+ * @package OC\Repair
+ */
+class RemoveRootShares implements IRepairStep {
+
+ /** @var IDBConnection */
+ protected $connection;
+
+ /** @var IUserManager */
+ protected $userManager;
+
+ /** @var IRootFolder */
+ protected $rootFolder;
+
+ /**
+ * RemoveRootShares constructor.
+ *
+ * @param IDBConnection $connection
+ * @param IUserManager $userManager
+ * @param IRootFolder $rootFolder
+ */
+ public function __construct(IDBConnection $connection,
+ IUserManager $userManager,
+ IRootFolder $rootFolder) {
+ $this->connection = $connection;
+ $this->userManager = $userManager;
+ $this->rootFolder = $rootFolder;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName() {
+ return 'Remove shares of a users root folder';
+ }
+
+ /**
+ * @param IOutput $output
+ */
+ public function run(IOutput $output) {
+ if ($this->rootSharesExist()) {
+ $this->removeRootShares($output);
+ }
+ }
+
+ /**
+ * @param IOutput $output
+ */
+ private function removeRootShares(IOutput $output) {
+ $function = function(IUser $user) use ($output) {
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $fileId = $userFolder->getId();
+
+ $qb = $this->connection->getQueryBuilder();
+ $qb->delete('share')
+ ->where($qb->expr()->eq('file_source', $qb->createNamedParameter($fileId)))
+ ->andWhere($qb->expr()->orX(
+ $qb->expr()->eq('item_type', $qb->expr()->literal('file')),
+ $qb->expr()->eq('item_type', $qb->expr()->literal('folder'))
+ ));
+
+ $qb->execute();
+
+ $output->advance();
+ };
+
+ $userCount = $this->countUsers();
+ $output->startProgress($userCount);
+
+ $this->userManager->callForAllUsers($function);
+
+ $output->finishProgress();
+ }
+
+ /**
+ * Count all the users
+ *
+ * @return int
+ */
+ private function countUsers() {
+ $allCount = $this->userManager->countUsers();
+
+ $totalCount = 0;
+ foreach ($allCount as $backend => $count) {
+ $totalCount += $count;
+ }
+
+ return $totalCount;
+ }
+
+ /**
+ * Verify if this repair steps is required
+ * It *should* not be necessary in most cases and it can be very
+ * costly.
+ *
+ * @return bool
+ */
+ private function rootSharesExist() {
+ $qb = $this->connection->getQueryBuilder();
+ $qb2 = $this->connection->getQueryBuilder();
+
+ $qb->select('fileid')
+ ->from('filecache')
+ ->where($qb->expr()->eq('path', $qb->expr()->literal('files')));
+
+ $qb2->select('id')
+ ->from('share')
+ ->where($qb2->expr()->in('file_source', $qb2->createFunction($qb->getSQL())))
+ ->andWhere($qb2->expr()->orX(
+ $qb2->expr()->eq('item_type', $qb->expr()->literal('file')),
+ $qb2->expr()->eq('item_type', $qb->expr()->literal('folder'))
+ ))
+ ->setMaxResults(1);
+
+ $cursor = $qb2->execute();
+ $data = $cursor->fetch();
+ $cursor->closeCursor();
+
+ if ($data === false) {
+ return false;
+ }
+
+ return true;
+ }
+}
+
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 5921bbc44c8..2857a394e1e 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -24,25 +24,24 @@
namespace OC\Share20;
+use OC\Cache\CappedMemoryCache;
use OC\Files\Mount\MoveableMount;
+use OCP\Files\File;
+use OCP\Files\Folder;
use OCP\Files\IRootFolder;
+use OCP\Files\Mount\IMountManager;
use OCP\Files\NotFoundException;
-use OCP\IUserManager;
-use OCP\Share\IManager;
-use OCP\Share\IProviderFactory;
-use OC\Share20\Exception\BackendError;
use OCP\IConfig;
+use OCP\IGroupManager;
use OCP\IL10N;
use OCP\ILogger;
-use OCP\Security\ISecureRandom;
+use OCP\IUserManager;
use OCP\Security\IHasher;
-use OCP\Files\Mount\IMountManager;
-use OCP\IGroupManager;
-use OCP\Files\File;
-use OCP\Files\Folder;
-
-use OCP\Share\Exceptions\ShareNotFound;
+use OCP\Security\ISecureRandom;
use OCP\Share\Exceptions\GenericShareException;
+use OCP\Share\Exceptions\ShareNotFound;
+use OCP\Share\IManager;
+use OCP\Share\IProviderFactory;
/**
* This class is the communication hub for all sharing related operations.
@@ -69,6 +68,9 @@ class Manager implements IManager {
private $userManager;
/** @var IRootFolder */
private $rootFolder;
+ /** @var CappedMemoryCache */
+ private $sharingDisabledForUsersCache;
+
/**
* Manager constructor.
@@ -106,6 +108,7 @@ class Manager implements IManager {
$this->factory = $factory;
$this->userManager = $userManager;
$this->rootFolder = $rootFolder;
+ $this->sharingDisabledForUsersCache = new CappedMemoryCache();
}
/**
@@ -1212,6 +1215,14 @@ class Manager implements IManager {
* @return bool
*/
public function sharingDisabledForUser($userId) {
+ if ($userId === null) {
+ return false;
+ }
+
+ if (isset($this->sharingDisabledForUsersCache[$userId])) {
+ return $this->sharingDisabledForUsersCache[$userId];
+ }
+
if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
$groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$excludedGroups = json_decode($groupsList);
@@ -1227,10 +1238,13 @@ class Manager implements IManager {
// if the user is only in groups which are disabled for sharing then
// sharing is also disabled for the user
if (empty($remainingGroups)) {
+ $this->sharingDisabledForUsersCache[$userId] = true;
return true;
}
}
}
+
+ $this->sharingDisabledForUsersCache[$userId] = false;
return false;
}
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index f560bb4bfc0..4e9c827448d 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -33,6 +33,7 @@ namespace OC\User;
use OC;
use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
+use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
use OC\Authentication\Token\IProvider;
use OC\Authentication\Token\IToken;
use OC\Hooks\Emitter;
@@ -348,18 +349,18 @@ class Session implements IUserSession, Emitter {
*
* @param string $user
* @param string $password
+ * @param IRequest $request
* @throws LoginException
+ * @throws PasswordLoginForbiddenException
* @return boolean
*/
- public function logClientIn($user, $password) {
+ public function logClientIn($user, $password, IRequest $request) {
$isTokenPassword = $this->isTokenPassword($password);
if (!$isTokenPassword && $this->isTokenAuthEnforced()) {
- // TODO: throw LoginException instead (https://github.com/owncloud/core/pull/24616)
- return false;
+ throw new PasswordLoginForbiddenException();
}
if (!$isTokenPassword && $this->isTwoFactorEnforced($user)) {
- // TODO: throw LoginException instead (https://github.com/owncloud/core/pull/24616)
- return false;
+ throw new PasswordLoginForbiddenException();
}
if (!$this->login($user, $password) ) {
$users = $this->manager->getByEmail($user);
@@ -368,9 +369,22 @@ class Session implements IUserSession, Emitter {
}
return false;
}
+
+ if ($this->supportsCookies($request)) {
+ $this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
+ }
+
return true;
}
+ protected function supportsCookies(IRequest $request) {
+ if (!is_null($request->getCookie('cookie_test'))) {
+ return true;
+ }
+ setcookie('cookie_test', 'test', $this->timeFacory->getTime() + 3600);
+ return false;
+ }
+
private function isTokenAuthEnforced() {
return $this->config->getSystemValue('token_auth_enforced', false);
}
@@ -428,19 +442,22 @@ class Session implements IUserSession, Emitter {
*/
public function tryBasicAuthLogin(IRequest $request) {
if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) {
- $result = $this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW']);
- if ($result === true) {
- /**
- * Add DAV authenticated. This should in an ideal world not be
- * necessary but the iOS App reads cookies from anywhere instead
- * only the DAV endpoint.
- * This makes sure that the cookies will be valid for the whole scope
- * @see https://github.com/owncloud/core/issues/22893
- */
- $this->session->set(
- Auth::DAV_AUTHENTICATED, $this->getUser()->getUID()
- );
- return true;
+ try {
+ if ($this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW'], $request)) {
+ /**
+ * Add DAV authenticated. This should in an ideal world not be
+ * necessary but the iOS App reads cookies from anywhere instead
+ * only the DAV endpoint.
+ * This makes sure that the cookies will be valid for the whole scope
+ * @see https://github.com/owncloud/core/issues/22893
+ */
+ $this->session->set(
+ Auth::DAV_AUTHENTICATED, $this->getUser()->getUID()
+ );
+ return true;
+ }
+ } catch (PasswordLoginForbiddenException $ex) {
+ // Nothing to do
}
}
return false;