summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/accessibility/lib/Controller/AccessibilityController.php10
-rw-r--r--apps/dav/lib/Connector/Sabre/File.php13
-rw-r--r--apps/dav/lib/Connector/Sabre/FilesPlugin.php8
-rw-r--r--apps/dav/lib/Connector/Sabre/Node.php31
-rw-r--r--apps/files/appinfo/info.xml4
-rw-r--r--apps/files/appinfo/routes.php5
-rw-r--r--apps/files/composer/composer/autoload_classmap.php2
-rw-r--r--apps/files/composer/composer/autoload_static.php2
-rw-r--r--apps/files/js/admin.js70
-rw-r--r--apps/files/lib/Controller/SettingsController.php51
-rw-r--r--apps/files/lib/Settings/Admin.php87
-rw-r--r--apps/files/templates/admin.php20
-rw-r--r--apps/files/tests/Settings/AdminTest.php84
-rw-r--r--apps/files_external/3rdparty/composer.json2
-rw-r--r--apps/files_external/3rdparty/composer.lock12
-rw-r--r--apps/files_external/3rdparty/composer/autoload_classmap.php15
-rw-r--r--apps/files_external/3rdparty/composer/autoload_static.php15
-rw-r--r--apps/files_external/3rdparty/composer/installed.json12
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php6
-rw-r--r--apps/files_external/lib/Command/Notify.php67
-rw-r--r--apps/files_sharing/.l10nignore4
-rw-r--r--apps/files_sharing/lib/External/Manager.php2
-rw-r--r--apps/files_versions/lib/Storage.php15
-rw-r--r--apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php32
-rw-r--r--apps/lookup_server_connector/lib/UpdateLookupServer.php20
-rw-r--r--apps/provisioning_api/lib/Controller/UsersController.php3
-rw-r--r--apps/provisioning_api/tests/Controller/UsersControllerTest.php4
-rw-r--r--apps/twofactor_backupcodes/composer/composer/autoload_classmap.php1
-rw-r--r--apps/twofactor_backupcodes/composer/composer/autoload_static.php1
-rw-r--r--apps/twofactor_backupcodes/lib/AppInfo/Application.php7
-rw-r--r--apps/twofactor_backupcodes/lib/BackgroundJob/RememberBackupCodesJob.php10
-rw-r--r--apps/twofactor_backupcodes/lib/Listener/ProviderDisabled.php65
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php31
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Listener/ProviderDisabledTest.php110
34 files changed, 422 insertions, 399 deletions
diff --git a/apps/accessibility/lib/Controller/AccessibilityController.php b/apps/accessibility/lib/Controller/AccessibilityController.php
index 91c110de868..e17b206cdfd 100644
--- a/apps/accessibility/lib/Controller/AccessibilityController.php
+++ b/apps/accessibility/lib/Controller/AccessibilityController.php
@@ -260,7 +260,15 @@ class AccessibilityController extends Controller {
* @return string
*/
private function invertSvgIconsColor(string $css) {
- return str_replace(['color=000', 'color=fff', 'color=***'], ['color=***', 'color=000', 'color=fff'], $css);
+ return str_replace(
+ ['color=000&', 'color=fff&', 'color=***&'],
+ ['color=***&', 'color=000&', 'color=fff&'],
+ str_replace(
+ ['color=000000&', 'color=ffffff&', 'color=******&'],
+ ['color=******&', 'color=000000&', 'color=ffffff&'],
+ $css
+ )
+ );
}
/**
diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php
index 8aa7d66ba34..3c42f66a04a 100644
--- a/apps/dav/lib/Connector/Sabre/File.php
+++ b/apps/dav/lib/Connector/Sabre/File.php
@@ -169,9 +169,12 @@ class File extends Node implements IFile {
if ($partStorage->instanceOfStorage(Storage\IWriteStreamStorage::class)) {
if (!is_resource($data)) {
- $data = fopen('php://temp', 'r+');
- fwrite($data, 'foobar');
- rewind($data);
+ $tmpData = fopen('php://temp', 'r+');
+ if ($data !== null) {
+ fwrite($tmpData, $data);
+ rewind($tmpData);
+ }
+ $data = $tmpData;
}
$isEOF = false;
@@ -205,7 +208,9 @@ class File extends Node implements IFile {
if (isset($_SERVER['CONTENT_LENGTH'])) {
$expected = $_SERVER['CONTENT_LENGTH'];
}
- throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )');
+ if ($expected !== "0") {
+ throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )');
+ }
}
// if content length is sent by client:
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
index f53f13c5687..99317f2bc1c 100644
--- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
@@ -70,6 +70,7 @@ class FilesPlugin extends ServerPlugin {
const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
const MOUNT_TYPE_PROPERTYNAME = '{http://nextcloud.org/ns}mount-type';
const IS_ENCRYPTED_PROPERTYNAME = '{http://nextcloud.org/ns}is-encrypted';
+ const SHARE_NOTE = '{http://nextcloud.org/ns}note';
/**
* Reference to main server object
@@ -161,6 +162,7 @@ class FilesPlugin extends ServerPlugin {
$server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
$server->protectedProperties[] = self::MOUNT_TYPE_PROPERTYNAME;
$server->protectedProperties[] = self::IS_ENCRYPTED_PROPERTYNAME;
+ $server->protectedProperties[] = self::SHARE_NOTE;
// normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
$allowedProperties = ['{DAV:}getetag'];
@@ -359,6 +361,12 @@ class FilesPlugin extends ServerPlugin {
$propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) {
return $node->getFileInfo()->getMountPoint()->getMountType();
});
+
+ $propFind->handle(self::SHARE_NOTE, function() use ($node, $httpRequest) {
+ return $node->getNoteFromShare(
+ $httpRequest->getRawServerValue('PHP_AUTH_USER')
+ );
+ });
}
if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
diff --git a/apps/dav/lib/Connector/Sabre/Node.php b/apps/dav/lib/Connector/Sabre/Node.php
index 38d0ff57fb2..32ba6c53a0c 100644
--- a/apps/dav/lib/Connector/Sabre/Node.php
+++ b/apps/dav/lib/Connector/Sabre/Node.php
@@ -41,6 +41,8 @@ use OCP\Files\FileInfo;
use OCP\Files\StorageNotAvailableException;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
+use OCP\Share;
+use OCP\Share\IShare;
abstract class Node implements \Sabre\DAV\INode {
@@ -291,6 +293,35 @@ abstract class Node implements \Sabre\DAV\INode {
}
/**
+ * @param string $user
+ * @return string
+ */
+ public function getNoteFromShare($user) {
+ if ($user === null) {
+ return '';
+ }
+
+ $types = [
+ Share::SHARE_TYPE_USER,
+ Share::SHARE_TYPE_GROUP,
+ Share::SHARE_TYPE_CIRCLE,
+ Share::SHARE_TYPE_ROOM
+ ];
+
+ foreach ($types as $shareType) {
+ $shares = $this->shareManager->getSharedWith($user, $shareType, $this, -1);
+ foreach ($shares as $share) {
+ $note = $share->getNote();
+ if($share->getShareOwner() !== $user && !empty($note)) {
+ return $note;
+ }
+ }
+ }
+
+ return '';
+ }
+
+ /**
* @return string
*/
public function getDavPermissions() {
diff --git a/apps/files/appinfo/info.xml b/apps/files/appinfo/info.xml
index d6a0959eebe..79926afe83e 100644
--- a/apps/files/appinfo/info.xml
+++ b/apps/files/appinfo/info.xml
@@ -35,10 +35,6 @@
<command>OCA\Files\Command\ScanAppData</command>
</commands>
- <settings>
- <admin>OCA\Files\Settings\Admin</admin>
- </settings>
-
<activity>
<settings>
<setting>OCA\Files\Activity\Settings\FavoriteAction</setting>
diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php
index 06806309cac..b085d79b8c8 100644
--- a/apps/files/appinfo/routes.php
+++ b/apps/files/appinfo/routes.php
@@ -77,11 +77,6 @@ $application->registerRoutes(
'verb' => 'GET',
],
[
- 'name' => 'settings#setMaxUploadSize',
- 'url' => '/settings/maxUpload',
- 'verb' => 'POST',
- ],
- [
'name' => 'ajax#getStorageStats',
'url' => '/ajax/getstoragestats.php',
'verb' => 'GET',
diff --git a/apps/files/composer/composer/autoload_classmap.php b/apps/files/composer/composer/autoload_classmap.php
index b664b3fa227..dd0bea25644 100644
--- a/apps/files/composer/composer/autoload_classmap.php
+++ b/apps/files/composer/composer/autoload_classmap.php
@@ -31,9 +31,7 @@ return array(
'OCA\\Files\\Command\\TransferOwnership' => $baseDir . '/../lib/Command/TransferOwnership.php',
'OCA\\Files\\Controller\\AjaxController' => $baseDir . '/../lib/Controller/AjaxController.php',
'OCA\\Files\\Controller\\ApiController' => $baseDir . '/../lib/Controller/ApiController.php',
- 'OCA\\Files\\Controller\\SettingsController' => $baseDir . '/../lib/Controller/SettingsController.php',
'OCA\\Files\\Controller\\ViewController' => $baseDir . '/../lib/Controller/ViewController.php',
'OCA\\Files\\Helper' => $baseDir . '/../lib/Helper.php',
'OCA\\Files\\Service\\TagService' => $baseDir . '/../lib/Service/TagService.php',
- 'OCA\\Files\\Settings\\Admin' => $baseDir . '/../lib/Settings/Admin.php',
);
diff --git a/apps/files/composer/composer/autoload_static.php b/apps/files/composer/composer/autoload_static.php
index ef1ecdcc0ce..ae748b5d4d8 100644
--- a/apps/files/composer/composer/autoload_static.php
+++ b/apps/files/composer/composer/autoload_static.php
@@ -46,11 +46,9 @@ class ComposerStaticInitFiles
'OCA\\Files\\Command\\TransferOwnership' => __DIR__ . '/..' . '/../lib/Command/TransferOwnership.php',
'OCA\\Files\\Controller\\AjaxController' => __DIR__ . '/..' . '/../lib/Controller/AjaxController.php',
'OCA\\Files\\Controller\\ApiController' => __DIR__ . '/..' . '/../lib/Controller/ApiController.php',
- 'OCA\\Files\\Controller\\SettingsController' => __DIR__ . '/..' . '/../lib/Controller/SettingsController.php',
'OCA\\Files\\Controller\\ViewController' => __DIR__ . '/..' . '/../lib/Controller/ViewController.php',
'OCA\\Files\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php',
'OCA\\Files\\Service\\TagService' => __DIR__ . '/..' . '/../lib/Service/TagService.php',
- 'OCA\\Files\\Settings\\Admin' => __DIR__ . '/..' . '/../lib/Settings/Admin.php',
);
public static function getInitializer(ClassLoader $loader)
diff --git a/apps/files/js/admin.js b/apps/files/js/admin.js
deleted file mode 100644
index 6afd77eb03e..00000000000
--- a/apps/files/js/admin.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2014
- *
- * This file is licensed under the Affero General Public License version 3
- * or later.
- *
- * See the COPYING-README file.
- *
- */
-
-(function() {
- if (!OCA.Files) {
- /**
- * Namespace for the files app
- * @namespace OCA.Files
- */
- OCA.Files = {};
- }
-
- /**
- * @namespace OCA.Files.Admin
- */
- OCA.Files.Admin = {
- initialize: function() {
- $('#submitMaxUpload').on('click', _.bind(this._onClickSubmitMaxUpload, this));
- },
-
- _onClickSubmitMaxUpload: function () {
- OC.msg.startSaving('#maxUploadSizeSettingsMsg');
-
- var request = $.ajax({
- url: OC.generateUrl('/apps/files/settings/maxUpload'),
- type: 'POST',
- data: {
- maxUploadSize: $('#maxUploadSize').val()
- }
- });
-
- request.done(function (data) {
- $('#maxUploadSize').val(data.maxUploadSize);
- OC.msg.finishedSuccess('#maxUploadSizeSettingsMsg', 'Saved');
- });
-
- request.fail(function () {
- OC.msg.finishedError('#maxUploadSizeSettingsMsg', 'Error');
- });
- }
- }
-})();
-
-function switchPublicFolder() {
- var publicEnable = $('#publicEnable').is(':checked');
- // find all radiobuttons of that group
- var sharingaimGroup = $('input:radio[name=sharingaim]');
- $.each(sharingaimGroup, function(index, sharingaimItem) {
- // set all buttons to the correct state
- sharingaimItem.disabled = !publicEnable;
- });
-}
-
-$(document).ready(function() {
- OCA.Files.Admin.initialize();
-
- // Execute the function after loading DOM tree
- switchPublicFolder();
- $('#publicEnable').click(function() {
- // To get rid of onClick()
- switchPublicFolder();
- });
-});
diff --git a/apps/files/lib/Controller/SettingsController.php b/apps/files/lib/Controller/SettingsController.php
deleted file mode 100644
index 0b2dc9c2dd1..00000000000
--- a/apps/files/lib/Controller/SettingsController.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-/**
- *
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-namespace OCA\Files\Controller;
-
-use OCP\AppFramework\Controller;
-use OCP\AppFramework\Http;
-use OCP\AppFramework\Http\JSONResponse;
-use OCP\IRequest;
-use OCP\Util;
-
-class SettingsController extends Controller {
- public function __construct($appName, IRequest $request) {
- parent::__construct($appName, $request);
- }
-
- /**
- * @param string $maxUploadSize
- * @return JSONResponse
- */
- public function setMaxUploadSize($maxUploadSize) {
- $setMaxSize = \OC_Files::setUploadLimit(Util::computerFileSize($maxUploadSize));
-
- if ($setMaxSize === false) {
- return new JSONResponse([], Http::STATUS_BAD_REQUEST);
- } else {
- return new JSONResponse([
- 'maxUploadSize' => Util::humanFileSize($setMaxSize)
- ]);
- }
- }
-}
diff --git a/apps/files/lib/Settings/Admin.php b/apps/files/lib/Settings/Admin.php
deleted file mode 100644
index 11b66dab846..00000000000
--- a/apps/files/lib/Settings/Admin.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-namespace OCA\Files\Settings;
-
-use bantu\IniGetWrapper\IniGetWrapper;
-use OCP\AppFramework\Http\TemplateResponse;
-use OCP\IRequest;
-use OCP\Settings\ISettings;
-use OCP\Util;
-
-class Admin implements ISettings {
-
- /** @var IniGetWrapper */
- private $iniWrapper;
-
- /** @var IRequest */
- private $request;
-
- public function __construct(IniGetWrapper $iniWrapper, IRequest $request) {
- $this->iniWrapper = $iniWrapper;
- $this->request = $request;
- }
-
- /**
- * @return TemplateResponse
- */
- public function getForm() {
- $htaccessWorking = (getenv('htaccessWorking') === 'true');
- $htaccessWritable = is_writable(\OC::$SERVERROOT.'/.htaccess');
- $userIniWritable = is_writable(\OC::$SERVERROOT.'/.user.ini');
-
- $upload_max_filesize = $this->iniWrapper->getBytes('upload_max_filesize');
- $post_max_size = $this->iniWrapper->getBytes('post_max_size');
- $maxUploadFilesize = Util::humanFileSize(min($upload_max_filesize, $post_max_size));
-
- $parameters = [
- 'uploadChangable' => ($htaccessWorking and $htaccessWritable) or $userIniWritable,
- 'uploadMaxFilesize' => $maxUploadFilesize,
- // max possible makes only sense on a 32 bit system
- 'displayMaxPossibleUploadSize' => PHP_INT_SIZE === 4,
- 'maxPossibleUploadSize' => Util::humanFileSize(PHP_INT_MAX),
- ];
-
- return new TemplateResponse('files', 'admin', $parameters, '');
- }
-
- /**
- * @return string the section ID, e.g. 'sharing'
- */
- public function getSection() {
- return 'server';
- }
-
- /**
- * @return int whether the form should be rather on the top or bottom of
- * the admin section. The forms are arranged in ascending order of the
- * priority values. It is required to return a value between 0 and 100.
- *
- * E.g.: 70
- */
- public function getPriority() {
- return 5;
- }
-
-}
diff --git a/apps/files/templates/admin.php b/apps/files/templates/admin.php
deleted file mode 100644
index 1cbb339fee7..00000000000
--- a/apps/files/templates/admin.php
+++ /dev/null
@@ -1,20 +0,0 @@
- <?php OCP\Util::addScript('files', 'admin'); ?>
-
- <div class="section">
- <h2><?php p($l->t('File handling')); ?></h2>
- <label for="maxUploadSize"><?php p($l->t( 'Maximum upload size' )); ?> </label>
- <span id="maxUploadSizeSettingsMsg" class="msg"></span>
- <br />
- <input type="text" name='maxUploadSize' id="maxUploadSize" value='<?php p($_['uploadMaxFilesize']) ?>' <?php if(!$_['uploadChangable']) { p('disabled'); } ?> />
- <?php if($_['displayMaxPossibleUploadSize']):?>
- (<?php p($l->t('max. possible: ')); p($_['maxPossibleUploadSize']) ?>)
- <?php endif;?>
- <input type="hidden" value="<?php p($_['requesttoken']); ?>" name="requesttoken" />
- <?php if($_['uploadChangable']): ?>
- <input type="submit" id="submitMaxUpload"
- value="<?php p($l->t( 'Save' )); ?>"/>
- <p><em><?php p($l->t('With PHP-FPM it might take 5 minutes for changes to be applied.')); ?></em></p>
- <?php else: ?>
- <p><em><?php p($l->t('Missing permissions to edit from here.')); ?></em></p>
- <?php endif; ?>
- </div>
diff --git a/apps/files/tests/Settings/AdminTest.php b/apps/files/tests/Settings/AdminTest.php
deleted file mode 100644
index 027a37d7b2f..00000000000
--- a/apps/files/tests/Settings/AdminTest.php
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * 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
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-namespace OCA\Files\Tests\Settings;
-
-use bantu\IniGetWrapper\IniGetWrapper;
-use OCA\Files\Settings\Admin;
-use OCP\AppFramework\Http\TemplateResponse;
-use OCP\IRequest;
-use OCP\Util;
-use Test\TestCase;
-
-class AdminTest extends TestCase {
- /** @var Admin */
- private $admin;
- /** @var IniGetWrapper */
- private $iniGetWrapper;
- /** @var IRequest */
- private $request;
-
- public function setUp() {
- parent::setUp();
- $this->iniGetWrapper = $this->getMockBuilder('\bantu\IniGetWrapper\IniGetWrapper')->disableOriginalConstructor()->getMock();
- $this->request = $this->getMockBuilder(IRequest::class)->getMock();
- $this->admin = new Admin(
- $this->iniGetWrapper,
- $this->request
- );
- }
-
- public function testGetForm() {
- $htaccessWorking = (getenv('htaccessWorking') == 'true');
- $htaccessWritable = is_writable(\OC::$SERVERROOT.'/.htaccess');
- $userIniWritable = is_writable(\OC::$SERVERROOT.'/.user.ini');
-
- $this->iniGetWrapper
- ->expects($this->at(0))
- ->method('getBytes')
- ->with('upload_max_filesize')
- ->willReturn(1234);
- $this->iniGetWrapper
- ->expects($this->at(1))
- ->method('getBytes')
- ->with('post_max_size')
- ->willReturn(1234);
- $params = [
- 'uploadChangable' => (($htaccessWorking and $htaccessWritable) or $userIniWritable ),
- 'uploadMaxFilesize' => '1 KB',
- 'displayMaxPossibleUploadSize' => PHP_INT_SIZE === 4,
- 'maxPossibleUploadSize' => Util::humanFileSize(PHP_INT_MAX),
- ];
- $expected = new TemplateResponse('files', 'admin', $params, '');
- $this->assertEquals($expected, $this->admin->getForm());
- }
-
- public function testGetSection() {
- $this->assertSame('server', $this->admin->getSection());
- }
-
- public function testGetPriority() {
- $this->assertSame(5, $this->admin->getPriority());
- }
-}
diff --git a/apps/files_external/3rdparty/composer.json b/apps/files_external/3rdparty/composer.json
index 20e4b8a4d38..897234dfce0 100644
--- a/apps/files_external/3rdparty/composer.json
+++ b/apps/files_external/3rdparty/composer.json
@@ -9,6 +9,6 @@
},
"require": {
"icewind/streams": "0.6.1",
- "icewind/smb": "3.1.0"
+ "icewind/smb": "3.1.1"
}
}
diff --git a/apps/files_external/3rdparty/composer.lock b/apps/files_external/3rdparty/composer.lock
index 33c975a7d77..69da480d19f 100644
--- a/apps/files_external/3rdparty/composer.lock
+++ b/apps/files_external/3rdparty/composer.lock
@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "ea11a8c6e4979d35dd3bdf1f057ef0e8",
+ "content-hash": "dd320be9cd87742d53b4384bf3df9c42",
"packages": [
{
"name": "icewind/smb",
- "version": "v3.1.0",
+ "version": "v3.1.1",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/SMB.git",
- "reference": "db16d4430cb75f0196eaa6377c5766b19f744c8d"
+ "reference": "26b7b8780342d0e61313b464b880d50a2ea898e2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/icewind1991/SMB/zipball/db16d4430cb75f0196eaa6377c5766b19f744c8d",
- "reference": "db16d4430cb75f0196eaa6377c5766b19f744c8d",
+ "url": "https://api.github.com/repos/icewind1991/SMB/zipball/26b7b8780342d0e61313b464b880d50a2ea898e2",
+ "reference": "26b7b8780342d0e61313b464b880d50a2ea898e2",
"shasum": ""
},
"require": {
@@ -46,7 +46,7 @@
}
],
"description": "php wrapper for smbclient and libsmbclient-php",
- "time": "2019-02-06T14:17:35+00:00"
+ "time": "2019-03-04T15:02:42+00:00"
},
{
"name": "icewind/streams",
diff --git a/apps/files_external/3rdparty/composer/autoload_classmap.php b/apps/files_external/3rdparty/composer/autoload_classmap.php
index b92bd22b4f0..9eb83e893bd 100644
--- a/apps/files_external/3rdparty/composer/autoload_classmap.php
+++ b/apps/files_external/3rdparty/composer/autoload_classmap.php
@@ -76,21 +76,6 @@ return array(
'Icewind\\Streams\\PathWrapper' => $vendorDir . '/icewind/streams/src/PathWrapper.php',
'Icewind\\Streams\\RetryWrapper' => $vendorDir . '/icewind/streams/src/RetryWrapper.php',
'Icewind\\Streams\\SeekableWrapper' => $vendorDir . '/icewind/streams/src/SeekableWrapper.php',
- 'Icewind\\Streams\\Tests\\CallbackWrapperTest' => $vendorDir . '/icewind/streams/tests/CallbackWrapperTest.php',
- 'Icewind\\Streams\\Tests\\CountWrapperTest' => $vendorDir . '/icewind/streams/tests/CountWrapperTest.php',
- 'Icewind\\Streams\\Tests\\DirectoryFilter' => $vendorDir . '/icewind/streams/tests/DirectoryFilter.php',
- 'Icewind\\Streams\\Tests\\DirectoryWrapper' => $vendorDir . '/icewind/streams/tests/DirectoryWrapper.php',
- 'Icewind\\Streams\\Tests\\DirectoryWrapperDummy' => $vendorDir . '/icewind/streams/tests/DirectoryWrapper.php',
- 'Icewind\\Streams\\Tests\\DirectoryWrapperNull' => $vendorDir . '/icewind/streams/tests/DirectoryWrapper.php',
- 'Icewind\\Streams\\Tests\\FailWrapper' => $vendorDir . '/icewind/streams/tests/RetryWrapper.php',
- 'Icewind\\Streams\\Tests\\IteratorDirectory' => $vendorDir . '/icewind/streams/tests/IteratorDirectory.php',
- 'Icewind\\Streams\\Tests\\NullWrapperTest' => $vendorDir . '/icewind/streams/tests/NullWrapperTest.php',
- 'Icewind\\Streams\\Tests\\PartialWrapper' => $vendorDir . '/icewind/streams/tests/RetryWrapper.php',
- 'Icewind\\Streams\\Tests\\PathWrapper' => $vendorDir . '/icewind/streams/tests/PathWrapper.php',
- 'Icewind\\Streams\\Tests\\RetryWrapperTest' => $vendorDir . '/icewind/streams/tests/RetryWrapper.php',
- 'Icewind\\Streams\\Tests\\SeekableWrapper' => $vendorDir . '/icewind/streams/tests/SeekableWrapper.php',
- 'Icewind\\Streams\\Tests\\UrlCallBack' => $vendorDir . '/icewind/streams/tests/UrlCallBack.php',
- 'Icewind\\Streams\\Tests\\WrapperTest' => $vendorDir . '/icewind/streams/tests/WrapperTest.php',
'Icewind\\Streams\\Url' => $vendorDir . '/icewind/streams/src/Url.php',
'Icewind\\Streams\\UrlCallback' => $vendorDir . '/icewind/streams/src/UrlCallBack.php',
'Icewind\\Streams\\Wrapper' => $vendorDir . '/icewind/streams/src/Wrapper.php',
diff --git a/apps/files_external/3rdparty/composer/autoload_static.php b/apps/files_external/3rdparty/composer/autoload_static.php
index 6d7ed9d8536..eb2329b2b05 100644
--- a/apps/files_external/3rdparty/composer/autoload_static.php
+++ b/apps/files_external/3rdparty/composer/autoload_static.php
@@ -106,21 +106,6 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3
'Icewind\\Streams\\PathWrapper' => __DIR__ . '/..' . '/icewind/streams/src/PathWrapper.php',
'Icewind\\Streams\\RetryWrapper' => __DIR__ . '/..' . '/icewind/streams/src/RetryWrapper.php',
'Icewind\\Streams\\SeekableWrapper' => __DIR__ . '/..' . '/icewind/streams/src/SeekableWrapper.php',
- 'Icewind\\Streams\\Tests\\CallbackWrapperTest' => __DIR__ . '/..' . '/icewind/streams/tests/CallbackWrapperTest.php',
- 'Icewind\\Streams\\Tests\\CountWrapperTest' => __DIR__ . '/..' . '/icewind/streams/tests/CountWrapperTest.php',
- 'Icewind\\Streams\\Tests\\DirectoryFilter' => __DIR__ . '/..' . '/icewind/streams/tests/DirectoryFilter.php',
- 'Icewind\\Streams\\Tests\\DirectoryWrapper' => __DIR__ . '/..' . '/icewind/streams/tests/DirectoryWrapper.php',
- 'Icewind\\Streams\\Tests\\DirectoryWrapperDummy' => __DIR__ . '/..' . '/icewind/streams/tests/DirectoryWrapper.php',
- 'Icewind\\Streams\\Tests\\DirectoryWrapperNull' => __DIR__ . '/..' . '/icewind/streams/tests/DirectoryWrapper.php',
- 'Icewind\\Streams\\Tests\\FailWrapper' => __DIR__ . '/..' . '/icewind/streams/tests/RetryWrapper.php',
- 'Icewind\\Streams\\Tests\\IteratorDirectory' => __DIR__ . '/..' . '/icewind/streams/tests/IteratorDirectory.php',
- 'Icewind\\Streams\\Tests\\NullWrapperTest' => __DIR__ . '/..' . '/icewind/streams/tests/NullWrapperTest.php',
- 'Icewind\\Streams\\Tests\\PartialWrapper' => __DIR__ . '/..' . '/icewind/streams/tests/RetryWrapper.php',
- 'Icewind\\Streams\\Tests\\PathWrapper' => __DIR__ . '/..' . '/icewind/streams/tests/PathWrapper.php',
- 'Icewind\\Streams\\Tests\\RetryWrapperTest' => __DIR__ . '/..' . '/icewind/streams/tests/RetryWrapper.php',
- 'Icewind\\Streams\\Tests\\SeekableWrapper' => __DIR__ . '/..' . '/icewind/streams/tests/SeekableWrapper.php',
- 'Icewind\\Streams\\Tests\\UrlCallBack' => __DIR__ . '/..' . '/icewind/streams/tests/UrlCallBack.php',
- 'Icewind\\Streams\\Tests\\WrapperTest' => __DIR__ . '/..' . '/icewind/streams/tests/WrapperTest.php',
'Icewind\\Streams\\Url' => __DIR__ . '/..' . '/icewind/streams/src/Url.php',
'Icewind\\Streams\\UrlCallback' => __DIR__ . '/..' . '/icewind/streams/src/UrlCallBack.php',
'Icewind\\Streams\\Wrapper' => __DIR__ . '/..' . '/icewind/streams/src/Wrapper.php',
diff --git a/apps/files_external/3rdparty/composer/installed.json b/apps/files_external/3rdparty/composer/installed.json
index ff953699268..b6c0b4d751c 100644
--- a/apps/files_external/3rdparty/composer/installed.json
+++ b/apps/files_external/3rdparty/composer/installed.json
@@ -1,17 +1,17 @@
[
{
"name": "icewind/smb",
- "version": "v3.1.0",
- "version_normalized": "3.1.0.0",
+ "version": "v3.1.1",
+ "version_normalized": "3.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/SMB.git",
- "reference": "db16d4430cb75f0196eaa6377c5766b19f744c8d"
+ "reference": "26b7b8780342d0e61313b464b880d50a2ea898e2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/icewind1991/SMB/zipball/db16d4430cb75f0196eaa6377c5766b19f744c8d",
- "reference": "db16d4430cb75f0196eaa6377c5766b19f744c8d",
+ "url": "https://api.github.com/repos/icewind1991/SMB/zipball/26b7b8780342d0e61313b464b880d50a2ea898e2",
+ "reference": "26b7b8780342d0e61313b464b880d50a2ea898e2",
"shasum": ""
},
"require": {
@@ -22,7 +22,7 @@
"friendsofphp/php-cs-fixer": "^2.13",
"phpunit/phpunit": "^5.7"
},
- "time": "2019-02-06T14:17:35+00:00",
+ "time": "2019-03-04T15:02:42+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php
index de0a1de40ee..830f6fb17b0 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php
@@ -66,7 +66,11 @@ class Connection extends RawConnection {
$this->parser->checkConnectionError($promptLine);
$output = [];
- $line = $this->readLine();
+ if (!$this->isPrompt($promptLine)) {
+ $line = $promptLine;
+ } else {
+ $line = $this->readLine();
+ }
if ($line === false) {
$this->unknownError($promptLine);
}
diff --git a/apps/files_external/lib/Command/Notify.php b/apps/files_external/lib/Command/Notify.php
index b859a825c80..556687e6930 100644
--- a/apps/files_external/lib/Command/Notify.php
+++ b/apps/files_external/lib/Command/Notify.php
@@ -2,6 +2,7 @@
/**
* @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl>
*
+ * @author Ari Selseng <ari@selseng.net>
* @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
@@ -24,6 +25,7 @@
namespace OCA\Files_External\Command;
+use Doctrine\DBAL\Exception\DriverException;
use OC\Core\Command\Base;
use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
use OCA\Files_External\Lib\StorageConfig;
@@ -35,6 +37,7 @@ use OCP\Files\Storage\INotifyStorage;
use OCP\Files\Storage\IStorage;
use OCP\Files\StorageNotAvailableException;
use OCP\IDBConnection;
+use OCP\ILogger;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -47,17 +50,15 @@ class Notify extends Base {
private $connection;
/** @var \OCP\DB\QueryBuilder\IQueryBuilder */
private $updateQuery;
+ /** @var ILogger */
+ private $logger;
- function __construct(GlobalStoragesService $globalService, IDBConnection $connection) {
+ function __construct(GlobalStoragesService $globalService, IDBConnection $connection, ILogger $logger) {
parent::__construct();
$this->globalService = $globalService;
$this->connection = $connection;
- // the query builder doesn't really like subqueries with parameters
- $this->updateQuery = $this->connection->prepare(
- 'UPDATE *PREFIX*filecache SET size = -1
- WHERE `path` = ?
- AND `storage` IN (SELECT storage_id FROM *PREFIX*mounts WHERE mount_id = ?)'
- );
+ $this->logger = $logger;
+ $this->updateQuery = $this->getUpdateQuery($this->connection);
}
protected function configure() {
@@ -143,9 +144,9 @@ class Notify extends Base {
$this->logUpdate($change, $output);
}
if ($change instanceof IRenameChange) {
- $this->markParentAsOutdated($mount->getId(), $change->getTargetPath());
+ $this->markParentAsOutdated($mount->getId(), $change->getTargetPath(), $output);
}
- $this->markParentAsOutdated($mount->getId(), $change->getPath());
+ $this->markParentAsOutdated($mount->getId(), $change->getPath(), $output);
});
}
@@ -154,12 +155,21 @@ class Notify extends Base {
return new $class($mount->getBackendOptions());
}
- private function markParentAsOutdated($mountId, $path) {
+ private function markParentAsOutdated($mountId, $path, OutputInterface $output) {
$parent = ltrim(dirname($path), '/');
if ($parent === '.') {
$parent = '';
}
- $this->updateQuery->execute([$parent, $mountId]);
+
+ try {
+ $this->updateQuery->execute([$parent, $mountId]);
+ } catch (DriverException $ex) {
+ $this->logger->logException($ex, ['app' => 'files_external', 'message' => 'Error while trying to mark folder as outdated', 'level' => ILogger::WARN]);
+ $this->connection = $this->reconnectToDatabase($this->connection, $output);
+ $output->writeln('<info>Needed to reconnect to the database</info>');
+ $this->updateQuery = $this->getUpdateQuery($this->connection);
+ $this->updateQuery->execute([$parent, $mountId]);
+ }
}
private function logUpdate(IChange $change, OutputInterface $output) {
@@ -188,6 +198,41 @@ class Notify extends Base {
$output->writeln($text);
}
+ /**
+ * @return \Doctrine\DBAL\Statement
+ */
+ private function getUpdateQuery(IDBConnection $connection) {
+ // the query builder doesn't really like subqueries with parameters
+ return $connection->prepare(
+ 'UPDATE *PREFIX*filecache SET size = -1
+ WHERE `path` = ?
+ AND `storage` IN (SELECT storage_id FROM *PREFIX*mounts WHERE mount_id = ?)'
+ );
+ }
+
+ /**
+ * @return \OCP\IDBConnection
+ */
+ private function reconnectToDatabase(IDBConnection $connection, OutputInterface $output) {
+ try {
+ $connection->close();
+ } catch (\Exception $ex) {
+ $this->logger->logException($ex, ['app' => 'files_external', 'message' => 'Error while disconnecting from DB', 'level' => ILogger::WARN]);
+ $output->writeln("<info>Error while disconnecting from database: {$ex->getMessage()}</info>");
+ }
+ while (!$connection->isConnected()) {
+ try {
+ $connection->connect();
+ } catch (\Exception $ex) {
+ $this->logger->logException($ex, ['app' => 'files_external', 'message' => 'Error while re-connecting to database', 'level' => ILogger::WARN]);
+ $output->writeln("<info>Error while re-connecting to database: {$ex->getMessage()}</info>");
+ sleep(60);
+ }
+ }
+ return $connection;
+ }
+
+
private function selfTest(IStorage $storage, INotifyHandler $notifyHandler, $verbose, OutputInterface $output) {
usleep(100 * 1000); //give time for the notify to start
$storage->file_put_contents('/.nc_test_file.txt', 'test content');
diff --git a/apps/files_sharing/.l10nignore b/apps/files_sharing/.l10nignore
index dfb7d6c4e6d..f5aa2c6a868 100644
--- a/apps/files_sharing/.l10nignore
+++ b/apps/files_sharing/.l10nignore
@@ -1,2 +1,6 @@
#webpack bundled files
js/additionalScripts.js
+js/dist/additionalScripts.js
+js/dist/files_sharing.js
+js/dist/files_sharing2.js
+js/dist/files_sharing3.js
diff --git a/apps/files_sharing/lib/External/Manager.php b/apps/files_sharing/lib/External/Manager.php
index 6a036b663d9..0cf7d899234 100644
--- a/apps/files_sharing/lib/External/Manager.php
+++ b/apps/files_sharing/lib/External/Manager.php
@@ -522,7 +522,7 @@ class Manager {
$share = $getShare->fetch();
$getShare->closeCursor();
- if ($result && (int)$share['share_type'] === Share::SHARE_TYPE_USER) {
+ if ($result && $share !== false && (int)$share['share_type'] === Share::SHARE_TYPE_USER) {
try {
$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
} catch (\Exception $e) {
diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php
index e2e4888cbce..c09633be3c1 100644
--- a/apps/files_versions/lib/Storage.php
+++ b/apps/files_versions/lib/Storage.php
@@ -750,13 +750,16 @@ class Storage {
// subtract size of files and current versions size from quota
if ($quota >= 0) {
if ($softQuota) {
- $files_view = new View('/' . $uid . '/files');
- $rootInfo = $files_view->getFileInfo('/', false);
- $free = $quota - $rootInfo['size']; // remaining free space for user
- if ($free > 0) {
- $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $versionsSize; // how much space can be used for versions
+ $userFolder = \OC::$server->getUserFolder($uid);
+ if(is_null($userFolder)) {
+ $availableSpace = 0;
} else {
- $availableSpace = $free - $versionsSize;
+ $free = $quota - $userFolder->getSize(false); // remaining free space for user
+ if ($free > 0) {
+ $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $versionsSize; // how much space can be used for versions
+ } else {
+ $availableSpace = $free - $versionsSize;
+ }
}
} else {
$availableSpace = $quota;
diff --git a/apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php b/apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php
index 5a7212a6522..242b0c713fe 100644
--- a/apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php
+++ b/apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php
@@ -36,8 +36,10 @@ class RetryJob extends Job {
private $jobList;
/** @var string */
private $lookupServer;
- /** @var int how much time should be between two tries (10 minutes) */
- private $interval = 600;
+ /** @var int how much time should be between two, will be increased for each retry */
+ private $interval = 100;
+ /** @var IConfig */
+ private $config;
/**
* @param IClientService $clientService
@@ -49,6 +51,7 @@ class RetryJob extends Job {
IConfig $config) {
$this->clientService = $clientService;
$this->jobList = $jobList;
+ $this->config = $config;
if ($config->getSystemValue('has_internet_connection', true) === false) {
return;
@@ -75,7 +78,7 @@ class RetryJob extends Job {
}
protected function run($argument) {
- if ($argument['retryNo'] === 5 || empty($this->lookupServer)) {
+ if ($this->killBackgroundJob((int)$argument['retryNo'])) {
return;
}
@@ -108,6 +111,27 @@ class RetryJob extends Job {
* @return bool
*/
protected function shouldRun($argument) {
- return !isset($argument['lastRun']) || ((time() - $argument['lastRun']) > $this->interval);
+ $retryNo = (int)$argument['retryNo'];
+ $delay = $this->interval * 6 ** $retryNo;
+ return !isset($argument['lastRun']) || ((time() - $argument['lastRun']) > $delay);
+ }
+
+ /**
+ * check if we should kill the background job
+ *
+ * The lookup server should no longer be contacted if:
+ *
+ * - max retries are reached (set to 5)
+ * - lookup server was disabled by the admin
+ * - no valid lookup server URL given
+ *
+ * @param int $retryCount
+ * @return bool
+ */
+ protected function killBackgroundJob($retryCount) {
+ $maxTriesReached = $retryCount >= 5;
+ $lookupServerDisabled = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes') !== 'yes';
+
+ return $maxTriesReached || $lookupServerDisabled || empty($this->lookupServer);
}
}
diff --git a/apps/lookup_server_connector/lib/UpdateLookupServer.php b/apps/lookup_server_connector/lib/UpdateLookupServer.php
index 7902ede8816..f96b3d787f2 100644
--- a/apps/lookup_server_connector/lib/UpdateLookupServer.php
+++ b/apps/lookup_server_connector/lib/UpdateLookupServer.php
@@ -46,6 +46,8 @@ class UpdateLookupServer {
private $jobList;
/** @var string URL point to lookup server */
private $lookupServer;
+ /** @var bool */
+ private $lookupServerEnabled;
/**
* @param AccountManager $accountManager
@@ -68,6 +70,8 @@ class UpdateLookupServer {
return;
}
+ $this->lookupServerEnabled = $config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes') === 'yes';
+
$this->lookupServer = $config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com');
if(!empty($this->lookupServer)) {
$this->lookupServer = rtrim($this->lookupServer, '/');
@@ -79,7 +83,8 @@ class UpdateLookupServer {
* @param IUser $user
*/
public function userUpdated(IUser $user) {
- if(empty($this->lookupServer)) {
+
+ if (!$this->shouldUpdateLookupServer()) {
return;
}
@@ -150,4 +155,17 @@ class UpdateLookupServer {
);
}
}
+
+ /**
+ * check if we should update the lookup server, we only do it if
+ *
+ * * we have a valid URL
+ * * the lookup server update was enabled by the admin
+ *
+ * @return bool
+ */
+ private function shouldUpdateLookupServer() {
+ return $this->lookupServerEnabled || !empty($this->lookupServer);
+ }
+
}
diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php
index a034ff6d77a..c7625a26f59 100644
--- a/apps/provisioning_api/lib/Controller/UsersController.php
+++ b/apps/provisioning_api/lib/Controller/UsersController.php
@@ -513,6 +513,9 @@ class UsersController extends AUserData {
break;
case 'password':
try {
+ if (!$targetUser->canChangePassword()) {
+ throw new OCSException('Setting the password is not supported by the users backend', 103);
+ }
$targetUser->setPassword($value);
} catch (HintException $e) { // password policy error
throw new OCSException($e->getMessage(), 103);
diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php
index fcdc68d353b..c6e0082c4b0 100644
--- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php
+++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php
@@ -1272,6 +1272,10 @@ class UsersControllerTest extends TestCase {
->will($this->returnValue($targetUser));
$targetUser
->expects($this->once())
+ ->method('canChangePassword')
+ ->will($this->returnValue(true));
+ $targetUser
+ ->expects($this->once())
->method('setPassword')
->with('NewPassword');
$targetUser
diff --git a/apps/twofactor_backupcodes/composer/composer/autoload_classmap.php b/apps/twofactor_backupcodes/composer/composer/autoload_classmap.php
index c093a1112a3..2038421a3a2 100644
--- a/apps/twofactor_backupcodes/composer/composer/autoload_classmap.php
+++ b/apps/twofactor_backupcodes/composer/composer/autoload_classmap.php
@@ -17,6 +17,7 @@ return array(
'OCA\\TwoFactorBackupCodes\\Listener\\ActivityPublisher' => $baseDir . '/../lib/Listener/ActivityPublisher.php',
'OCA\\TwoFactorBackupCodes\\Listener\\ClearNotifications' => $baseDir . '/../lib/Listener/ClearNotifications.php',
'OCA\\TwoFactorBackupCodes\\Listener\\IListener' => $baseDir . '/../lib/Listener/IListener.php',
+ 'OCA\\TwoFactorBackupCodes\\Listener\\ProviderDisabled' => $baseDir . '/../lib/Listener/ProviderDisabled.php',
'OCA\\TwoFactorBackupCodes\\Listener\\ProviderEnabled' => $baseDir . '/../lib/Listener/ProviderEnabled.php',
'OCA\\TwoFactorBackupCodes\\Listener\\RegistryUpdater' => $baseDir . '/../lib/Listener/RegistryUpdater.php',
'OCA\\TwoFactorBackupCodes\\Migration\\CheckBackupCodes' => $baseDir . '/../lib/Migration/CheckBackupCodes.php',
diff --git a/apps/twofactor_backupcodes/composer/composer/autoload_static.php b/apps/twofactor_backupcodes/composer/composer/autoload_static.php
index baad28d711a..d1f124a407d 100644
--- a/apps/twofactor_backupcodes/composer/composer/autoload_static.php
+++ b/apps/twofactor_backupcodes/composer/composer/autoload_static.php
@@ -32,6 +32,7 @@ class ComposerStaticInitTwoFactorBackupCodes
'OCA\\TwoFactorBackupCodes\\Listener\\ActivityPublisher' => __DIR__ . '/..' . '/../lib/Listener/ActivityPublisher.php',
'OCA\\TwoFactorBackupCodes\\Listener\\ClearNotifications' => __DIR__ . '/..' . '/../lib/Listener/ClearNotifications.php',
'OCA\\TwoFactorBackupCodes\\Listener\\IListener' => __DIR__ . '/..' . '/../lib/Listener/IListener.php',
+ 'OCA\\TwoFactorBackupCodes\\Listener\\ProviderDisabled' => __DIR__ . '/..' . '/../lib/Listener/ProviderDisabled.php',
'OCA\\TwoFactorBackupCodes\\Listener\\ProviderEnabled' => __DIR__ . '/..' . '/../lib/Listener/ProviderEnabled.php',
'OCA\\TwoFactorBackupCodes\\Listener\\RegistryUpdater' => __DIR__ . '/..' . '/../lib/Listener/RegistryUpdater.php',
'OCA\\TwoFactorBackupCodes\\Migration\\CheckBackupCodes' => __DIR__ . '/..' . '/../lib/Migration/CheckBackupCodes.php',
diff --git a/apps/twofactor_backupcodes/lib/AppInfo/Application.php b/apps/twofactor_backupcodes/lib/AppInfo/Application.php
index f5d0139dbd9..fc6c94d5b7a 100644
--- a/apps/twofactor_backupcodes/lib/AppInfo/Application.php
+++ b/apps/twofactor_backupcodes/lib/AppInfo/Application.php
@@ -30,6 +30,7 @@ use OCA\TwoFactorBackupCodes\Event\CodesGenerated;
use OCA\TwoFactorBackupCodes\Listener\ActivityPublisher;
use OCA\TwoFactorBackupCodes\Listener\ClearNotifications;
use OCA\TwoFactorBackupCodes\Listener\IListener;
+use OCA\TwoFactorBackupCodes\Listener\ProviderDisabled;
use OCA\TwoFactorBackupCodes\Listener\ProviderEnabled;
use OCA\TwoFactorBackupCodes\Listener\RegistryUpdater;
use OCA\TwoFactorBackupCodes\Notifications\Notifier;
@@ -81,6 +82,12 @@ class Application extends App {
$listener = $container->query(ProviderEnabled::class);
$listener->handle($event);
});
+
+ $eventDispatcher->addListener(IRegistry::EVENT_PROVIDER_DISABLED, function(RegistryEvent $event) use ($container) {
+ /** @var IListener $listener */
+ $listener = $container->query(ProviderDisabled::class);
+ $listener->handle($event);
+ });
}
public function registerNotification() {
diff --git a/apps/twofactor_backupcodes/lib/BackgroundJob/RememberBackupCodesJob.php b/apps/twofactor_backupcodes/lib/BackgroundJob/RememberBackupCodesJob.php
index b04a8c3a29f..1a7f5aca3eb 100644
--- a/apps/twofactor_backupcodes/lib/BackgroundJob/RememberBackupCodesJob.php
+++ b/apps/twofactor_backupcodes/lib/BackgroundJob/RememberBackupCodesJob.php
@@ -70,7 +70,15 @@ class RememberBackupCodesJob extends TimedJob {
}
$providers = $this->registry->getProviderStates($user);
- if (isset($providers['backup_codes']) && $providers['backup_codes'] === true) {
+ $state2fa = array_reduce($providers, function(bool $carry, bool $state) {
+ return $carry || $state;
+ }, false);
+
+ /*
+ * If no provider is active or if the backup codes are already generate
+ * we can remove the job
+ */
+ if ($state2fa === false || (isset($providers['backup_codes']) && $providers['backup_codes'] === true)) {
// Backup codes already generated lets remove this job
$this->jobList->remove(self::class, $argument);
return;
diff --git a/apps/twofactor_backupcodes/lib/Listener/ProviderDisabled.php b/apps/twofactor_backupcodes/lib/Listener/ProviderDisabled.php
new file mode 100644
index 00000000000..835eb0394f9
--- /dev/null
+++ b/apps/twofactor_backupcodes/lib/Listener/ProviderDisabled.php
@@ -0,0 +1,65 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OCA\TwoFactorBackupCodes\Listener;
+
+use OCA\TwoFactorBackupCodes\BackgroundJob\RememberBackupCodesJob;
+use OCP\Authentication\TwoFactorAuth\IRegistry;
+use OCP\Authentication\TwoFactorAuth\RegistryEvent;
+use OCP\BackgroundJob\IJobList;
+use Symfony\Component\EventDispatcher\Event;
+
+class ProviderDisabled implements IListener {
+
+ /** @var IRegistry */
+ private $registry;
+
+ /** @var IJobList */
+ private $jobList;
+
+ public function __construct(IRegistry $registry,
+ IJobList $jobList) {
+ $this->registry = $registry;
+ $this->jobList = $jobList;
+ }
+
+ public function handle(Event $event) {
+ if (!($event instanceof RegistryEvent)) {
+ return;
+ }
+
+ $providers = $this->registry->getProviderStates($event->getUser());
+
+ // Loop over all providers. If all are disabled we remove the job
+ $state = array_reduce($providers, function (bool $carry, bool $enabled) {
+ return $carry || $enabled;
+ }, false);
+
+ if ($state === false) {
+ $this->jobList->remove(RememberBackupCodesJob::class, ['uid' => $event->getUser()->getUID()]);
+ }
+ }
+
+}
diff --git a/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php b/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php
index 0e23e032bd8..fe68da8ebf5 100644
--- a/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php
@@ -114,6 +114,34 @@ class RememberBackupCodesJobTest extends TestCase {
$this->invokePrivate($this->job, 'run', [['uid' => 'validUID']]);
}
+ public function testNoActiveProvider() {
+ $user = $this->createMock(IUser::class);
+ $user->method('getUID')
+ ->willReturn('validUID');
+ $this->userManager->method('get')
+ ->with('validUID')
+ ->willReturn($user);
+
+ $this->registry->method('getProviderStates')
+ ->with($user)
+ ->willReturn([
+ 'backup_codes' => false,
+ 'foo' => false,
+ ]);
+
+ $this->jobList->expects($this->once())
+ ->method('remove')
+ ->with(
+ RememberBackupCodesJob::class,
+ ['uid' => 'validUID']
+ );
+
+ $this->notificationManager->expects($this->never())
+ ->method($this->anything());
+
+ $this->invokePrivate($this->job, 'run', [['uid' => 'validUID']]);
+ }
+
public function testNotificationSend() {
$user = $this->createMock(IUser::class);
$user->method('getUID')
@@ -125,7 +153,8 @@ class RememberBackupCodesJobTest extends TestCase {
$this->registry->method('getProviderStates')
->with($user)
->willReturn([
- 'backup_codes' => false
+ 'backup_codes' => false,
+ 'foo' => true,
]);
$this->jobList->expects($this->never())
diff --git a/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderDisabledTest.php b/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderDisabledTest.php
new file mode 100644
index 00000000000..1bd5a7ccab0
--- /dev/null
+++ b/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderDisabledTest.php
@@ -0,0 +1,110 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+namespace OCA\TwoFactorBackupCodes\Tests\Unit\Listener;
+
+use OCA\TwoFactorBackupCodes\BackgroundJob\RememberBackupCodesJob;
+use OCA\TwoFactorBackupCodes\Listener\ProviderDisabled;
+use OCP\Authentication\TwoFactorAuth\IRegistry;
+use OCP\Authentication\TwoFactorAuth\RegistryEvent;
+use OCP\BackgroundJob\IJobList;
+use OCP\IUser;
+use Symfony\Component\EventDispatcher\Event;
+use Test\TestCase;
+
+class ProviderDisabledTest extends TestCase {
+
+ /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */
+ private $registy;
+
+ /** @var IJobList|\PHPUnit\Framework\MockObject\MockObject */
+ private $jobList;
+
+ /** @var ProviderDisabled */
+ private $listener;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->registy = $this->createMock(IRegistry::class);
+ $this->jobList = $this->createMock(IJobList::class);
+
+ $this->listener = new ProviderDisabled($this->registy, $this->jobList);
+ }
+
+ public function testHandleGenericEvent() {
+ $event = $this->createMock(Event::class);
+ $this->jobList->expects($this->never())
+ ->method($this->anything());
+
+ $this->listener->handle($event);
+ }
+
+ public function testHandleStillActiveProvider() {
+ $user = $this->createMock(IUser::class);
+ $user->method('getUID')
+ ->willReturn('myUID');
+ $event = $this->createMock(RegistryEvent::class);
+ $event->method('getUser')
+ ->willReturn($user);
+
+ $this->registy->method('getProviderStates')
+ ->with($user)
+ ->willReturn([
+ 'backup_codes' => false,
+ 'foo' => true,
+ ]);
+
+ $this->jobList->expects($this->never())
+ ->method($this->anything());
+
+ $this->listener->handle($event);
+ }
+
+ public function testHandleNoActiveProvider() {
+ $user = $this->createMock(IUser::class);
+ $user->method('getUID')
+ ->willReturn('myUID');
+ $event = $this->createMock(RegistryEvent::class);
+ $event->method('getUser')
+ ->willReturn($user);
+
+ $this->registy->method('getProviderStates')
+ ->with($user)
+ ->willReturn([
+ 'backup_codes' => false,
+ 'foo' => false,
+ ]);
+
+ $this->jobList->expects($this->once())
+ ->method('remove')
+ ->with(
+ $this->equalTo(RememberBackupCodesJob::class),
+ $this->equalTo(['uid' => 'myUID'])
+ );
+
+ $this->listener->handle($event);
+ }
+}