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

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2019-09-17 17:33:27 +0300
committernpmbuildbot[bot] <npmbuildbot[bot]@users.noreply.github.com>2019-09-28 12:39:28 +0300
commitde6940352a2f708376219a89ec84a8e6d25ca59e (patch)
tree459bacfc183b24d611be1877fbe22bbcd4efb1d6 /apps/settings/tests
parentc8cd607681ac128228f57114ce14dd67ab05de04 (diff)
Move settings to an app
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at> Signed-off-by: npmbuildbot[bot] <npmbuildbot[bot]@users.noreply.github.com>
Diffstat (limited to 'apps/settings/tests')
-rw-r--r--apps/settings/tests/Activity/SecurityFilterTest.php87
-rw-r--r--apps/settings/tests/Activity/SecurityProviderTest.php136
-rw-r--r--apps/settings/tests/Activity/SecuritySettingTest.php73
-rw-r--r--apps/settings/tests/AppInfo/ApplicationTest.php118
-rw-r--r--apps/settings/tests/Controller/AdminSettingsControllerTest.php128
-rw-r--r--apps/settings/tests/Controller/AppSettingsControllerTest.php247
-rw-r--r--apps/settings/tests/Controller/AuthSettingsControllerTest.php400
-rw-r--r--apps/settings/tests/Controller/CertificateControllerTest.php190
-rw-r--r--apps/settings/tests/Controller/CheckSetupControllerTest.php1449
-rw-r--r--apps/settings/tests/Controller/MailSettingsControllerTest.php178
-rw-r--r--apps/settings/tests/Controller/TwoFactorSettingsControllerTest.php84
-rw-r--r--apps/settings/tests/Controller/UsersControllerTest.php552
-rw-r--r--apps/settings/tests/Mailer/NewUserMailHelperTest.php881
-rw-r--r--apps/settings/tests/Middleware/SubadminMiddlewareTest.php104
-rw-r--r--apps/settings/tests/Personal/Security/AuthtokensTest.php124
-rw-r--r--apps/settings/tests/Settings/Admin/MailTest.php133
-rw-r--r--apps/settings/tests/Settings/Admin/SecurityTest.php149
-rw-r--r--apps/settings/tests/Settings/Admin/ServerTest.php85
-rw-r--r--apps/settings/tests/Settings/Admin/SharingTest.php271
-rw-r--r--apps/settings/tests/Settings/Personal/SecurityTest.php119
20 files changed, 5508 insertions, 0 deletions
diff --git a/apps/settings/tests/Activity/SecurityFilterTest.php b/apps/settings/tests/Activity/SecurityFilterTest.php
new file mode 100644
index 00000000000..f5d25608d66
--- /dev/null
+++ b/apps/settings/tests/Activity/SecurityFilterTest.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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\Settings\Tests;
+
+use OCA\Settings\Activity\SecurityFilter;
+use OCP\IL10N;
+use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class SecurityFilterTest extends TestCase {
+
+ /** @var IURLGenerator|MockObject */
+ private $urlGenerator;
+
+ /** @var IL10N|MockObject */
+ private $l10n;
+
+ /** @var SecurityFilter */
+ private $filter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
+ $this->l10n = $this->createMock(IL10N::class);
+
+ $this->filter = new SecurityFilter($this->urlGenerator, $this->l10n);
+ }
+
+ public function testAllowedApps() {
+ $this->assertEquals([], $this->filter->allowedApps());
+ }
+
+ public function testFilterTypes() {
+ $this->assertEquals(['security'], $this->filter->filterTypes(['comments', 'security']));
+ }
+
+ public function testGetIcon() {
+ $this->urlGenerator->expects($this->once())
+ ->method('imagePath')
+ ->with('core', 'actions/password.svg')
+ ->will($this->returnValue('path/to/icon.svg'));
+ $this->urlGenerator->expects($this->once())
+ ->method('getAbsoluteURL')
+ ->with('path/to/icon.svg')
+ ->will($this->returnValue('abs/path/to/icon.svg'));
+ $this->assertEquals('abs/path/to/icon.svg', $this->filter->getIcon());
+ }
+
+ public function testGetIdentifier() {
+ $this->assertEquals('security', $this->filter->getIdentifier());
+ }
+
+ public function testGetName() {
+ $this->l10n->expects($this->once())
+ ->method('t')
+ ->with('Security')
+ ->will($this->returnValue('translated'));
+ $this->assertEquals('translated', $this->filter->getName());
+ }
+
+ public function testGetPriority() {
+ $this->assertEquals(30, $this->filter->getPriority());
+ }
+
+}
diff --git a/apps/settings/tests/Activity/SecurityProviderTest.php b/apps/settings/tests/Activity/SecurityProviderTest.php
new file mode 100644
index 00000000000..143312addc2
--- /dev/null
+++ b/apps/settings/tests/Activity/SecurityProviderTest.php
@@ -0,0 +1,136 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ * @copyright Copyright (c) 2016 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * Two-factor backup codes
+ *
+ * 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 OCA\Settings\Tests;
+
+use InvalidArgumentException;
+use OCA\Settings\Activity\SecurityProvider;
+use OCP\Activity\IEvent;
+use OCP\Activity\IManager;
+use OCP\IL10N;
+use OCP\IURLGenerator;
+use OCP\L10N\IFactory;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class SecurityProviderTest extends TestCase {
+
+ /** @var IFactory|MockObject */
+ private $l10n;
+
+ /** @var IURLGenerator|MockObject */
+ private $urlGenerator;
+
+ /** @var IManager|MockObject */
+ private $activityManager;
+
+ /** @var SecurityProvider */
+ private $provider;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->l10n = $this->createMock(IFactory::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
+ $this->activityManager = $this->createMock(IManager::class);
+
+ $this->provider = new SecurityProvider($this->l10n, $this->urlGenerator, $this->activityManager);
+ }
+
+ public function testParseUnrelated() {
+ $lang = 'ru';
+ $event = $this->createMock(IEvent::class);
+ $event->expects($this->once())
+ ->method('getType')
+ ->willReturn('comments');
+ $this->expectException(InvalidArgumentException::class);
+
+ $this->provider->parse($lang, $event);
+ }
+
+ public function subjectData() {
+ return [
+ ['twofactor_success'],
+ ['twofactor_failed'],
+ ];
+ }
+
+ /**
+ * @dataProvider subjectData
+ */
+ public function testParse($subject) {
+ $lang = 'ru';
+ $event = $this->createMock(IEvent::class);
+ $l = $this->createMock(IL10N::class);
+
+ $event->expects($this->once())
+ ->method('getType')
+ ->willReturn('security');
+ $this->l10n->expects($this->once())
+ ->method('get')
+ ->with('settings', $lang)
+ ->willReturn($l);
+ $this->urlGenerator->expects($this->once())
+ ->method('imagePath')
+ ->with('core', 'actions/password.svg')
+ ->willReturn('path/to/image');
+ $this->urlGenerator->expects($this->once())
+ ->method('getAbsoluteURL')
+ ->with('path/to/image')
+ ->willReturn('absolute/path/to/image');
+ $event->expects($this->once())
+ ->method('setIcon')
+ ->with('absolute/path/to/image');
+ $event->expects($this->once())
+ ->method('getSubject')
+ ->willReturn($subject);
+ $event->method('getSubjectParameters')
+ ->willReturn([
+ 'provider' => 'myProvider',
+ ]);
+ $event->expects($this->once())
+ ->method('setParsedSubject');
+
+ $this->provider->parse($lang, $event);
+ }
+
+ public function testParseInvalidSubject() {
+ $lang = 'ru';
+ $l = $this->createMock(IL10N::class);
+ $event = $this->createMock(IEvent::class);
+
+ $event->expects($this->once())
+ ->method('getType')
+ ->willReturn('security');
+ $this->l10n->expects($this->once())
+ ->method('get')
+ ->with('settings', $lang)
+ ->willReturn($l);
+ $event->expects($this->once())
+ ->method('getSubject')
+ ->willReturn('unrelated');
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->provider->parse($lang, $event);
+ }
+
+}
diff --git a/apps/settings/tests/Activity/SecuritySettingTest.php b/apps/settings/tests/Activity/SecuritySettingTest.php
new file mode 100644
index 00000000000..39ca3e2b792
--- /dev/null
+++ b/apps/settings/tests/Activity/SecuritySettingTest.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ * @copyright Copyright (c) 2016 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * Two-factor backup codes
+ *
+ * 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 OCA\Settings\Tests;
+
+use OCA\Settings\Activity\SecuritySetting;
+use OCP\IL10N;
+use Test\TestCase;
+
+class SecuritySettingTest extends TestCase {
+
+ private $l10n;
+
+ /** @var SecuritySetting */
+ private $setting;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->l10n = $this->createMock(IL10N::class);
+
+ $this->setting = new SecuritySetting($this->l10n);
+ }
+
+ public function testCanChangeMail() {
+ $this->assertFalse($this->setting->canChangeMail());
+ }
+
+ public function testCanChangeStream() {
+ $this->assertFalse($this->setting->canChangeStream());
+ }
+
+ public function testGetIdentifier() {
+ $this->assertEquals('security', $this->setting->getIdentifier());
+ }
+
+ public function testGetName() {
+ $this->l10n->expects($this->once())
+ ->method('t')
+ ->with('Security')
+ ->will($this->returnValue('Sicherheit'));
+ $this->assertEquals('Sicherheit', $this->setting->getName());
+ }
+
+ public function testGetPriority() {
+ $this->assertEquals(30, $this->setting->getPriority());
+ }
+
+ public function testIsDefaultEnabled() {
+ $this->assertTrue($this->setting->isDefaultEnabledMail());
+ $this->assertTrue($this->setting->isDefaultEnabledStream());
+ }
+
+}
diff --git a/apps/settings/tests/AppInfo/ApplicationTest.php b/apps/settings/tests/AppInfo/ApplicationTest.php
new file mode 100644
index 00000000000..49ba48f10d2
--- /dev/null
+++ b/apps/settings/tests/AppInfo/ApplicationTest.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016, Joas Schilling <coding@schilljs.com>
+ *
+ * @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\Settings\Tests\AppInfo;
+
+
+use OCA\Settings\AppInfo\Application;
+use OCA\Settings\Controller\AdminSettingsController;
+use OCA\Settings\Controller\AppSettingsController;
+use OCA\Settings\Controller\AuthSettingsController;
+use OCA\Settings\Controller\CertificateController;
+use OCA\Settings\Controller\CheckSetupController;
+use OCA\Settings\Controller\LogSettingsController;
+use OCA\Settings\Controller\MailSettingsController;
+use OCA\Settings\Controller\UsersController;
+use OCA\Settings\Middleware\SubadminMiddleware;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\IAppContainer;
+use OCP\AppFramework\Middleware;
+use OCP\IUser;
+use OCP\IUserSession;
+use Test\TestCase;
+
+/**
+ * Class ApplicationTest
+ *
+ * @package Tests\Settings
+ * @group DB
+ */
+class ApplicationTest extends TestCase {
+ /** @var Application */
+ protected $app;
+
+ /** @var IAppContainer */
+ protected $container;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->app = new Application();
+ $this->container = $this->app->getContainer();
+ }
+
+ public function testContainerAppName() {
+ $this->app = new Application();
+ $this->assertEquals('settings', $this->container->getAppName());
+ }
+
+ public function dataContainerQuery() {
+ return [
+ [AdminSettingsController::class, Controller::class],
+ [AppSettingsController::class, Controller::class],
+ [AuthSettingsController::class, Controller::class],
+ // Needs session: [CertificateController::class, Controller::class],
+ [CheckSetupController::class, Controller::class],
+ [LogSettingsController::class, Controller::class],
+ [MailSettingsController::class, Controller::class],
+ [UsersController::class, Controller::class],
+
+ [SubadminMiddleware::class, Middleware::class],
+ ];
+ }
+
+ /**
+ * @dataProvider dataContainerQuery
+ * @param string $service
+ * @param string $expected
+ */
+ public function testContainerQuery($service, $expected) {
+ $this->assertTrue($this->container->query($service) instanceof $expected);
+ }
+
+ public function dataContainerQueryRequiresSession() {
+ return [
+ [CertificateController::class, Controller::class],
+ ];
+ }
+
+ /**
+ * @dataProvider dataContainerQueryRequiresSession
+ * @param string $service
+ * @param string $expected
+ */
+ public function testContainerQueryRequiresSession($service, $expected) {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())
+ ->method('getUID')
+ ->willReturn('test');
+
+ $session = $this->createMock(IUserSession::class);
+ $session->expects($this->once())
+ ->method('getUser')
+ ->willReturn($user);
+
+ $this->overwriteService('UserSession', $session);
+ $this->assertTrue($this->container->query($service) instanceof $expected);
+ $this->restoreService('UserSession');
+ }
+}
diff --git a/apps/settings/tests/Controller/AdminSettingsControllerTest.php b/apps/settings/tests/Controller/AdminSettingsControllerTest.php
new file mode 100644
index 00000000000..f1f81c7c75b
--- /dev/null
+++ b/apps/settings/tests/Controller/AdminSettingsControllerTest.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @author Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\Settings\Tests\Controller;
+
+use OCA\Settings\Personal\ServerDevNotice;
+use OCA\Settings\Controller\AdminSettingsController;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\Group\ISubAdmin;
+use OCP\IGroupManager;
+use OCP\INavigationManager;
+use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserSession;
+use OCP\Settings\IManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+/**
+ * Class AdminSettingsControllerTest
+ *
+ * @group DB
+ *
+ * @package Tests\Settings\Controller
+ */
+class AdminSettingsControllerTest extends TestCase {
+
+ /** @var AdminSettingsController */
+ private $adminSettingsController;
+ /** @var IRequest|MockObject */
+ private $request;
+ /** @var INavigationManager|MockObject */
+ private $navigationManager;
+ /** @var IManager|MockObject */
+ private $settingsManager;
+ /** @var IUserSession|MockObject */
+ private $userSession;
+ /** @var IGroupManager|MockObject */
+ private $groupManager;
+ /** @var ISubAdmin|MockObject */
+ private $subAdmin;
+ /** @var string */
+ private $adminUid = 'lololo';
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->request = $this->createMock(IRequest::class);
+ $this->navigationManager = $this->createMock(INavigationManager::class);
+ $this->settingsManager = $this->createMock(IManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->groupManager = $this->createMock(IGroupManager::class);
+ $this->subAdmin = $this->createMock(ISubAdmin::class);
+
+ $this->adminSettingsController = new AdminSettingsController(
+ 'settings',
+ $this->request,
+ $this->navigationManager,
+ $this->settingsManager,
+ $this->userSession,
+ $this->groupManager,
+ $this->subAdmin
+ );
+
+ $user = \OC::$server->getUserManager()->createUser($this->adminUid, 'olo');
+ \OC_User::setUserId($user->getUID());
+ \OC::$server->getGroupManager()->createGroup('admin')->addUser($user);
+ }
+
+ public function tearDown() {
+ \OC::$server->getUserManager()->get($this->adminUid)->delete();
+
+ parent::tearDown();
+ }
+
+ public function testIndex() {
+ $user = $this->createMock(IUser::class);
+ $this->userSession
+ ->method('getUser')
+ ->willReturn($user);
+ $user->method('getUID')->willReturn('user123');
+ $this->groupManager
+ ->method('isAdmin')
+ ->with('user123')
+ ->willReturn(true);
+ $this->subAdmin
+ ->method('isSubAdmin')
+ ->with($user)
+ ->willReturn(false);
+ $this->settingsManager
+ ->expects($this->once())
+ ->method('getAdminSections')
+ ->willReturn([]);
+ $this->settingsManager
+ ->expects($this->once())
+ ->method('getPersonalSections')
+ ->willReturn([]);
+ $this->settingsManager
+ ->expects($this->once())
+ ->method('getAdminSettings')
+ ->with('test')
+ ->willReturn([5 => new ServerDevNotice()]);
+
+ $idx = $this->adminSettingsController->index('test');
+
+ $expected = new TemplateResponse('settings', 'settings/frame', ['forms' => ['personal' => [], 'admin' => []], 'content' => '']);
+ $this->assertEquals($expected, $idx);
+ }
+}
diff --git a/apps/settings/tests/Controller/AppSettingsControllerTest.php b/apps/settings/tests/Controller/AppSettingsControllerTest.php
new file mode 100644
index 00000000000..449f158ec4a
--- /dev/null
+++ b/apps/settings/tests/Controller/AppSettingsControllerTest.php
@@ -0,0 +1,247 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
+ * @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 OCA\Settings\Tests\Controller;
+
+use OC\App\AppStore\Bundles\BundleFetcher;
+use OC\App\AppStore\Fetcher\AppFetcher;
+use OC\App\AppStore\Fetcher\CategoryFetcher;
+use OC\Installer;
+use OCA\Settings\Controller\AppSettingsController;
+use OCP\AppFramework\Http\ContentSecurityPolicy;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\ILogger;
+use OCP\IURLGenerator;
+use OCP\L10N\IFactory;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+use OCP\IRequest;
+use OCP\IL10N;
+use OCP\IConfig;
+use OCP\INavigationManager;
+use OCP\App\IAppManager;
+
+/**
+ * Class AppSettingsControllerTest
+ *
+ * @package Tests\Settings\Controller
+ *
+ * @group DB
+ */
+class AppSettingsControllerTest extends TestCase {
+ /** @var AppSettingsController */
+ private $appSettingsController;
+ /** @var IRequest|MockObject */
+ private $request;
+ /** @var IL10N|MockObject */
+ private $l10n;
+ /** @var IConfig|MockObject */
+ private $config;
+ /** @var INavigationManager|MockObject */
+ private $navigationManager;
+ /** @var IAppManager|MockObject */
+ private $appManager;
+ /** @var CategoryFetcher|MockObject */
+ private $categoryFetcher;
+ /** @var AppFetcher|MockObject */
+ private $appFetcher;
+ /** @var IFactory|MockObject */
+ private $l10nFactory;
+ /** @var BundleFetcher|MockObject */
+ private $bundleFetcher;
+ /** @var Installer|MockObject */
+ private $installer;
+ /** @var IURLGenerator|MockObject */
+ private $urlGenerator;
+ /** @var ILogger|MockObject */
+ private $logger;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->request = $this->createMock(IRequest::class);
+ $this->l10n = $this->createMock(IL10N::class);
+ $this->l10n->expects($this->any())
+ ->method('t')
+ ->will($this->returnArgument(0));
+ $this->config = $this->createMock(IConfig::class);
+ $this->navigationManager = $this->createMock(INavigationManager::class);
+ $this->appManager = $this->createMock(IAppManager::class);
+ $this->categoryFetcher = $this->createMock(CategoryFetcher::class);
+ $this->appFetcher = $this->createMock(AppFetcher::class);
+ $this->l10nFactory = $this->createMock(IFactory::class);
+ $this->bundleFetcher = $this->createMock(BundleFetcher::class);
+ $this->installer = $this->createMock(Installer::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
+ $this->logger = $this->createMock(ILogger::class);
+
+ $this->appSettingsController = new AppSettingsController(
+ 'settings',
+ $this->request,
+ $this->l10n,
+ $this->config,
+ $this->navigationManager,
+ $this->appManager,
+ $this->categoryFetcher,
+ $this->appFetcher,
+ $this->l10nFactory,
+ $this->bundleFetcher,
+ $this->installer,
+ $this->urlGenerator,
+ $this->logger
+ );
+ }
+
+ public function testListCategories() {
+ $this->installer->expects($this->any())
+ ->method('isUpdateAvailable')
+ ->willReturn(false);
+ $expected = new JSONResponse([
+ [
+ 'id' => 'auth',
+ 'ident' => 'auth',
+ 'displayName' => 'Authentication & authorization',
+ ],
+ [
+ 'id' => 'customization',
+ 'ident' => 'customization',
+ 'displayName' => 'Customization',
+ ],
+ [
+ 'id' => 'files',
+ 'ident' => 'files',
+ 'displayName' => 'Files',
+ ],
+ [
+ 'id' => 'integration',
+ 'ident' => 'integration',
+ 'displayName' => 'Integration',
+ ],
+ [
+ 'id' => 'monitoring',
+ 'ident' => 'monitoring',
+ 'displayName' => 'Monitoring',
+ ],
+ [
+ 'id' => 'multimedia',
+ 'ident' => 'multimedia',
+ 'displayName' => 'Multimedia',
+ ],
+ [
+ 'id' => 'office',
+ 'ident' => 'office',
+ 'displayName' => 'Office & text',
+ ],
+ [
+ 'id' => 'organization',
+ 'ident' => 'organization',
+ 'displayName' => 'Organization',
+ ],
+ [
+ 'id' => 'social',
+ 'ident' => 'social',
+ 'displayName' => 'Social & communication',
+ ],
+ [
+ 'id' => 'tools',
+ 'ident' => 'tools',
+ 'displayName' => 'Tools',
+ ],
+ ]);
+
+ $this->categoryFetcher
+ ->expects($this->once())
+ ->method('get')
+ ->willReturn(json_decode('[{"id":"auth","translations":{"cs":{"name":"Autentizace & autorizace","description":"Aplikace poskytující služby dodatečného ověření nebo přihlášení"},"hu":{"name":"Azonosítás és hitelesítés","description":"Apps that provide additional authentication or authorization services"},"de":{"name":"Authentifizierung & Authorisierung","description":"Apps die zusätzliche Autentifizierungs- oder Autorisierungsdienste bereitstellen"},"nl":{"name":"Authenticatie & authorisatie","description":"Apps die aanvullende authenticatie- en autorisatiediensten bieden"},"nb":{"name":"Pålogging og tilgangsstyring","description":"Apper for å tilby ekstra pålogging eller tilgangsstyring"},"it":{"name":"Autenticazione e autorizzazione","description":"Apps that provide additional authentication or authorization services"},"fr":{"name":"Authentification et autorisations","description":"Applications qui fournissent des services d\'authentification ou d\'autorisations additionnels."},"ru":{"name":"Аутентификация и авторизация","description":"Apps that provide additional authentication or authorization services"},"en":{"name":"Authentication & authorization","description":"Apps that provide additional authentication or authorization services"}}},{"id":"customization","translations":{"cs":{"name":"Přizpůsobení","description":"Motivy a aplikace měnící rozvržení a uživatelské rozhraní"},"it":{"name":"Personalizzazione","description":"Applicazioni di temi, modifiche della disposizione e UX"},"de":{"name":"Anpassung","description":"Apps zur Änderung von Themen, Layout und Benutzererfahrung"},"hu":{"name":"Személyre szabás","description":"Témák, elrendezések felhasználói felület módosító alkalmazások"},"nl":{"name":"Maatwerk","description":"Thema\'s, layout en UX aanpassingsapps"},"nb":{"name":"Tilpasning","description":"Apper for å endre Tema, utseende og brukeropplevelse"},"fr":{"name":"Personalisation","description":"Thèmes, apparence et applications modifiant l\'expérience utilisateur"},"ru":{"name":"Настройка","description":"Themes, layout and UX change apps"},"en":{"name":"Customization","description":"Themes, layout and UX change apps"}}},{"id":"files","translations":{"cs":{"name":"Soubory","description":"Aplikace rozšiřující správu souborů nebo aplikaci Soubory"},"it":{"name":"File","description":"Applicazioni di gestione dei file ed estensione dell\'applicazione FIle"},"de":{"name":"Dateien","description":"Dateimanagement sowie Erweiterungs-Apps für die Dateien-App"},"hu":{"name":"Fájlok","description":"Fájl kezelő és kiegészítő alkalmazások"},"nl":{"name":"Bestanden","description":"Bestandebeheer en uitbreidingen van bestand apps"},"nb":{"name":"Filer","description":"Apper for filhåndtering og filer"},"fr":{"name":"Fichiers","description":"Applications de gestion de fichiers et extensions à l\'application Fichiers"},"ru":{"name":"Файлы","description":"Расширение: файлы и управление файлами"},"en":{"name":"Files","description":"File management and Files app extension apps"}}},{"id":"integration","translations":{"it":{"name":"Integrazione","description":"Applicazioni che collegano Nextcloud con altri servizi e piattaforme"},"hu":{"name":"Integráció","description":"Apps that connect Nextcloud with other services and platforms"},"nl":{"name":"Integratie","description":"Apps die Nextcloud verbinden met andere services en platformen"},"nb":{"name":"Integrasjon","description":"Apper som kobler Nextcloud med andre tjenester og plattformer"},"de":{"name":"Integration","description":"Apps die Nextcloud mit anderen Diensten und Plattformen verbinden"},"cs":{"name":"Propojení","description":"Aplikace propojující NextCloud s dalšími službami a platformami"},"fr":{"name":"Intégration","description":"Applications qui connectent Nextcloud avec d\'autres services et plateformes"},"ru":{"name":"Интеграция","description":"Приложения, соединяющие Nextcloud с другими службами и платформами"},"en":{"name":"Integration","description":"Apps that connect Nextcloud with other services and platforms"}}},{"id":"monitoring","translations":{"nb":{"name":"Overvåking","description":"Apper for statistikk, systemdiagnose og aktivitet"},"it":{"name":"Monitoraggio","description":"Applicazioni di statistiche, diagnostica di sistema e attività"},"de":{"name":"Überwachung","description":"Datenstatistiken-, Systemdiagnose- und Aktivitäten-Apps"},"hu":{"name":"Megfigyelés","description":"Data statistics, system diagnostics and activity apps"},"nl":{"name":"Monitoren","description":"Gegevensstatistiek, systeem diagnose en activiteit apps"},"cs":{"name":"Kontrola","description":"Datové statistiky, diagnózy systému a aktivity aplikací"},"fr":{"name":"Surveillance","description":"Applications de statistiques sur les données, de diagnostics systèmes et d\'activité."},"ru":{"name":"Мониторинг","description":"Статистика данных, диагностика системы и активность приложений"},"en":{"name":"Monitoring","description":"Data statistics, system diagnostics and activity apps"}}},{"id":"multimedia","translations":{"nb":{"name":"Multimedia","description":"Apper for lyd, film og bilde"},"it":{"name":"Multimedia","description":"Applicazioni per audio, video e immagini"},"de":{"name":"Multimedia","description":"Audio-, Video- und Bilder-Apps"},"hu":{"name":"Multimédia","description":"Hang, videó és kép alkalmazások"},"nl":{"name":"Multimedia","description":"Audio, video en afbeelding apps"},"en":{"name":"Multimedia","description":"Audio, video and picture apps"},"cs":{"name":"Multimédia","description":"Aplikace audia, videa a obrázků"},"fr":{"name":"Multimédia","description":"Applications audio, vidéo et image"},"ru":{"name":"Мультимедиа","description":"Приложение аудио, видео и изображения"}}},{"id":"office","translations":{"nb":{"name":"Kontorstøtte og tekst","description":"Apper for Kontorstøtte og tekstbehandling"},"it":{"name":"Ufficio e testo","description":"Applicazione per ufficio ed elaborazione di testi"},"de":{"name":"Büro & Text","description":"Büro- und Textverarbeitungs-Apps"},"hu":{"name":"Iroda és szöveg","description":"Irodai és szöveg feldolgozó alkalmazások"},"nl":{"name":"Office & tekst","description":"Office en tekstverwerkingsapps"},"cs":{"name":"Kancelář a text","description":"Aplikace pro kancelář a zpracování textu"},"fr":{"name":"Bureautique & texte","description":"Applications de bureautique et de traitement de texte"},"en":{"name":"Office & text","description":"Office and text processing apps"}}},{"id":"organization","translations":{"nb":{"name":"Organisering","description":"Apper for tidsstyring, oppgaveliste og kalender"},"it":{"name":"Organizzazione","description":"Applicazioni di gestione del tempo, elenco delle cose da fare e calendario"},"hu":{"name":"Szervezet","description":"Időbeosztás, teendő lista és naptár alkalmazások"},"nl":{"name":"Organisatie","description":"Tijdmanagement, takenlijsten en agenda apps"},"cs":{"name":"Organizace","description":"Aplikace pro správu času, plánování a kalendáře"},"de":{"name":"Organisation","description":"Time management, Todo list and calendar apps"},"fr":{"name":"Organisation","description":"Applications de gestion du temps, de listes de tâches et d\'agendas"},"ru":{"name":"Организация","description":"Приложения по управлению временем, список задач и календарь"},"en":{"name":"Organization","description":"Time management, Todo list and calendar apps"}}},{"id":"social","translations":{"nb":{"name":"Sosialt og kommunikasjon","description":"Apper for meldinger, kontakthåndtering og sosiale medier"},"it":{"name":"Sociale e comunicazione","description":"Applicazioni di messaggistica, gestione dei contatti e reti sociali"},"de":{"name":"Kommunikation","description":"Nachrichten-, Kontaktverwaltungs- und Social-Media-Apps"},"hu":{"name":"Közösségi és kommunikáció","description":"Üzenetküldő, kapcsolat kezelő és közösségi média alkalmazások"},"nl":{"name":"Sociaal & communicatie","description":"Messaging, contactbeheer en social media apps"},"cs":{"name":"Sociální sítě a komunikace","description":"Aplikace pro zasílání zpráv, správu kontaktů a sociální sítě"},"fr":{"name":"Social & communication","description":"Applications de messagerie, de gestion de contacts et de réseaux sociaux"},"ru":{"name":"Социальное и связь","description":"Общение, управление контактами и социальное медиа-приложение"},"en":{"name":"Social & communication","description":"Messaging, contact management and social media apps"}}},{"id":"tools","translations":{"nb":{"name":"Verktøy","description":"Alt annet"},"it":{"name":"Strumenti","description":"Tutto il resto"},"hu":{"name":"Eszközök","description":"Minden más"},"nl":{"name":"Tools","description":"De rest"},"de":{"name":"Werkzeuge","description":"Alles Andere"},"en":{"name":"Tools","description":"Everything else"},"cs":{"name":"Nástroje","description":"Vše ostatní"},"fr":{"name":"Outils","description":"Tout le reste"},"ru":{"name":"Приложения","description":"Что-то еще"}}}]', true));
+
+ $this->assertEquals($expected, $this->appSettingsController->listCategories());
+ }
+
+ public function testViewApps() {
+ $this->bundleFetcher->expects($this->once())->method('getBundles')->willReturn([]);
+ $this->installer->expects($this->any())
+ ->method('isUpdateAvailable')
+ ->willReturn(false);
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('appstoreenabled', true)
+ ->will($this->returnValue(true));
+ $this->navigationManager
+ ->expects($this->once())
+ ->method('setActiveEntry')
+ ->with('core_apps');
+
+ $policy = new ContentSecurityPolicy();
+ $policy->addAllowedImageDomain('https://usercontent.apps.nextcloud.com');
+
+ $expected = new TemplateResponse('settings',
+ 'settings-vue',
+ [
+ 'serverData' => [
+ 'updateCount' => 0,
+ 'appstoreEnabled' => true,
+ 'bundles' => [],
+ 'developerDocumentation' => ''
+ ]
+ ],
+ 'user');
+ $expected->setContentSecurityPolicy($policy);
+
+ $this->assertEquals($expected, $this->appSettingsController->viewApps());
+ }
+
+ public function testViewAppsAppstoreNotEnabled() {
+ $this->installer->expects($this->any())
+ ->method('isUpdateAvailable')
+ ->willReturn(false);
+ $this->bundleFetcher->expects($this->once())->method('getBundles')->willReturn([]);
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('appstoreenabled', true)
+ ->will($this->returnValue(false));
+ $this->navigationManager
+ ->expects($this->once())
+ ->method('setActiveEntry')
+ ->with('core_apps');
+
+ $policy = new ContentSecurityPolicy();
+ $policy->addAllowedImageDomain('https://usercontent.apps.nextcloud.com');
+
+ $expected = new TemplateResponse('settings',
+ 'settings-vue',
+ [
+ 'serverData' => [
+ 'updateCount' => 0,
+ 'appstoreEnabled' => false,
+ 'bundles' => [],
+ 'developerDocumentation' => ''
+ ]
+ ],
+ 'user');
+ $expected->setContentSecurityPolicy($policy);
+
+ $this->assertEquals($expected, $this->appSettingsController->viewApps());
+ }
+}
diff --git a/apps/settings/tests/Controller/AuthSettingsControllerTest.php b/apps/settings/tests/Controller/AuthSettingsControllerTest.php
new file mode 100644
index 00000000000..88913b1f03f
--- /dev/null
+++ b/apps/settings/tests/Controller/AuthSettingsControllerTest.php
@@ -0,0 +1,400 @@
+<?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 Test\Settings\Controller;
+
+use OC\AppFramework\Http;
+use OC\Authentication\Exceptions\InvalidTokenException;
+use OC\Authentication\Token\DefaultToken;
+use OC\Authentication\Token\IProvider;
+use OC\Authentication\Token\IToken;
+use OC\Authentication\Token\RemoteWipe;
+use OCA\Settings\Controller\AuthSettingsController;
+use OCP\Activity\IEvent;
+use OCP\Activity\IManager;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\ILogger;
+use OCP\IRequest;
+use OCP\ISession;
+use OCP\IUserSession;
+use OCP\Security\ISecureRandom;
+use OCP\Session\Exceptions\SessionNotAvailableException;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class AuthSettingsControllerTest extends TestCase {
+
+ /** @var AuthSettingsController */
+ private $controller;
+ /** @var IRequest|MockObject */
+ private $request;
+ /** @var IProvider|MockObject */
+ private $tokenProvider;
+ /** @var ISession|MockObject */
+ private $session;
+ /**@var IUserSession|MockObject */
+ private $userSession;
+ /** @var ISecureRandom|MockObject */
+ private $secureRandom;
+ /** @var IManager|MockObject */
+ private $activityManager;
+ /** @var RemoteWipe|MockObject */
+ private $remoteWipe;
+ private $uid = 'jane';
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->request = $this->createMock(IRequest::class);
+ $this->tokenProvider = $this->createMock(IProvider::class);
+ $this->session = $this->createMock(ISession::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->secureRandom = $this->createMock(ISecureRandom::class);
+ $this->activityManager = $this->createMock(IManager::class);
+ $this->remoteWipe = $this->createMock(RemoteWipe::class);
+ /** @var ILogger|MockObject $logger */
+ $logger = $this->createMock(ILogger::class);
+
+ $this->controller = new AuthSettingsController(
+ 'core',
+ $this->request,
+ $this->tokenProvider,
+ $this->session,
+ $this->secureRandom,
+ $this->uid,
+ $this->userSession,
+ $this->activityManager,
+ $this->remoteWipe,
+ $logger
+ );
+ }
+
+ public function testCreate() {
+ $name = 'Nexus 4';
+ $sessionToken = $this->createMock(IToken::class);
+ $deviceToken = $this->createMock(IToken::class);
+ $password = '123456';
+
+ $this->session->expects($this->once())
+ ->method('getId')
+ ->willReturn('sessionid');
+ $this->tokenProvider->expects($this->once())
+ ->method('getToken')
+ ->with('sessionid')
+ ->willReturn($sessionToken);
+ $this->tokenProvider->expects($this->once())
+ ->method('getPassword')
+ ->with($sessionToken, 'sessionid')
+ ->willReturn($password);
+ $sessionToken->expects($this->once())
+ ->method('getLoginName')
+ ->willReturn('User13');
+
+ $this->secureRandom->expects($this->exactly(5))
+ ->method('generate')
+ ->with(5, ISecureRandom::CHAR_HUMAN_READABLE)
+ ->willReturn('XXXXX');
+ $newToken = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX';
+
+ $this->tokenProvider->expects($this->once())
+ ->method('generateToken')
+ ->with($newToken, $this->uid, 'User13', $password, $name, IToken::PERMANENT_TOKEN)
+ ->willReturn($deviceToken);
+
+ $deviceToken->expects($this->once())
+ ->method('jsonSerialize')
+ ->willReturn(['dummy' => 'dummy', 'canDelete' => true]);
+
+ $this->mockActivityManager();
+
+ $expected = [
+ 'token' => $newToken,
+ 'deviceToken' => ['dummy' => 'dummy', 'canDelete' => true, 'canRename' => true],
+ 'loginName' => 'User13',
+ ];
+
+ $response = $this->controller->create($name);
+ $this->assertInstanceOf(JSONResponse::class, $response);
+ $this->assertEquals($expected, $response->getData());
+ }
+
+ public function testCreateSessionNotAvailable() {
+ $name = 'personal phone';
+
+ $this->session->expects($this->once())
+ ->method('getId')
+ ->will($this->throwException(new SessionNotAvailableException()));
+
+ $expected = new JSONResponse();
+ $expected->setStatus(Http::STATUS_SERVICE_UNAVAILABLE);
+
+ $this->assertEquals($expected, $this->controller->create($name));
+ }
+
+ public function testCreateInvalidToken() {
+ $name = 'Company IPhone';
+
+ $this->session->expects($this->once())
+ ->method('getId')
+ ->willReturn('sessionid');
+ $this->tokenProvider->expects($this->once())
+ ->method('getToken')
+ ->with('sessionid')
+ ->will($this->throwException(new InvalidTokenException()));
+
+ $expected = new JSONResponse();
+ $expected->setStatus(Http::STATUS_SERVICE_UNAVAILABLE);
+
+ $this->assertEquals($expected, $this->controller->create($name));
+ }
+
+ public function testDestroy() {
+ $tokenId = 124;
+ $token = $this->createMock(DefaultToken::class);
+
+ $this->mockGetTokenById($tokenId, $token);
+ $this->mockActivityManager();
+
+ $token->expects($this->exactly(2))
+ ->method('getId')
+ ->willReturn($tokenId);
+
+ $token->expects($this->once())
+ ->method('getUID')
+ ->willReturn('jane');
+
+ $this->tokenProvider->expects($this->once())
+ ->method('invalidateTokenById')
+ ->with($this->uid, $tokenId);
+
+ $this->assertEquals([], $this->controller->destroy($tokenId));
+ }
+
+ public function testDestroyWrongUser() {
+ $tokenId = 124;
+ $token = $this->createMock(DefaultToken::class);
+
+ $this->mockGetTokenById($tokenId, $token);
+
+ $token->expects($this->once())
+ ->method('getUID')
+ ->willReturn('foobar');
+
+ $response = $this->controller->destroy($tokenId);
+ $this->assertSame([], $response->getData());
+ $this->assertSame(\OCP\AppFramework\Http::STATUS_NOT_FOUND, $response->getStatus());
+ }
+
+ public function dataRenameToken(): array {
+ return [
+ 'App password => Other token name' => ['App password', 'Other token name'],
+ 'Other token name => App password' => ['Other token name', 'App password'],
+ ];
+ }
+
+ /**
+ * @dataProvider dataRenameToken
+ *
+ * @param string $name
+ * @param string $newName
+ */
+ public function testUpdateRename(string $name, string $newName): void {
+ $tokenId = 42;
+ $token = $this->createMock(DefaultToken::class);
+
+ $this->mockGetTokenById($tokenId, $token);
+ $this->mockActivityManager();
+
+ $token->expects($this->once())
+ ->method('getUID')
+ ->willReturn('jane');
+
+ $token->expects($this->once())
+ ->method('getName')
+ ->willReturn($name);
+
+ $token->expects($this->once())
+ ->method('getScopeAsArray')
+ ->willReturn(['filesystem' => true]);
+
+ $token->expects($this->once())
+ ->method('setName')
+ ->with($this->equalTo($newName));
+
+ $this->tokenProvider->expects($this->once())
+ ->method('updateToken')
+ ->with($this->equalTo($token));
+
+ $this->assertSame([], $this->controller->update($tokenId, ['filesystem' => true], $newName));
+ }
+
+ public function dataUpdateFilesystemScope(): array {
+ return [
+ 'Grant filesystem access' => [false, true],
+ 'Revoke filesystem access' => [true, false],
+ ];
+ }
+
+ /**
+ * @dataProvider dataUpdateFilesystemScope
+ *
+ * @param bool $filesystem
+ * @param bool $newFilesystem
+ */
+ public function testUpdateFilesystemScope(bool $filesystem, bool $newFilesystem): void {
+ $tokenId = 42;
+ $token = $this->createMock(DefaultToken::class);
+
+ $this->mockGetTokenById($tokenId, $token);
+ $this->mockActivityManager();
+
+ $token->expects($this->once())
+ ->method('getUID')
+ ->willReturn('jane');
+
+ $token->expects($this->once())
+ ->method('getName')
+ ->willReturn('App password');
+
+ $token->expects($this->once())
+ ->method('getScopeAsArray')
+ ->willReturn(['filesystem' => $filesystem]);
+
+ $token->expects($this->once())
+ ->method('setScope')
+ ->with($this->equalTo(['filesystem' => $newFilesystem]));
+
+ $this->tokenProvider->expects($this->once())
+ ->method('updateToken')
+ ->with($this->equalTo($token));
+
+ $this->assertSame([], $this->controller->update($tokenId, ['filesystem' => $newFilesystem], 'App password'));
+ }
+
+ public function testUpdateNoChange(): void {
+ $tokenId = 42;
+ $token = $this->createMock(DefaultToken::class);
+
+ $this->mockGetTokenById($tokenId, $token);
+
+ $token->expects($this->once())
+ ->method('getUID')
+ ->willReturn('jane');
+
+ $token->expects($this->once())
+ ->method('getName')
+ ->willReturn('App password');
+
+ $token->expects($this->once())
+ ->method('getScopeAsArray')
+ ->willReturn(['filesystem' => true]);
+
+ $token->expects($this->never())
+ ->method('setName');
+
+ $token->expects($this->never())
+ ->method('setScope');
+
+ $this->tokenProvider->expects($this->once())
+ ->method('updateToken')
+ ->with($this->equalTo($token));
+
+ $this->assertSame([], $this->controller->update($tokenId, ['filesystem' => true], 'App password'));
+ }
+
+ public function testUpdateTokenWrongUser() {
+ $tokenId = 42;
+ $token = $this->createMock(DefaultToken::class);
+
+ $this->mockGetTokenById($tokenId, $token);
+
+ $token->expects($this->once())
+ ->method('getUID')
+ ->willReturn('foobar');
+
+ $token->expects($this->never())
+ ->method('setScope');
+ $this->tokenProvider->expects($this->never())
+ ->method('updateToken');
+
+ $response = $this->controller->update($tokenId, ['filesystem' => true], 'App password');
+ $this->assertSame([], $response->getData());
+ $this->assertSame(\OCP\AppFramework\Http::STATUS_NOT_FOUND, $response->getStatus());
+ }
+
+ public function testUpdateTokenNonExisting() {
+ $this->tokenProvider->expects($this->once())
+ ->method('getTokenById')
+ ->with($this->equalTo(42))
+ ->willThrowException(new InvalidTokenException('Token does not exist'));
+
+ $this->tokenProvider->expects($this->never())
+ ->method('updateToken');
+
+ $response = $this->controller->update(42, ['filesystem' => true], 'App password');
+ $this->assertSame([], $response->getData());
+ $this->assertSame(\OCP\AppFramework\Http::STATUS_NOT_FOUND, $response->getStatus());
+ }
+
+ private function mockActivityManager(): void {
+ $this->activityManager->expects($this->once())
+ ->method('generateEvent')
+ ->willReturn($this->createMock(IEvent::class));
+ $this->activityManager->expects($this->once())
+ ->method('publish');
+ }
+
+ /**
+ * @param int $tokenId
+ * @param $token
+ */
+ private function mockGetTokenById(int $tokenId, $token): void {
+ $this->tokenProvider->expects($this->once())
+ ->method('getTokenById')
+ ->with($this->equalTo($tokenId))
+ ->willReturn($token);
+ }
+
+ public function testRemoteWipeNotSuccessful(): void {
+ $this->remoteWipe->expects($this->once())
+ ->method('markTokenForWipe')
+ ->with(123)
+ ->willReturn(false);
+
+ $response = $this->controller->wipe(123);
+
+ $expected = new JSONResponse([], Http::STATUS_BAD_REQUEST);
+ $this->assertEquals($expected, $response);
+ }
+
+ public function testRemoteWipeSuccessful(): void {
+ $this->remoteWipe->expects($this->once())
+ ->method('markTokenForWipe')
+ ->with(123)
+ ->willReturn(true);
+
+ $response = $this->controller->wipe(123);
+
+ $expected = new JSONResponse([]);
+ $this->assertEquals($expected, $response);
+ }
+
+}
diff --git a/apps/settings/tests/Controller/CertificateControllerTest.php b/apps/settings/tests/Controller/CertificateControllerTest.php
new file mode 100644
index 00000000000..a36cc201779
--- /dev/null
+++ b/apps/settings/tests/Controller/CertificateControllerTest.php
@@ -0,0 +1,190 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@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 OCA\Settings\Tests\Controller;
+
+use OCA\Settings\Controller\CertificateController;
+use OCP\App\IAppManager;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\IRequest;
+use OCP\IL10N;
+use OCP\ICertificateManager;
+
+/**
+ * Class CertificateControllerTest
+ *
+ * @package Tests\Settings\Controller
+ */
+class CertificateControllerTest extends \Test\TestCase {
+ /** @var CertificateController */
+ private $certificateController;
+ /** @var IRequest */
+ private $request;
+ /** @var ICertificateManager */
+ private $certificateManager;
+ /** @var IL10N */
+ private $l10n;
+ /** @var IAppManager */
+ private $appManager;
+ /** @var ICertificateManager */
+ private $systemCertificateManager;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->request = $this->getMockBuilder(IRequest::class)->getMock();
+ $this->certificateManager = $this->getMockBuilder(ICertificateManager::class)->getMock();
+ $this->systemCertificateManager = $this->getMockBuilder(ICertificateManager::class)->getMock();
+ $this->l10n = $this->getMockBuilder(IL10N::class)->getMock();
+ $this->appManager = $this->getMockBuilder(IAppManager::class)->getMock();
+
+ $this->certificateController = $this->getMockBuilder(CertificateController::class)
+ ->setConstructorArgs(
+ [
+ 'settings',
+ $this->request,
+ $this->certificateManager,
+ $this->systemCertificateManager,
+ $this->l10n,
+ $this->appManager
+ ]
+ )->setMethods(['isCertificateImportAllowed'])->getMock();
+
+ $this->certificateController->expects($this->any())
+ ->method('isCertificateImportAllowed')->willReturn(true);
+ }
+
+ public function testAddPersonalRootCertificateWithEmptyFile() {
+ $this->request
+ ->expects($this->once())
+ ->method('getUploadedFile')
+ ->with('rootcert_import')
+ ->will($this->returnValue(null));
+
+ $expected = new DataResponse(['message' => 'No file uploaded'], Http::STATUS_UNPROCESSABLE_ENTITY);
+ $this->assertEquals($expected, $this->certificateController->addPersonalRootCertificate());
+ }
+
+ public function testAddPersonalRootCertificateValidCertificate() {
+ $uploadedFile = [
+ 'tmp_name' => __DIR__ . '/../../../../tests/data/certificates/goodCertificate.crt',
+ 'name' => 'goodCertificate.crt',
+ ];
+
+ $certificate = $this->getMockBuilder('\OCP\ICertificate')->getMock();
+ $certificate
+ ->expects($this->once())
+ ->method('getName')
+ ->will($this->returnValue('Name'));
+ $certificate
+ ->expects($this->once())
+ ->method('getCommonName')
+ ->will($this->returnValue('CommonName'));
+ $certificate
+ ->expects($this->once())
+ ->method('getOrganization')
+ ->will($this->returnValue('Organization'));
+ $certificate
+ ->expects($this->exactly(2))
+ ->method('getIssueDate')
+ ->will($this->returnValue(new \DateTime('@1429099555')));
+ $certificate
+ ->expects($this->exactly(2))
+ ->method('getExpireDate')
+ ->will($this->returnValue(new \DateTime('@1529099555')));
+ $certificate
+ ->expects($this->once())
+ ->method('getIssuerName')
+ ->will($this->returnValue('Issuer'));
+ $certificate
+ ->expects($this->once())
+ ->method('getIssuerOrganization')
+ ->will($this->returnValue('IssuerOrganization'));
+
+ $this->request
+ ->expects($this->once())
+ ->method('getUploadedFile')
+ ->with('rootcert_import')
+ ->will($this->returnValue($uploadedFile));
+ $this->certificateManager
+ ->expects($this->once())
+ ->method('addCertificate')
+ ->with(file_get_contents($uploadedFile['tmp_name'], 'goodCertificate.crt'))
+ ->will($this->returnValue($certificate));
+
+ $this->l10n
+ ->expects($this->at(0))
+ ->method('l')
+ ->with('date', new \DateTime('@1429099555'))
+ ->will($this->returnValue('Valid From as String'));
+ $this->l10n
+ ->expects($this->at(1))
+ ->method('l')
+ ->with('date', new \DateTime('@1529099555'))
+ ->will($this->returnValue('Valid Till as String'));
+
+
+ $expected = new DataResponse([
+ 'name' => 'Name',
+ 'commonName' => 'CommonName',
+ 'organization' => 'Organization',
+ 'validFrom' => 1429099555,
+ 'validTill' => 1529099555,
+ 'validFromString' => 'Valid From as String',
+ 'validTillString' => 'Valid Till as String',
+ 'issuer' => 'Issuer',
+ 'issuerOrganization' => 'IssuerOrganization',
+ ]);
+ $this->assertEquals($expected, $this->certificateController->addPersonalRootCertificate());
+ }
+
+ public function testAddPersonalRootCertificateInvalidCertificate() {
+ $uploadedFile = [
+ 'tmp_name' => __DIR__ . '/../../../../tests/data/certificates/badCertificate.crt',
+ 'name' => 'badCertificate.crt',
+ ];
+
+ $this->request
+ ->expects($this->once())
+ ->method('getUploadedFile')
+ ->with('rootcert_import')
+ ->will($this->returnValue($uploadedFile));
+ $this->certificateManager
+ ->expects($this->once())
+ ->method('addCertificate')
+ ->with(file_get_contents($uploadedFile['tmp_name'], 'badCertificate.crt'))
+ ->will($this->throwException(new \Exception()));
+
+ $expected = new DataResponse(['An error occurred.'], Http::STATUS_UNPROCESSABLE_ENTITY);
+ $this->assertEquals($expected, $this->certificateController->addPersonalRootCertificate());
+ }
+
+ public function testRemoveCertificate() {
+ $this->certificateManager
+ ->expects($this->once())
+ ->method('removeCertificate')
+ ->with('CertificateToRemove');
+
+ $this->assertEquals(new DataResponse(), $this->certificateController->removePersonalRootCertificate('CertificateToRemove'));
+ }
+
+}
diff --git a/apps/settings/tests/Controller/CheckSetupControllerTest.php b/apps/settings/tests/Controller/CheckSetupControllerTest.php
new file mode 100644
index 00000000000..23e282b6eb4
--- /dev/null
+++ b/apps/settings/tests/Controller/CheckSetupControllerTest.php
@@ -0,0 +1,1449 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@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 OCA\Settings\Tests\Controller;
+
+use OC;
+use OC\DB\Connection;
+use OC\MemoryInfo;
+use OC\Security\SecureRandom;
+use OCA\Settings\Controller\CheckSetupController;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\DataDisplayResponse;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\Http\RedirectResponse;
+use OCP\Http\Client\IClientService;
+use OCP\IConfig;
+use OCP\IDateTimeFormatter;
+use OCP\IL10N;
+use OCP\ILogger;
+use OCP\IRequest;
+use OCP\IURLGenerator;
+use OCP\Lock\ILockingProvider;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Http\Message\ResponseInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Test\TestCase;
+use OC\IntegrityCheck\Checker;
+
+/**
+ * Class CheckSetupControllerTest
+ *
+ * @backupStaticAttributes
+ * @package Tests\Settings\Controller
+ */
+class CheckSetupControllerTest extends TestCase {
+ /** @var CheckSetupController | \PHPUnit_Framework_MockObject_MockObject */
+ private $checkSetupController;
+ /** @var IRequest | \PHPUnit_Framework_MockObject_MockObject */
+ private $request;
+ /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */
+ private $config;
+ /** @var IClientService | \PHPUnit_Framework_MockObject_MockObject*/
+ private $clientService;
+ /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject */
+ private $urlGenerator;
+ /** @var IL10N | \PHPUnit_Framework_MockObject_MockObject */
+ private $l10n;
+ /** @var ILogger */
+ private $logger;
+ /** @var Checker|\PHPUnit_Framework_MockObject_MockObject */
+ private $checker;
+ /** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */
+ private $dispatcher;
+ /** @var Connection|\PHPUnit_Framework_MockObject_MockObject */
+ private $db;
+ /** @var ILockingProvider|\PHPUnit_Framework_MockObject_MockObject */
+ private $lockingProvider;
+ /** @var IDateTimeFormatter|\PHPUnit_Framework_MockObject_MockObject */
+ private $dateTimeFormatter;
+ /** @var MemoryInfo|MockObject */
+ private $memoryInfo;
+ /** @var SecureRandom|\PHPUnit_Framework_MockObject_MockObject */
+ private $secureRandom;
+
+ /**
+ * Holds a list of directories created during tests.
+ *
+ * @var array
+ */
+ private $dirsToRemove = [];
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->request = $this->getMockBuilder(IRequest::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->config = $this->getMockBuilder(IConfig::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->clientService = $this->getMockBuilder(IClientService::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->l10n = $this->getMockBuilder(IL10N::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->l10n->expects($this->any())
+ ->method('t')
+ ->will($this->returnCallback(function($message, array $replace) {
+ return vsprintf($message, $replace);
+ }));
+ $this->dispatcher = $this->getMockBuilder(EventDispatcherInterface::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
+ ->disableOriginalConstructor()->getMock();
+ $this->logger = $this->getMockBuilder(ILogger::class)->getMock();
+ $this->db = $this->getMockBuilder(Connection::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->lockingProvider = $this->getMockBuilder(ILockingProvider::class)->getMock();
+ $this->dateTimeFormatter = $this->getMockBuilder(IDateTimeFormatter::class)->getMock();
+ $this->memoryInfo = $this->getMockBuilder(MemoryInfo::class)
+ ->setMethods(['isMemoryLimitSufficient',])
+ ->getMock();
+ $this->secureRandom = $this->getMockBuilder(SecureRandom::class)->getMock();
+ $this->checkSetupController = $this->getMockBuilder(CheckSetupController::class)
+ ->setConstructorArgs([
+ 'settings',
+ $this->request,
+ $this->config,
+ $this->clientService,
+ $this->urlGenerator,
+ $this->l10n,
+ $this->checker,
+ $this->logger,
+ $this->dispatcher,
+ $this->db,
+ $this->lockingProvider,
+ $this->dateTimeFormatter,
+ $this->memoryInfo,
+ $this->secureRandom,
+ ])
+ ->setMethods([
+ 'isReadOnlyConfig',
+ 'hasValidTransactionIsolationLevel',
+ 'hasFileinfoInstalled',
+ 'hasWorkingFileLocking',
+ 'getLastCronInfo',
+ 'getSuggestedOverwriteCliURL',
+ 'getCurlVersion',
+ 'isPhpOutdated',
+ 'isOpcacheProperlySetup',
+ 'hasFreeTypeSupport',
+ 'hasMissingIndexes',
+ 'isSqliteUsed',
+ 'isPHPMailerUsed',
+ 'hasOpcacheLoaded',
+ 'getAppDirsWithDifferentOwner',
+ 'hasRecommendedPHPModules',
+ 'hasBigIntConversionPendingColumns',
+ 'isMysqlUsedWithoutUTF8MB4',
+ 'isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed',
+ ])->getMock();
+ }
+
+ /**
+ * Removes directories created during tests.
+ *
+ * @after
+ * @return void
+ */
+ public function removeTestDirectories() {
+ foreach ($this->dirsToRemove as $dirToRemove) {
+ rmdir($dirToRemove);
+ }
+ $this->dirsToRemove = [];
+ }
+
+ public function testIsInternetConnectionWorkingDisabledViaConfig() {
+ $this->config->expects($this->once())
+ ->method('getSystemValue')
+ ->with('has_internet_connection', true)
+ ->will($this->returnValue(false));
+
+ $this->assertFalse(
+ self::invokePrivate(
+ $this->checkSetupController,
+ 'hasInternetConnectivityProblems'
+ )
+ );
+ }
+
+ public function testIsInternetConnectionWorkingCorrectly() {
+ $this->config->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('has_internet_connection', true)
+ ->will($this->returnValue(true));
+
+ $this->config->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('connectivity_check_domains', ['www.nextcloud.com', 'www.startpage.com', 'www.eff.org', 'www.edri.org'])
+ ->will($this->returnValue(['www.nextcloud.com', 'www.startpage.com', 'www.eff.org', 'www.edri.org']));
+
+ $client = $this->getMockBuilder('\OCP\Http\Client\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $client->expects($this->any())
+ ->method('get');
+
+ $this->clientService->expects($this->once())
+ ->method('newClient')
+ ->will($this->returnValue($client));
+
+
+ $this->assertFalse(
+ self::invokePrivate(
+ $this->checkSetupController,
+ 'hasInternetConnectivityProblems'
+ )
+ );
+ }
+
+ public function testIsInternetConnectionFail() {
+ $this->config->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('has_internet_connection', true)
+ ->will($this->returnValue(true));
+
+ $this->config->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('connectivity_check_domains', ['www.nextcloud.com', 'www.startpage.com', 'www.eff.org', 'www.edri.org'])
+ ->will($this->returnValue(['www.nextcloud.com', 'www.startpage.com', 'www.eff.org', 'www.edri.org']));
+
+ $client = $this->getMockBuilder('\OCP\Http\Client\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $client->expects($this->any())
+ ->method('get')
+ ->will($this->throwException(new \Exception()));
+
+ $this->clientService->expects($this->exactly(4))
+ ->method('newClient')
+ ->will($this->returnValue($client));
+
+ $this->assertTrue(
+ self::invokePrivate(
+ $this->checkSetupController,
+ 'hasInternetConnectivityProblems'
+ )
+ );
+ }
+
+
+ public function testIsMemcacheConfiguredFalse() {
+ $this->config->expects($this->once())
+ ->method('getSystemValue')
+ ->with('memcache.local', null)
+ ->will($this->returnValue(null));
+
+ $this->assertFalse(
+ self::invokePrivate(
+ $this->checkSetupController,
+ 'isMemcacheConfigured'
+ )
+ );
+ }
+
+ public function testIsMemcacheConfiguredTrue() {
+ $this->config->expects($this->once())
+ ->method('getSystemValue')
+ ->with('memcache.local', null)
+ ->will($this->returnValue('SomeProvider'));
+
+ $this->assertTrue(
+ self::invokePrivate(
+ $this->checkSetupController,
+ 'isMemcacheConfigured'
+ )
+ );
+ }
+
+ public function testIsPhpSupportedFalse() {
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('isPhpOutdated')
+ ->willReturn(true);
+
+ $this->assertEquals(
+ ['eol' => true, 'version' => PHP_VERSION],
+ self::invokePrivate($this->checkSetupController, 'isPhpSupported')
+ );
+ }
+
+ public function testIsPhpSupportedTrue() {
+ $this->checkSetupController
+ ->expects($this->exactly(2))
+ ->method('isPhpOutdated')
+ ->willReturn(false);
+
+ $this->assertEquals(
+ ['eol' => false, 'version' => PHP_VERSION],
+ self::invokePrivate($this->checkSetupController, 'isPhpSupported')
+ );
+
+
+ $this->assertEquals(
+ ['eol' => false, 'version' => PHP_VERSION],
+ self::invokePrivate($this->checkSetupController, 'isPhpSupported')
+ );
+ }
+
+ /**
+ * @dataProvider dataForwardedForHeadersWorking
+ *
+ * @param array $trustedProxies
+ * @param string $remoteAddrNotForwarded
+ * @param string $remoteAddr
+ * @param bool $result
+ */
+ public function testForwardedForHeadersWorking(array $trustedProxies, string $remoteAddrNotForwarded, string $remoteAddr, bool $result) {
+ $this->config->expects($this->once())
+ ->method('getSystemValue')
+ ->with('trusted_proxies', [])
+ ->willReturn($trustedProxies);
+ $this->request->expects($this->atLeastOnce())
+ ->method('getHeader')
+ ->willReturnMap([
+ ['REMOTE_ADDR', $remoteAddrNotForwarded],
+ ['X-Forwarded-Host', '']
+ ]);
+ $this->request->expects($this->any())
+ ->method('getRemoteAddress')
+ ->willReturn($remoteAddr);
+
+ $this->assertEquals(
+ $result,
+ self::invokePrivate($this->checkSetupController, 'forwardedForHeadersWorking')
+ );
+ }
+
+ public function dataForwardedForHeadersWorking() {
+ return [
+ // description => trusted proxies, getHeader('REMOTE_ADDR'), getRemoteAddr, expected result
+ 'no trusted proxies' => [[], '2.2.2.2', '2.2.2.2', true],
+ 'trusted proxy, remote addr not trusted proxy' => [['1.1.1.1'], '2.2.2.2', '2.2.2.2', true],
+ 'trusted proxy, remote addr is trusted proxy, x-forwarded-for working' => [['1.1.1.1'], '1.1.1.1', '2.2.2.2', true],
+ 'trusted proxy, remote addr is trusted proxy, x-forwarded-for not set' => [['1.1.1.1'], '1.1.1.1', '1.1.1.1', false],
+ ];
+ }
+
+ public function testForwardedHostPresentButTrustedProxiesEmpty() {
+ $this->config->expects($this->once())
+ ->method('getSystemValue')
+ ->with('trusted_proxies', [])
+ ->willReturn([]);
+ $this->request->expects($this->atLeastOnce())
+ ->method('getHeader')
+ ->willReturnMap([
+ ['REMOTE_ADDR', '1.1.1.1'],
+ ['X-Forwarded-Host', 'nextcloud.test']
+ ]);
+ $this->request->expects($this->any())
+ ->method('getRemoteAddress')
+ ->willReturn('1.1.1.1');
+
+ $this->assertEquals(
+ false,
+ self::invokePrivate($this->checkSetupController, 'forwardedForHeadersWorking')
+ );
+ }
+
+ public function testCheck() {
+ $this->config->expects($this->at(0))
+ ->method('getAppValue')
+ ->with('core', 'cronErrors')
+ ->willReturn('');
+ $this->config->expects($this->at(2))
+ ->method('getSystemValue')
+ ->with('connectivity_check_domains', ['www.nextcloud.com', 'www.startpage.com', 'www.eff.org', 'www.edri.org'])
+ ->will($this->returnValue(['www.nextcloud.com', 'www.startpage.com', 'www.eff.org', 'www.edri.org']));
+ $this->config->expects($this->at(3))
+ ->method('getSystemValue')
+ ->with('memcache.local', null)
+ ->will($this->returnValue('SomeProvider'));
+ $this->config->expects($this->at(4))
+ ->method('getSystemValue')
+ ->with('has_internet_connection', true)
+ ->will($this->returnValue(true));
+ $this->config->expects($this->at(5))
+ ->method('getSystemValue')
+ ->with('appstoreenabled', true)
+ ->will($this->returnValue(false));
+
+ $this->request->expects($this->atLeastOnce())
+ ->method('getHeader')
+ ->willReturnMap([
+ ['REMOTE_ADDR', '4.3.2.1'],
+ ['X-Forwarded-Host', '']
+ ]);
+
+ $client = $this->getMockBuilder('\OCP\Http\Client\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $client->expects($this->at(0))
+ ->method('get')
+ ->with('http://www.nextcloud.com/', [])
+ ->will($this->throwException(new \Exception()));
+ $client->expects($this->at(1))
+ ->method('get')
+ ->with('http://www.startpage.com/', [])
+ ->will($this->throwException(new \Exception()));
+ $client->expects($this->at(2))
+ ->method('get')
+ ->with('http://www.eff.org/', [])
+ ->will($this->throwException(new \Exception()));
+ $client->expects($this->at(3))
+ ->method('get')
+ ->with('http://www.edri.org/', [])
+ ->will($this->throwException(new \Exception()));
+ $this->clientService->expects($this->exactly(4))
+ ->method('newClient')
+ ->will($this->returnValue($client));
+ $this->urlGenerator->expects($this->at(0))
+ ->method('linkToDocs')
+ ->with('admin-performance')
+ ->willReturn('http://docs.example.org/server/go.php?to=admin-performance');
+ $this->urlGenerator->expects($this->at(1))
+ ->method('linkToDocs')
+ ->with('admin-security')
+ ->willReturn('https://docs.example.org/server/8.1/admin_manual/configuration_server/hardening.html');
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('isPhpOutdated')
+ ->willReturn(true);
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('isOpcacheProperlySetup')
+ ->willReturn(false);
+ $this->urlGenerator->expects($this->at(2))
+ ->method('linkToDocs')
+ ->with('admin-reverse-proxy')
+ ->willReturn('reverse-proxy-doc-link');
+ $this->urlGenerator->expects($this->at(3))
+ ->method('linkToDocs')
+ ->with('admin-code-integrity')
+ ->willReturn('http://docs.example.org/server/go.php?to=admin-code-integrity');
+ $this->urlGenerator->expects($this->at(4))
+ ->method('linkToDocs')
+ ->with('admin-php-opcache')
+ ->willReturn('http://docs.example.org/server/go.php?to=admin-php-opcache');
+ $this->urlGenerator->expects($this->at(5))
+ ->method('linkToDocs')
+ ->with('admin-db-conversion')
+ ->willReturn('http://docs.example.org/server/go.php?to=admin-db-conversion');
+ $this->urlGenerator->expects($this->at(6))
+ ->method('getAbsoluteURL')
+ ->with('index.php/settings/admin')
+ ->willReturn('https://server/index.php/settings/admin');
+ $this->checkSetupController
+ ->method('hasFreeTypeSupport')
+ ->willReturn(false);
+ $this->checkSetupController
+ ->method('hasMissingIndexes')
+ ->willReturn([]);
+ $this->checkSetupController
+ ->method('isSqliteUsed')
+ ->willReturn(false);
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('isReadOnlyConfig')
+ ->willReturn(false);
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('hasValidTransactionIsolationLevel')
+ ->willReturn(true);
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('hasFileinfoInstalled')
+ ->willReturn(true);
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('hasOpcacheLoaded')
+ ->willReturn(true);
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('hasWorkingFileLocking')
+ ->willReturn(true);
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getSuggestedOverwriteCliURL')
+ ->willReturn('');
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getLastCronInfo')
+ ->willReturn([
+ 'diffInSeconds' => 123,
+ 'relativeTime' => '2 hours ago',
+ 'backgroundJobsUrl' => 'https://example.org',
+ ]);
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('isPHPMailerUsed')
+ ->willReturn(false);
+ $this->checker
+ ->expects($this->once())
+ ->method('hasPassedCheck')
+ ->willReturn(true);
+ $this->memoryInfo
+ ->method('isMemoryLimitSufficient')
+ ->willReturn(true);
+
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getAppDirsWithDifferentOwner')
+ ->willReturn([]);
+
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('hasRecommendedPHPModules')
+ ->willReturn([]);
+
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('hasBigIntConversionPendingColumns')
+ ->willReturn([]);
+
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('isMysqlUsedWithoutUTF8MB4')
+ ->willReturn(false);
+
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed')
+ ->willReturn(true);
+
+ $expected = new DataResponse(
+ [
+ 'isGetenvServerWorking' => true,
+ 'isReadOnlyConfig' => false,
+ 'hasValidTransactionIsolationLevel' => true,
+ 'hasFileinfoInstalled' => true,
+ 'hasWorkingFileLocking' => true,
+ 'suggestedOverwriteCliURL' => '',
+ 'cronInfo' => [
+ 'diffInSeconds' => 123,
+ 'relativeTime' => '2 hours ago',
+ 'backgroundJobsUrl' => 'https://example.org',
+ ],
+ 'cronErrors' => [],
+ 'serverHasInternetConnectionProblems' => true,
+ 'isMemcacheConfigured' => true,
+ 'memcacheDocs' => 'http://docs.example.org/server/go.php?to=admin-performance',
+ 'isRandomnessSecure' => self::invokePrivate($this->checkSetupController, 'isRandomnessSecure'),
+ 'securityDocs' => 'https://docs.example.org/server/8.1/admin_manual/configuration_server/hardening.html',
+ 'isUsedTlsLibOutdated' => '',
+ 'phpSupported' => [
+ 'eol' => true,
+ 'version' => PHP_VERSION
+ ],
+ 'forwardedForHeadersWorking' => true,
+ 'reverseProxyDocs' => 'reverse-proxy-doc-link',
+ 'isCorrectMemcachedPHPModuleInstalled' => true,
+ 'hasPassedCodeIntegrityCheck' => true,
+ 'codeIntegrityCheckerDocumentation' => 'http://docs.example.org/server/go.php?to=admin-code-integrity',
+ 'isOpcacheProperlySetup' => false,
+ 'hasOpcacheLoaded' => true,
+ 'phpOpcacheDocumentation' => 'http://docs.example.org/server/go.php?to=admin-php-opcache',
+ 'isSettimelimitAvailable' => true,
+ 'hasFreeTypeSupport' => false,
+ 'isSqliteUsed' => false,
+ 'databaseConversionDocumentation' => 'http://docs.example.org/server/go.php?to=admin-db-conversion',
+ 'missingIndexes' => [],
+ 'isPHPMailerUsed' => false,
+ 'mailSettingsDocumentation' => 'https://server/index.php/settings/admin',
+ 'isMemoryLimitSufficient' => true,
+ 'appDirsWithDifferentOwner' => [],
+ 'recommendedPHPModules' => [],
+ 'pendingBigIntConversionColumns' => [],
+ 'isMysqlUsedWithoutUTF8MB4' => false,
+ 'isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed' => true,
+ ]
+ );
+ $this->assertEquals($expected, $this->checkSetupController->check());
+ }
+
+ public function testIsPHPMailerUsed() {
+ $checkSetupController = $this->getMockBuilder(CheckSetupController::class)
+ ->setConstructorArgs([
+ 'settings',
+ $this->request,
+ $this->config,
+ $this->clientService,
+ $this->urlGenerator,
+ $this->l10n,
+ $this->checker,
+ $this->logger,
+ $this->dispatcher,
+ $this->db,
+ $this->lockingProvider,
+ $this->dateTimeFormatter,
+ $this->memoryInfo,
+ $this->secureRandom,
+ ])
+ ->setMethods(null)->getMock();
+
+ $this->config->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('mail_smtpmode', 'smtp')
+ ->will($this->returnValue('php'));
+ $this->config->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('mail_smtpmode', 'smtp')
+ ->will($this->returnValue('not-php'));
+
+ $this->assertTrue($this->invokePrivate($checkSetupController, 'isPHPMailerUsed'));
+ $this->assertFalse($this->invokePrivate($checkSetupController, 'isPHPMailerUsed'));
+ }
+
+ public function testGetCurlVersion() {
+ $checkSetupController = $this->getMockBuilder(CheckSetupController::class)
+ ->setConstructorArgs([
+ 'settings',
+ $this->request,
+ $this->config,
+ $this->clientService,
+ $this->urlGenerator,
+ $this->l10n,
+ $this->checker,
+ $this->logger,
+ $this->dispatcher,
+ $this->db,
+ $this->lockingProvider,
+ $this->dateTimeFormatter,
+ $this->memoryInfo,
+ $this->secureRandom,
+ ])
+ ->setMethods(null)->getMock();
+
+ $this->assertArrayHasKey('ssl_version', $this->invokePrivate($checkSetupController, 'getCurlVersion'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithAnotherLibrary() {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->will($this->returnValue(true));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'SSLlib']));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithMisbehavingCurl() {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->will($this->returnValue(true));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue([]));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithOlderOpenSsl() {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->will($this->returnValue(true));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.1c']));
+ $this->assertSame('cURL is using an outdated OpenSSL version (OpenSSL/1.0.1c). Please update your operating system or features such as installing and updating apps via the app store or Federated Cloud Sharing will not work reliably.', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithOlderOpenSslAndWithoutAppstore() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('has_internet_connection', true)
+ ->will($this->returnValue(true));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.1c']));
+ $this->assertSame('cURL is using an outdated OpenSSL version (OpenSSL/1.0.1c). Please update your operating system or features such as Federated Cloud Sharing will not work reliably.', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithOlderOpenSsl1() {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->will($this->returnValue(true));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.2a']));
+ $this->assertSame('cURL is using an outdated OpenSSL version (OpenSSL/1.0.2a). Please update your operating system or features such as installing and updating apps via the app store or Federated Cloud Sharing will not work reliably.', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithMatchingOpenSslVersion() {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->will($this->returnValue(true));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.1d']));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithMatchingOpenSslVersion1() {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->will($this->returnValue(true));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.2b']));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ /**
+ * Setups a temp directory and some subdirectories.
+ * Then calls the 'getAppDirsWithDifferentOwner' method.
+ * The result is expected to be empty since
+ * there are no directories with different owners than the current user.
+ *
+ * @return void
+ */
+ public function testAppDirectoryOwnersOk() {
+ $tempDir = tempnam(sys_get_temp_dir(), 'apps') . 'dir';
+ mkdir($tempDir);
+ mkdir($tempDir . DIRECTORY_SEPARATOR . 'app1');
+ mkdir($tempDir . DIRECTORY_SEPARATOR . 'app2');
+ $this->dirsToRemove[] = $tempDir . DIRECTORY_SEPARATOR . 'app1';
+ $this->dirsToRemove[] = $tempDir . DIRECTORY_SEPARATOR . 'app2';
+ $this->dirsToRemove[] = $tempDir;
+ OC::$APPSROOTS = [
+ [
+ 'path' => $tempDir,
+ 'url' => '/apps',
+ 'writable' => true,
+ ],
+ ];
+ $this->assertSame(
+ [],
+ $this->invokePrivate($this->checkSetupController, 'getAppDirsWithDifferentOwner')
+ );
+ }
+
+ /**
+ * Calls the check for a none existing app root that is marked as not writable.
+ * It's expected that no error happens since the check shouldn't apply.
+ *
+ * @return void
+ */
+ public function testAppDirectoryOwnersNotWritable() {
+ $tempDir = tempnam(sys_get_temp_dir(), 'apps') . 'dir';
+ OC::$APPSROOTS = [
+ [
+ 'path' => $tempDir,
+ 'url' => '/apps',
+ 'writable' => false,
+ ],
+ ];
+ $this->assertSame(
+ [],
+ $this->invokePrivate($this->checkSetupController, 'getAppDirsWithDifferentOwner')
+ );
+ }
+
+ public function testIsBuggyNss400() {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->will($this->returnValue(true));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'NSS/1.0.2b']));
+ $client = $this->getMockBuilder('\OCP\Http\Client\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $exception = $this->getMockBuilder('\GuzzleHttp\Exception\ClientException')
+ ->disableOriginalConstructor()->getMock();
+ $response = $this->getMockBuilder(ResponseInterface::class)
+ ->disableOriginalConstructor()->getMock();
+ $response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue(400));
+ $exception->expects($this->once())
+ ->method('getResponse')
+ ->will($this->returnValue($response));
+
+ $client->expects($this->at(0))
+ ->method('get')
+ ->with('https://nextcloud.com/', [])
+ ->will($this->throwException($exception));
+
+ $this->clientService->expects($this->once())
+ ->method('newClient')
+ ->will($this->returnValue($client));
+
+ $this->assertSame('cURL is using an outdated NSS version (NSS/1.0.2b). Please update your operating system or features such as installing and updating apps via the app store or Federated Cloud Sharing will not work reliably.', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+
+ public function testIsBuggyNss200() {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->will($this->returnValue(true));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'NSS/1.0.2b']));
+ $client = $this->getMockBuilder('\OCP\Http\Client\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $exception = $this->getMockBuilder('\GuzzleHttp\Exception\ClientException')
+ ->disableOriginalConstructor()->getMock();
+ $response = $this->getMockBuilder(ResponseInterface::class)
+ ->disableOriginalConstructor()->getMock();
+ $response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue(200));
+ $exception->expects($this->once())
+ ->method('getResponse')
+ ->will($this->returnValue($response));
+
+ $client->expects($this->at(0))
+ ->method('get')
+ ->with('https://nextcloud.com/', [])
+ ->will($this->throwException($exception));
+
+ $this->clientService->expects($this->once())
+ ->method('newClient')
+ ->will($this->returnValue($client));
+
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithInternetDisabled() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('has_internet_connection', true)
+ ->will($this->returnValue(false));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithAppstoreDisabledAndServerToServerSharingEnabled() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('has_internet_connection', true)
+ ->will($this->returnValue(true));
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('appstoreenabled', true)
+ ->will($this->returnValue(false));
+ $this->config
+ ->expects($this->at(2))
+ ->method('getAppValue')
+ ->with('files_sharing', 'outgoing_server2server_share_enabled', 'yes')
+ ->will($this->returnValue('no'));
+ $this->config
+ ->expects($this->at(3))
+ ->method('getAppValue')
+ ->with('files_sharing', 'incoming_server2server_share_enabled', 'yes')
+ ->will($this->returnValue('yes'));
+
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue([]));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithAppstoreDisabledAndServerToServerSharingDisabled() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('has_internet_connection', true)
+ ->will($this->returnValue(true));
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('appstoreenabled', true)
+ ->will($this->returnValue(false));
+ $this->config
+ ->expects($this->at(2))
+ ->method('getAppValue')
+ ->with('files_sharing', 'outgoing_server2server_share_enabled', 'yes')
+ ->will($this->returnValue('no'));
+ $this->config
+ ->expects($this->at(3))
+ ->method('getAppValue')
+ ->with('files_sharing', 'incoming_server2server_share_enabled', 'yes')
+ ->will($this->returnValue('no'));
+
+ $this->checkSetupController
+ ->expects($this->never())
+ ->method('getCurlVersion')
+ ->will($this->returnValue([]));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testRescanFailedIntegrityCheck() {
+ $this->checker
+ ->expects($this->once())
+ ->method('runInstanceVerification');
+ $this->urlGenerator
+ ->expects($this->once())
+ ->method('linkToRoute')
+ ->with('settings.AdminSettings.index')
+ ->will($this->returnValue('/admin'));
+
+ $expected = new RedirectResponse('/admin');
+ $this->assertEquals($expected, $this->checkSetupController->rescanFailedIntegrityCheck());
+ }
+
+ public function testGetFailedIntegrityCheckDisabled() {
+ $this->checker
+ ->expects($this->once())
+ ->method('isCodeCheckEnforced')
+ ->willReturn(false);
+
+ $expected = new DataDisplayResponse('Integrity checker has been disabled. Integrity cannot be verified.');
+ $this->assertEquals($expected, $this->checkSetupController->getFailedIntegrityCheckFiles());
+ }
+
+
+ public function testGetFailedIntegrityCheckFilesWithNoErrorsFound() {
+ $this->checker
+ ->expects($this->once())
+ ->method('isCodeCheckEnforced')
+ ->willReturn(true);
+ $this->checker
+ ->expects($this->once())
+ ->method('getResults')
+ ->will($this->returnValue([]));
+
+ $expected = new DataDisplayResponse(
+ 'No errors have been found.',
+ Http::STATUS_OK,
+ [
+ 'Content-Type' => 'text/plain',
+ ]
+ );
+ $this->assertEquals($expected, $this->checkSetupController->getFailedIntegrityCheckFiles());
+ }
+
+ public function testGetFailedIntegrityCheckFilesWithSomeErrorsFound() {
+ $this->checker
+ ->expects($this->once())
+ ->method('isCodeCheckEnforced')
+ ->willReturn(true);
+ $this->checker
+ ->expects($this->once())
+ ->method('getResults')
+ ->will($this->returnValue(array ( 'core' => array ( 'EXTRA_FILE' => array('/testfile' => array()), 'INVALID_HASH' => array ( '/.idea/workspace.xml' => array ( 'expected' => 'f1c5e2630d784bc9cb02d5a28f55d6f24d06dae2a0fee685f3c2521b050955d9d452769f61454c9ddfa9c308146ade10546cfa829794448eaffbc9a04a29d216', 'current' => 'ce08bf30bcbb879a18b49239a9bec6b8702f52452f88a9d32142cad8d2494d5735e6bfa0d8642b2762c62ca5be49f9bf4ec231d4a230559d4f3e2c471d3ea094', ), '/lib/private/integritycheck/checker.php' => array ( 'expected' => 'c5a03bacae8dedf8b239997901ba1fffd2fe51271d13a00cc4b34b09cca5176397a89fc27381cbb1f72855fa18b69b6f87d7d5685c3b45aee373b09be54742ea', 'current' => '88a3a92c11db91dec1ac3be0e1c87f862c95ba6ffaaaa3f2c3b8f682187c66f07af3a3b557a868342ef4a271218fe1c1e300c478e6c156c5955ed53c40d06585', ), '/settings/controller/checksetupcontroller.php' => array ( 'expected' => '3e1de26ce93c7bfe0ede7c19cb6c93cadc010340225b375607a7178812e9de163179b0dc33809f451e01f491d93f6f5aaca7929685d21594cccf8bda732327c4', 'current' => '09563164f9904a837f9ca0b5f626db56c838e5098e0ccc1d8b935f68fa03a25c5ec6f6b2d9e44a868e8b85764dafd1605522b4af8db0ae269d73432e9a01e63a', ), ), ), 'bookmarks' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'dav' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'encryption' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'external' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'federation' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'files' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'files_antivirus' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'files_drop' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'files_external' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'files_pdfviewer' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'files_sharing' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'files_trashbin' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'files_versions' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'files_videoviewer' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'firstrunwizard' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'gitsmart' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'logreader' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature could not get verified.', ), ), 'password_policy' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'provisioning_api' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'sketch' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'threatblock' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'two_factor_auth' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'user_ldap' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), 'user_shibboleth' => array ( 'EXCEPTION' => array ( 'class' => 'OC\\IntegrityCheck\\Exceptions\\InvalidSignatureException', 'message' => 'Signature data not found.', ), ), )));
+
+ $expected = new DataDisplayResponse(
+ 'Technical information
+=====================
+The following list covers which files have failed the integrity check. Please read
+the previous linked documentation to learn more about the errors and how to fix
+them.
+
+Results
+=======
+- core
+ - EXTRA_FILE
+ - /testfile
+ - INVALID_HASH
+ - /.idea/workspace.xml
+ - /lib/private/integritycheck/checker.php
+ - /settings/controller/checksetupcontroller.php
+- bookmarks
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- dav
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- encryption
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- external
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- federation
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- files
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- files_antivirus
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- files_drop
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- files_external
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- files_pdfviewer
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- files_sharing
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- files_trashbin
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- files_versions
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- files_videoviewer
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- firstrunwizard
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- gitsmart
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- logreader
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature could not get verified.
+- password_policy
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- provisioning_api
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- sketch
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- threatblock
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- two_factor_auth
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- user_ldap
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+- user_shibboleth
+ - EXCEPTION
+ - OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ - Signature data not found.
+
+Raw output
+==========
+Array
+(
+ [core] => Array
+ (
+ [EXTRA_FILE] => Array
+ (
+ [/testfile] => Array
+ (
+ )
+
+ )
+
+ [INVALID_HASH] => Array
+ (
+ [/.idea/workspace.xml] => Array
+ (
+ [expected] => f1c5e2630d784bc9cb02d5a28f55d6f24d06dae2a0fee685f3c2521b050955d9d452769f61454c9ddfa9c308146ade10546cfa829794448eaffbc9a04a29d216
+ [current] => ce08bf30bcbb879a18b49239a9bec6b8702f52452f88a9d32142cad8d2494d5735e6bfa0d8642b2762c62ca5be49f9bf4ec231d4a230559d4f3e2c471d3ea094
+ )
+
+ [/lib/private/integritycheck/checker.php] => Array
+ (
+ [expected] => c5a03bacae8dedf8b239997901ba1fffd2fe51271d13a00cc4b34b09cca5176397a89fc27381cbb1f72855fa18b69b6f87d7d5685c3b45aee373b09be54742ea
+ [current] => 88a3a92c11db91dec1ac3be0e1c87f862c95ba6ffaaaa3f2c3b8f682187c66f07af3a3b557a868342ef4a271218fe1c1e300c478e6c156c5955ed53c40d06585
+ )
+
+ [/settings/controller/checksetupcontroller.php] => Array
+ (
+ [expected] => 3e1de26ce93c7bfe0ede7c19cb6c93cadc010340225b375607a7178812e9de163179b0dc33809f451e01f491d93f6f5aaca7929685d21594cccf8bda732327c4
+ [current] => 09563164f9904a837f9ca0b5f626db56c838e5098e0ccc1d8b935f68fa03a25c5ec6f6b2d9e44a868e8b85764dafd1605522b4af8db0ae269d73432e9a01e63a
+ )
+
+ )
+
+ )
+
+ [bookmarks] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [dav] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [encryption] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [external] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [federation] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [files] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [files_antivirus] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [files_drop] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [files_external] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [files_pdfviewer] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [files_sharing] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [files_trashbin] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [files_versions] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [files_videoviewer] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [firstrunwizard] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [gitsmart] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [logreader] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature could not get verified.
+ )
+
+ )
+
+ [password_policy] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [provisioning_api] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [sketch] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [threatblock] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [two_factor_auth] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [user_ldap] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+ [user_shibboleth] => Array
+ (
+ [EXCEPTION] => Array
+ (
+ [class] => OC\IntegrityCheck\Exceptions\InvalidSignatureException
+ [message] => Signature data not found.
+ )
+
+ )
+
+)
+',
+ Http::STATUS_OK,
+ [
+ 'Content-Type' => 'text/plain',
+ ]
+ );
+ $this->assertEquals($expected, $this->checkSetupController->getFailedIntegrityCheckFiles());
+ }
+
+ public function dataForIsMysqlUsedWithoutUTF8MB4() {
+ return [
+ ['sqlite', false, false],
+ ['sqlite', true, false],
+ ['postgres', false, false],
+ ['postgres', true, false],
+ ['oci', false, false],
+ ['oci', true, false],
+ ['mysql', false, true],
+ ['mysql', true, false],
+ ];
+ }
+
+ /**
+ * @dataProvider dataForIsMysqlUsedWithoutUTF8MB4
+ */
+ public function testIsMysqlUsedWithoutUTF8MB4(string $db, bool $useUTF8MB4, bool $expected) {
+ $this->config->method('getSystemValue')
+ ->will($this->returnCallback(function($key, $default) use ($db, $useUTF8MB4) {
+ if ($key === 'dbtype') {
+ return $db;
+ }
+ if ($key === 'mysql.utf8mb4') {
+ return $useUTF8MB4;
+ }
+ return $default;
+ }));
+
+ $checkSetupController = new CheckSetupController(
+ 'settings',
+ $this->request,
+ $this->config,
+ $this->clientService,
+ $this->urlGenerator,
+ $this->l10n,
+ $this->checker,
+ $this->logger,
+ $this->dispatcher,
+ $this->db,
+ $this->lockingProvider,
+ $this->dateTimeFormatter,
+ $this->memoryInfo,
+ $this->secureRandom
+ );
+
+ $this->assertSame($expected, $this->invokePrivate($checkSetupController, 'isMysqlUsedWithoutUTF8MB4'));
+ }
+
+ public function dataForIsEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed() {
+ return [
+ ['singlebucket', 'OC\\Files\\ObjectStore\\Swift', true],
+ ['multibucket', 'OC\\Files\\ObjectStore\\Swift', true],
+ ['singlebucket', 'OC\\Files\\ObjectStore\\Custom', true],
+ ['multibucket', 'OC\Files\\ObjectStore\\Custom', true],
+ ['singlebucket', 'OC\Files\ObjectStore\Swift', true],
+ ['multibucket', 'OC\Files\ObjectStore\Swift', true],
+ ['singlebucket', 'OC\Files\ObjectStore\Custom', true],
+ ['multibucket', 'OC\Files\ObjectStore\Custom', true],
+ ];
+ }
+
+ /**
+ * @dataProvider dataForIsEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed
+ */
+ public function testIsEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed(string $mode, string $className, bool $expected) {
+ $this->config->method('getSystemValue')
+ ->will($this->returnCallback(function($key, $default) use ($mode, $className) {
+ if ($key === 'objectstore' && $mode === 'singlebucket') {
+ return ['class' => $className];
+ }
+ if ($key === 'objectstore_multibucket' && $mode === 'multibucket') {
+ return ['class' => $className];
+ }
+ return $default;
+ }));
+
+ $checkSetupController = new CheckSetupController(
+ 'settings',
+ $this->request,
+ $this->config,
+ $this->clientService,
+ $this->urlGenerator,
+ $this->l10n,
+ $this->checker,
+ $this->logger,
+ $this->dispatcher,
+ $this->db,
+ $this->lockingProvider,
+ $this->dateTimeFormatter,
+ $this->memoryInfo,
+ $this->secureRandom
+ );
+
+ $this->assertSame($expected, $this->invokePrivate($checkSetupController, 'isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed'));
+ }
+}
diff --git a/apps/settings/tests/Controller/MailSettingsControllerTest.php b/apps/settings/tests/Controller/MailSettingsControllerTest.php
new file mode 100644
index 00000000000..7b12ca03e6c
--- /dev/null
+++ b/apps/settings/tests/Controller/MailSettingsControllerTest.php
@@ -0,0 +1,178 @@
+<?php
+/**
+ * @copyright 2014 Lukas Reschke lukas@nextcloud.com
+ * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
+ *
+ * @author Lukas Reschke <lukas@statuscode.ch>
+ * @author Joas Schilling <coding@schilljs.com>
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\Settings\Tests\Controller;
+
+use OC\Mail\Message;
+use OCA\Settings\Controller\MailSettingsController;
+use OCP\AppFramework\Http;
+use OCP\IConfig;
+use OCP\IL10N;
+use OCP\IRequest;
+use OCP\IUserSession;
+use OCP\Mail\IEMailTemplate;
+use OCP\Mail\IMailer;
+use OC\User\User;
+
+/**
+ * @package Tests\Settings\Controller
+ */
+class MailSettingsControllerTest extends \Test\TestCase {
+
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ private $config;
+ /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
+ private $userSession;
+ /** @var IMailer|\PHPUnit_Framework_MockObject_MockObject */
+ private $mailer;
+ /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
+ private $l;
+
+ /** @var MailSettingsController */
+ private $mailController;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->l = $this->createMock(IL10N::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->mailer = $this->createMock(IMailer::class);
+ /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject $request */
+ $request = $this->createMock(IRequest::class);
+ $this->mailController = new MailSettingsController(
+ 'settings',
+ $request,
+ $this->l,
+ $this->config,
+ $this->userSession,
+ $this->mailer,
+ 'no-reply@nextcloud.com'
+ );
+ }
+
+ public function testSetMailSettings() {
+ $this->config->expects($this->exactly(2))
+ ->method('setSystemValues')
+ ->withConsecutive(
+ [[
+ 'mail_domain' => 'nextcloud.com',
+ 'mail_from_address' => 'demo@nextcloud.com',
+ 'mail_smtpmode' => 'smtp',
+ 'mail_smtpsecure' => 'ssl',
+ 'mail_smtphost' => 'mx.nextcloud.org',
+ 'mail_smtpauthtype' => 'NTLM',
+ 'mail_smtpauth' => 1,
+ 'mail_smtpport' => '25',
+ 'mail_sendmailmode' => null,
+ ]],
+ [[
+ 'mail_domain' => 'nextcloud.com',
+ 'mail_from_address' => 'demo@nextcloud.com',
+ 'mail_smtpmode' => 'smtp',
+ 'mail_smtpsecure' => 'ssl',
+ 'mail_smtphost' => 'mx.nextcloud.org',
+ 'mail_smtpauthtype' => 'NTLM',
+ 'mail_smtpauth' => null,
+ 'mail_smtpport' => '25',
+ 'mail_smtpname' => null,
+ 'mail_smtppassword' => null,
+ 'mail_sendmailmode' => null,
+ ]]
+ );
+
+ // With authentication
+ $response = $this->mailController->setMailSettings(
+ 'nextcloud.com',
+ 'demo@nextcloud.com',
+ 'smtp',
+ 'ssl',
+ 'mx.nextcloud.org',
+ 'NTLM',
+ 1,
+ '25',
+ null
+ );
+ $this->assertSame(Http::STATUS_OK, $response->getStatus());
+
+ // Without authentication (testing the deletion of the stored password)
+ $response = $this->mailController->setMailSettings(
+ 'nextcloud.com',
+ 'demo@nextcloud.com',
+ 'smtp',
+ 'ssl',
+ 'mx.nextcloud.org',
+ 'NTLM',
+ 0,
+ '25',
+ null
+ );
+ $this->assertSame(Http::STATUS_OK, $response->getStatus());
+
+ }
+
+ public function testStoreCredentials() {
+ $this->config
+ ->expects($this->once())
+ ->method('setSystemValues')
+ ->with([
+ 'mail_smtpname' => 'UsernameToStore',
+ 'mail_smtppassword' => 'PasswordToStore',
+ ]);
+
+ $response = $this->mailController->storeCredentials('UsernameToStore', 'PasswordToStore');
+ $this->assertSame(Http::STATUS_OK, $response->getStatus());
+ }
+
+ public function testSendTestMail() {
+ $user = $this->createMock(User::class);
+ $user->expects($this->any())
+ ->method('getUID')
+ ->will($this->returnValue('Werner'));
+ $user->expects($this->any())
+ ->method('getDisplayName')
+ ->will($this->returnValue('Werner Brösel'));
+
+ $this->l->expects($this->any())
+ ->method('t')
+ ->willReturnCallback(function($text, $parameters = []) {
+ return vsprintf($text, $parameters);
+ });
+ $this->userSession
+ ->expects($this->any())
+ ->method('getUser')
+ ->will($this->returnValue($user));
+
+ // Ensure that it fails when no mail address has been specified
+ $response = $this->mailController->sendTestMail();
+ $this->assertSame(Http::STATUS_BAD_REQUEST, $response->getStatus());
+ $this->assertSame('You need to set your user email before being able to send test emails.', $response->getData());
+
+ // If no exception is thrown it should work
+ $this->config
+ ->expects($this->any())
+ ->method('getUserValue')
+ ->will($this->returnValue('mail@example.invalid'));
+ $this->mailer->expects($this->once())
+ ->method('createMessage')
+ ->willReturn($this->createMock(Message::class));
+ $emailTemplate = $this->createMock(IEMailTemplate::class);
+ $this->mailer
+ ->expects($this->once())
+ ->method('createEMailTemplate')
+ ->willReturn($emailTemplate);
+ $response = $this->mailController->sendTestMail();
+ $this->assertSame(Http::STATUS_OK, $response->getStatus(), $response->getData());
+ }
+
+}
diff --git a/apps/settings/tests/Controller/TwoFactorSettingsControllerTest.php b/apps/settings/tests/Controller/TwoFactorSettingsControllerTest.php
new file mode 100644
index 00000000000..58b82bc0930
--- /dev/null
+++ b/apps/settings/tests/Controller/TwoFactorSettingsControllerTest.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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\Settings\Tests\Controller;
+
+use OC\Authentication\TwoFactorAuth\EnforcementState;
+use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor;
+use OCA\Settings\Controller\TwoFactorSettingsController;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class TwoFactorSettingsControllerTest extends TestCase {
+
+ /** @var IRequest|MockObject */
+ private $request;
+
+ /** @var MandatoryTwoFactor|MockObject */
+ private $mandatoryTwoFactor;
+
+ /** @var TwoFactorSettingsController */
+ private $controller;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->request = $this->createMock(IRequest::class);
+ $this->mandatoryTwoFactor = $this->createMock(MandatoryTwoFactor::class);
+
+ $this->controller = new TwoFactorSettingsController(
+ 'settings',
+ $this->request,
+ $this->mandatoryTwoFactor
+ );
+ }
+
+ public function testIndex() {
+ $state = new EnforcementState(true);
+ $this->mandatoryTwoFactor->expects($this->once())
+ ->method('getState')
+ ->willReturn($state);
+ $expected = new JSONResponse($state);
+
+ $resp = $this->controller->index();
+
+ $this->assertEquals($expected, $resp);
+ }
+
+ public function testUpdate() {
+ $state = new EnforcementState(true);
+ $this->mandatoryTwoFactor->expects($this->once())
+ ->method('setState')
+ ->with($this->equalTo(new EnforcementState(true)));
+ $this->mandatoryTwoFactor->expects($this->once())
+ ->method('getState')
+ ->willReturn($state);
+ $expected = new JSONResponse($state);
+
+ $resp = $this->controller->update(true);
+
+ $this->assertEquals($expected, $resp);
+ }
+
+}
diff --git a/apps/settings/tests/Controller/UsersControllerTest.php b/apps/settings/tests/Controller/UsersControllerTest.php
new file mode 100644
index 00000000000..5ca45297c58
--- /dev/null
+++ b/apps/settings/tests/Controller/UsersControllerTest.php
@@ -0,0 +1,552 @@
+<?php
+/**
+ * @author Lukas Reschke
+ * @copyright 2014-2015 Lukas Reschke lukas@owncloud.com
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\Settings\Tests\Controller;
+
+use OC\Accounts\AccountManager;
+use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
+use OC\Group\Manager;
+use OCA\Settings\Controller\UsersController;
+use OCP\App\IAppManager;
+use OCP\AppFramework\Http;
+use OCP\BackgroundJob\IJobList;
+use OCP\Encryption\IEncryptionModule;
+use OCP\Encryption\IManager;
+use OCP\IAvatarManager;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IL10N;
+use OCP\ILogger;
+use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\IUserSession;
+use OCP\L10N\IFactory;
+use OCP\Mail\IMailer;
+use OCP\Security\ISecureRandom;
+
+/**
+ * @group DB
+ *
+ * @package Tests\Settings\Controller
+ */
+class UsersControllerTest extends \Test\TestCase {
+
+ /** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $groupManager;
+ /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $userManager;
+ /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
+ private $userSession;
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ private $config;
+ /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
+ private $logger;
+ /** @var IMailer|\PHPUnit_Framework_MockObject_MockObject */
+ private $mailer;
+ /** @var IFactory|\PHPUnit_Framework_MockObject_MockObject */
+ private $l10nFactory;
+ /** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $appManager;
+ /** @var IAvatarManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $avatarManager;
+ /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
+ private $l;
+ /** @var AccountManager | \PHPUnit_Framework_MockObject_MockObject */
+ private $accountManager;
+ /** @var ISecureRandom | \PHPUnit_Framework_MockObject_MockObject */
+ private $secureRandom;
+ /** @var \OCA\Settings\Mailer\NewUserMailHelper|\PHPUnit_Framework_MockObject_MockObject */
+ private $newUserMailHelper;
+ /** @var IJobList | \PHPUnit_Framework_MockObject_MockObject */
+ private $jobList;
+ /** @var \OC\Security\IdentityProof\Manager |\PHPUnit_Framework_MockObject_MockObject */
+ private $securityManager;
+ /** @var IManager | \PHPUnit_Framework_MockObject_MockObject */
+ private $encryptionManager;
+ /** @var IEncryptionModule | \PHPUnit_Framework_MockObject_MockObject */
+ private $encryptionModule;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->groupManager = $this->createMock(Manager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->l = $this->createMock(IL10N::class);
+ $this->mailer = $this->createMock(IMailer::class);
+ $this->l10nFactory = $this->createMock(IFactory::class);
+ $this->appManager = $this->createMock(IAppManager::class);
+ $this->accountManager = $this->createMock(AccountManager::class);
+ $this->securityManager = $this->getMockBuilder(\OC\Security\IdentityProof\Manager::class)->disableOriginalConstructor()->getMock();
+ $this->jobList = $this->createMock(IJobList::class);
+ $this->encryptionManager = $this->createMock(IManager::class);
+
+ $this->l->method('t')
+ ->will($this->returnCallback(function ($text, $parameters = []) {
+ return vsprintf($text, $parameters);
+ }));
+
+ $this->encryptionModule = $this->createMock(IEncryptionModule::class);
+ $this->encryptionManager->expects($this->any())->method('getEncryptionModules')
+ ->willReturn(['encryptionModule' => ['callback' => function() { return $this->encryptionModule;}]]);
+
+ }
+
+ /**
+ * @param bool $isAdmin
+ * @return UsersController | \PHPUnit_Framework_MockObject_MockObject
+ */
+ protected function getController($isAdmin = false, $mockedMethods = []) {
+ if (empty($mockedMethods)) {
+ return new UsersController(
+ 'settings',
+ $this->createMock(IRequest::class),
+ $this->userManager,
+ $this->groupManager,
+ $this->userSession,
+ $this->config,
+ $isAdmin,
+ $this->l,
+ $this->mailer,
+ $this->l10nFactory,
+ $this->appManager,
+ $this->accountManager,
+ $this->securityManager,
+ $this->jobList,
+ $this->encryptionManager
+ );
+ } else {
+ return $this->getMockBuilder(UsersController::class)
+ ->setConstructorArgs(
+ [
+ 'settings',
+ $this->createMock(IRequest::class),
+ $this->userManager,
+ $this->groupManager,
+ $this->userSession,
+ $this->config,
+ $isAdmin,
+ $this->l,
+ $this->mailer,
+ $this->l10nFactory,
+ $this->appManager,
+ $this->accountManager,
+ $this->securityManager,
+ $this->jobList,
+ $this->encryptionManager
+ ]
+ )->setMethods($mockedMethods)->getMock();
+ }
+ }
+
+ /**
+ * @dataProvider dataTestSetUserSettings
+ *
+ * @param string $email
+ * @param bool $validEmail
+ * @param $expectedStatus
+ */
+ public function testSetUserSettings($email, $validEmail, $expectedStatus) {
+ $controller = $this->getController(false, ['saveUserSettings']);
+ $user = $this->createMock(IUser::class);
+
+ $this->userSession->method('getUser')->willReturn($user);
+
+ if (!empty($email) && $validEmail) {
+ $this->mailer->expects($this->once())->method('validateMailAddress')
+ ->willReturn($validEmail);
+ }
+
+ $saveData = (!empty($email) && $validEmail) || empty($email);
+
+ if ($saveData) {
+ $this->accountManager->expects($this->once())
+ ->method('getUser')
+ ->with($user)
+ ->willReturn([
+ AccountManager::PROPERTY_DISPLAYNAME =>
+ [
+ 'value' => 'Display name',
+ 'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
+ 'verified' => AccountManager::NOT_VERIFIED,
+ ],
+ AccountManager::PROPERTY_ADDRESS =>
+ [
+ 'value' => '',
+ 'scope' => AccountManager::VISIBILITY_PRIVATE,
+ 'verified' => AccountManager::NOT_VERIFIED,
+ ],
+ AccountManager::PROPERTY_WEBSITE =>
+ [
+ 'value' => '',
+ 'scope' => AccountManager::VISIBILITY_PRIVATE,
+ 'verified' => AccountManager::NOT_VERIFIED,
+ ],
+ AccountManager::PROPERTY_EMAIL =>
+ [
+ 'value' => '',
+ 'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
+ 'verified' => AccountManager::NOT_VERIFIED,
+ ],
+ AccountManager::PROPERTY_AVATAR =>
+ [
+ 'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY
+ ],
+ AccountManager::PROPERTY_PHONE =>
+ [
+ 'value' => '',
+ 'scope' => AccountManager::VISIBILITY_PRIVATE,
+ 'verified' => AccountManager::NOT_VERIFIED,
+ ],
+ AccountManager::PROPERTY_TWITTER =>
+ [
+ 'value' => '',
+ 'scope' => AccountManager::VISIBILITY_PRIVATE,
+ 'verified' => AccountManager::NOT_VERIFIED,
+ ],
+ ]);
+
+ $controller->expects($this->once())->method('saveUserSettings');
+ } else {
+ $controller->expects($this->never())->method('saveUserSettings');
+ }
+
+ $result = $controller->setUserSettings(
+ AccountManager::VISIBILITY_CONTACTS_ONLY,
+ 'displayName',
+ AccountManager::VISIBILITY_CONTACTS_ONLY,
+ '47658468',
+ AccountManager::VISIBILITY_CONTACTS_ONLY,
+ $email,
+ AccountManager::VISIBILITY_CONTACTS_ONLY,
+ 'nextcloud.com',
+ AccountManager::VISIBILITY_CONTACTS_ONLY,
+ 'street and city',
+ AccountManager::VISIBILITY_CONTACTS_ONLY,
+ '@nextclouders',
+ AccountManager::VISIBILITY_CONTACTS_ONLY
+ );
+
+ $this->assertSame($expectedStatus, $result->getStatus());
+ }
+
+ public function dataTestSetUserSettings() {
+ return [
+ ['', true, Http::STATUS_OK],
+ ['', false, Http::STATUS_OK],
+ ['example.com', false, Http::STATUS_UNPROCESSABLE_ENTITY],
+ ['john@example.com', true, Http::STATUS_OK],
+ ];
+ }
+
+ /**
+ * @dataProvider dataTestSaveUserSettings
+ *
+ * @param array $data
+ * @param string $oldEmailAddress
+ * @param string $oldDisplayName
+ */
+ public function testSaveUserSettings($data,
+ $oldEmailAddress,
+ $oldDisplayName
+ ) {
+ $controller = $this->getController();
+ $user = $this->createMock(IUser::class);
+
+ $user->method('getDisplayName')->willReturn($oldDisplayName);
+ $user->method('getEMailAddress')->willReturn($oldEmailAddress);
+ $user->method('canChangeDisplayName')->willReturn(true);
+
+ if ($data[AccountManager::PROPERTY_EMAIL]['value'] === $oldEmailAddress ||
+ ($oldEmailAddress === null && $data[AccountManager::PROPERTY_EMAIL]['value'] === '')) {
+ $user->expects($this->never())->method('setEMailAddress');
+ } else {
+ $user->expects($this->once())->method('setEMailAddress')
+ ->with($data[AccountManager::PROPERTY_EMAIL]['value'])
+ ->willReturn(true);
+ }
+
+ if ($data[AccountManager::PROPERTY_DISPLAYNAME]['value'] === $oldDisplayName ||
+ ($oldDisplayName === null && $data[AccountManager::PROPERTY_DISPLAYNAME]['value'] === '')) {
+ $user->expects($this->never())->method('setDisplayName');
+ } else {
+ $user->expects($this->once())->method('setDisplayName')
+ ->with($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
+ ->willReturn(true);
+ }
+
+ $this->accountManager->expects($this->once())->method('updateUser')
+ ->with($user, $data);
+
+ $this->invokePrivate($controller, 'saveUserSettings', [$user, $data]);
+ }
+
+ public function dataTestSaveUserSettings() {
+ return [
+ [
+ [
+ AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
+ ],
+ 'john@example.com',
+ 'john doe'
+ ],
+ [
+ [
+ AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
+ ],
+ 'johnNew@example.com',
+ 'john New doe'
+ ],
+ [
+ [
+ AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
+ ],
+ 'johnNew@example.com',
+ 'john doe'
+ ],
+ [
+ [
+ AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
+ ],
+ 'john@example.com',
+ 'john New doe'
+ ],
+ [
+ [
+ AccountManager::PROPERTY_EMAIL => ['value' => ''],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
+ ],
+ null,
+ 'john New doe'
+ ],
+ [
+ [
+ AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
+ ],
+ 'john@example.com',
+ null
+ ],
+
+ ];
+ }
+
+ /**
+ * @dataProvider dataTestSaveUserSettingsException
+ *
+ * @param array $data
+ * @param string $oldEmailAddress
+ * @param string $oldDisplayName
+ * @param bool $setDisplayNameResult
+ * @param bool $canChangeEmail
+ *
+ * @expectedException \OC\ForbiddenException
+ */
+ public function testSaveUserSettingsException($data,
+ $oldEmailAddress,
+ $oldDisplayName,
+ $setDisplayNameResult,
+ $canChangeEmail
+ ) {
+ $controller = $this->getController();
+ $user = $this->createMock(IUser::class);
+
+ $user->method('getDisplayName')->willReturn($oldDisplayName);
+ $user->method('getEMailAddress')->willReturn($oldEmailAddress);
+
+ if ($data[AccountManager::PROPERTY_EMAIL]['value'] !== $oldEmailAddress) {
+ $user->method('canChangeDisplayName')
+ ->willReturn($canChangeEmail);
+ }
+
+ if ($data[AccountManager::PROPERTY_DISPLAYNAME]['value'] !== $oldDisplayName) {
+ $user->method('setDisplayName')
+ ->with($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
+ ->willReturn($setDisplayNameResult);
+ }
+
+ $this->invokePrivate($controller, 'saveUserSettings', [$user, $data]);
+ }
+
+
+ public function dataTestSaveUserSettingsException() {
+ return [
+ [
+ [
+ AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
+ ],
+ 'johnNew@example.com',
+ 'john New doe',
+ true,
+ false
+ ],
+ [
+ [
+ AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
+ ],
+ 'johnNew@example.com',
+ 'john New doe',
+ false,
+ true
+ ],
+ [
+ [
+ AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
+ AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
+ ],
+ 'johnNew@example.com',
+ 'john New doe',
+ false,
+ false
+ ],
+
+ ];
+ }
+
+ /**
+ * @param string $account
+ * @param string $type
+ * @param array $dataBefore
+ * @param array $expectedData
+ *
+ * @dataProvider dataTestGetVerificationCode
+ */
+ public function testGetVerificationCode($account, $type, $dataBefore, $expectedData, $onlyVerificationCode) {
+
+ $message = 'Use my Federated Cloud ID to share with me: user@nextcloud.com';
+ $signature = 'theSignature';
+
+ $code = $message . ' ' . $signature;
+ if($type === AccountManager::PROPERTY_TWITTER) {
+ $code = $message . ' ' . md5($signature);
+ }
+
+ $controller = $this->getController(false, ['signMessage', 'getCurrentTime']);
+
+ $user = $this->createMock(IUser::class);
+ $this->userSession->expects($this->once())->method('getUser')->willReturn($user);
+ $this->accountManager->expects($this->once())->method('getUser')->with($user)->willReturn($dataBefore);
+ $user->expects($this->any())->method('getCloudId')->willReturn('user@nextcloud.com');
+ $user->expects($this->any())->method('getUID')->willReturn('uid');
+ $controller->expects($this->once())->method('signMessage')->with($user, $message)->willReturn($signature);
+ $controller->expects($this->any())->method('getCurrentTime')->willReturn(1234567);
+
+ if ($onlyVerificationCode === false) {
+ $this->accountManager->expects($this->once())->method('updateUser')->with($user, $expectedData);
+ $this->jobList->expects($this->once())->method('add')
+ ->with('OCA\Settings\BackgroundJobs\VerifyUserData',
+ [
+ 'verificationCode' => $code,
+ 'data' => $dataBefore[$type]['value'],
+ 'type' => $type,
+ 'uid' => 'uid',
+ 'try' => 0,
+ 'lastRun' => 1234567
+ ]);
+ }
+
+ $result = $controller->getVerificationCode($account, $onlyVerificationCode);
+
+ $data = $result->getData();
+ $this->assertSame(Http::STATUS_OK, $result->getStatus());
+ $this->assertSame($code, $data['code']);
+ }
+
+ public function dataTestGetVerificationCode() {
+
+ $accountDataBefore = [
+ AccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::NOT_VERIFIED],
+ AccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::NOT_VERIFIED, 'signature' => 'theSignature'],
+ ];
+
+ $accountDataAfterWebsite = [
+ AccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::VERIFICATION_IN_PROGRESS, 'signature' => 'theSignature'],
+ AccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::NOT_VERIFIED, 'signature' => 'theSignature'],
+ ];
+
+ $accountDataAfterTwitter = [
+ AccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::NOT_VERIFIED],
+ AccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::VERIFICATION_IN_PROGRESS, 'signature' => 'theSignature'],
+ ];
+
+ return [
+ ['verify-twitter', AccountManager::PROPERTY_TWITTER, $accountDataBefore, $accountDataAfterTwitter, false],
+ ['verify-website', AccountManager::PROPERTY_WEBSITE, $accountDataBefore, $accountDataAfterWebsite, false],
+ ['verify-twitter', AccountManager::PROPERTY_TWITTER, $accountDataBefore, $accountDataAfterTwitter, true],
+ ['verify-website', AccountManager::PROPERTY_WEBSITE, $accountDataBefore, $accountDataAfterWebsite, true],
+ ];
+ }
+
+ /**
+ * test get verification code in case no valid user was given
+ */
+ public function testGetVerificationCodeInvalidUser() {
+
+ $controller = $this->getController();
+ $this->userSession->expects($this->once())->method('getUser')->willReturn(null);
+ $result = $controller->getVerificationCode('account', false);
+
+ $this->assertSame(Http::STATUS_BAD_REQUEST, $result->getStatus());
+ }
+
+ /**
+ * @dataProvider dataTestCanAdminChangeUserPasswords
+ *
+ * @param bool $encryptionEnabled
+ * @param bool $encryptionModuleLoaded
+ * @param bool $masterKeyEnabled
+ * @param bool $expected
+ */
+ public function testCanAdminChangeUserPasswords($encryptionEnabled,
+ $encryptionModuleLoaded,
+ $masterKeyEnabled,
+ $expected) {
+ $controller = $this->getController();
+
+ $this->encryptionManager->expects($this->any())
+ ->method('isEnabled')
+ ->willReturn($encryptionEnabled);
+ $this->encryptionManager->expects($this->any())
+ ->method('getEncryptionModule')
+ ->willReturnCallback(function() use ($encryptionModuleLoaded) {
+ if ($encryptionModuleLoaded) return $this->encryptionModule;
+ else throw new ModuleDoesNotExistsException();
+ });
+ $this->encryptionModule->expects($this->any())
+ ->method('needDetailedAccessList')
+ ->willReturn(!$masterKeyEnabled);
+
+ $result = $this->invokePrivate($controller, 'canAdminChangeUserPasswords', []);
+ $this->assertSame($expected, $result);
+ }
+
+ public function dataTestCanAdminChangeUserPasswords() {
+ return [
+ // encryptionEnabled, encryptionModuleLoaded, masterKeyEnabled, expectedResult
+ [true, true, true, true],
+ [false, true, true, true],
+ [true, false, true, false],
+ [false, false, true, true],
+ [true, true, false, false],
+ [false, true, false, false],
+ [true, false, false, false],
+ [false, false, false, true],
+ ];
+ }
+
+}
diff --git a/apps/settings/tests/Mailer/NewUserMailHelperTest.php b/apps/settings/tests/Mailer/NewUserMailHelperTest.php
new file mode 100644
index 00000000000..20e6612f94e
--- /dev/null
+++ b/apps/settings/tests/Mailer/NewUserMailHelperTest.php
@@ -0,0 +1,881 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\Settings\Tests\Mailer;
+
+use OC\Mail\EMailTemplate;
+use OCP\L10N\IFactory;
+use OCP\Mail\IEMailTemplate;
+use OC\Mail\Message;
+use OCA\Settings\Mailer\NewUserMailHelper;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Defaults;
+use OCP\IConfig;
+use OCP\IL10N;
+use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\Mail\IMailer;
+use OCP\Security\ICrypto;
+use OCP\Security\ISecureRandom;
+use Test\TestCase;
+
+class NewUserMailHelperTest extends TestCase {
+ /** @var Defaults|\PHPUnit_Framework_MockObject_MockObject */
+ private $defaults;
+ /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
+ private $urlGenerator;
+ /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
+ private $l10n;
+ /** @var IMailer|\PHPUnit_Framework_MockObject_MockObject */
+ private $mailer;
+ /** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */
+ private $secureRandom;
+ /** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */
+ private $timeFactory;
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ private $config;
+ /** @var ICrypto|\PHPUnit_Framework_MockObject_MockObject */
+ private $crypto;
+ /** @var \OCA\Settings\Mailer\NewUserMailHelper */
+ private $newUserMailHelper;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->defaults = $this->createMock(Defaults::class);
+ $this->defaults->method('getLogo')
+ ->willReturn('myLogo');
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
+ $this->l10n = $this->createMock(IL10N::class);
+ $this->l10nFactory = $this->createMock(IFactory::class);
+ $this->mailer = $this->createMock(IMailer::class);
+ $template = new EMailTemplate(
+ $this->defaults,
+ $this->urlGenerator,
+ $this->l10n,
+ 'test.TestTemplate',
+ []
+ );
+ $this->mailer->method('createEMailTemplate')
+ ->will($this->returnValue($template));
+ $this->secureRandom = $this->createMock(ISecureRandom::class);
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->config
+ ->expects($this->any())
+ ->method('getSystemValue')
+ ->willReturnCallback(function($arg) {
+ switch ($arg) {
+ case 'secret':
+ return 'MyInstanceWideSecret';
+ case 'customclient_desktop':
+ return 'https://nextcloud.com/install/#install-clients';
+ }
+ return '';
+ });
+ $this->crypto = $this->createMock(ICrypto::class);
+ $this->l10n->method('t')
+ ->will($this->returnCallback(function ($text, $parameters = []) {
+ return vsprintf($text, $parameters);
+ }));
+ $this->l10nFactory->method('get')
+ ->will($this->returnCallback(function ($text, $lang) {
+ return $this->l10n;
+ }));
+
+ $this->newUserMailHelper = new \OCA\Settings\Mailer\NewUserMailHelper(
+ $this->defaults,
+ $this->urlGenerator,
+ $this->l10nFactory,
+ $this->mailer,
+ $this->secureRandom,
+ $this->timeFactory,
+ $this->config,
+ $this->crypto,
+ 'no-reply@nextcloud.com'
+ );
+ }
+
+ public function testGenerateTemplateWithPasswordResetToken() {
+ $this->secureRandom
+ ->expects($this->once())
+ ->method('generate')
+ ->with(21,
+ ISecureRandom::CHAR_DIGITS .
+ ISecureRandom::CHAR_LOWER .
+ ISecureRandom::CHAR_UPPER
+ )
+ ->willReturn('MySuperLongSecureRandomToken');
+ $this->timeFactory
+ ->expects($this->once())
+ ->method('getTime')
+ ->willReturn('12345');
+ /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */
+ $user = $this->createMock(IUser::class);
+ $user
+ ->expects($this->any())
+ ->method('getEmailAddress')
+ ->willReturn('recipient@example.com');
+ $this->crypto
+ ->expects($this->once())
+ ->method('encrypt')
+ ->with('12345:MySuperLongSecureRandomToken', 'recipient@example.comMyInstanceWideSecret')
+ ->willReturn('TokenCiphertext');
+ $user
+ ->expects($this->any())
+ ->method('getUID')
+ ->willReturn('john');
+ $this->config
+ ->expects($this->once())
+ ->method('setUserValue')
+ ->with('john', 'core', 'lostpassword', 'TokenCiphertext');
+ $this->urlGenerator
+ ->expects($this->at(0))
+ ->method('linkToRouteAbsolute')
+ ->with('core.lost.resetform', ['userId' => 'john', 'token' => 'MySuperLongSecureRandomToken'])
+ ->willReturn('https://example.com/resetPassword/MySuperLongSecureRandomToken');
+ $user
+ ->expects($this->any())
+ ->method('getDisplayName')
+ ->willReturn('john');
+ $user
+ ->expects($this->at(5))
+ ->method('getUID')
+ ->willReturn('john');
+ $this->defaults
+ ->expects($this->any())
+ ->method('getName')
+ ->willReturn('TestCloud');
+ $this->defaults
+ ->expects($this->any())
+ ->method('getTextColorPrimary')
+ ->willReturn('#ffffff');
+
+ $expectedHtmlBody = <<<EOF
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="-webkit-font-smoothing:antialiased;background:#f3f3f3!important">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width">
+ <title></title>
+ <style type="text/css">@media only screen{html{min-height:100%;background:#F5F5F5}}@media only screen and (max-width:610px){table.body img{width:auto;height:auto}table.body center{min-width:0!important}table.body .container{width:95%!important}table.body .columns{height:auto!important;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:30px!important;padding-right:30px!important}th.small-12{display:inline-block!important;width:100%!important}table.menu{width:100%!important}table.menu td,table.menu th{width:auto!important;display:inline-block!important}table.menu.vertical td,table.menu.vertical th{display:block!important}table.menu[align=center]{width:auto!important}}</style>
+</head>
+<body style="-moz-box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-box-sizing:border-box;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;Margin:0;background:#f3f3f3!important;box-sizing:border-box;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;min-width:100%;padding:0;text-align:left;width:100%!important">
+ <span class="preheader" style="color:#F5F5F5;display:none!important;font-size:1px;line-height:1px;max-height:0;max-width:0;mso-hide:all!important;opacity:0;overflow:hidden;visibility:hidden">
+ </span>
+ <table class="body" style="-webkit-font-smoothing:antialiased;Margin:0;background:#f3f3f3!important;border-collapse:collapse;border-spacing:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;height:100%;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <center data-parsed="" style="min-width:580px;width:100%"><table align="center" class="wrapper header float-center" style="Margin:0 auto;background:#8a8a8a;background-color:;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:20px;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table align="center" class="container" style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table class="row collapse" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <center data-parsed="" style="min-width:580px;width:100%">
+ <img class="logo float-center" src="" alt="TestCloud" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;outline:0;text-align:center;text-decoration:none" height="50">
+ </center>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</table>
+<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="80px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:80px;font-weight:400;hyphens:auto;line-height:80px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table><table align="center" class="container main-heading float-center" style="Margin:0 auto;background:0 0!important;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:580px">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <h1 class="text-center" style="Margin:0;Margin-bottom:10px;color:inherit;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:24px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:center;word-wrap:normal">Welcome aboard</h1>
+ </td>
+ </tr>
+ </tbody>
+</table>
+<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="40px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:40px;font-weight:400;hyphens:auto;line-height:40px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table><table align="center" class="wrapper content float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table align="center" class="container has-shadow" style="Margin:0 auto;background:#fefefe;border-collapse:collapse;border-spacing:0;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 3px 0 rgba(0,0,0,.1);margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+ </table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
+ <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">Welcome to your TestCloud account, you can add, protect, and share your data.</p>
+ </th>
+ <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+ </tr>
+ </table>
+ </th>
+ </tr>
+ </tbody>
+</table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
+ <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">Your username is: john</p>
+ </th>
+ <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+ </tr>
+ </table>
+ </th>
+ </tr>
+ </tbody>
+</table><table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="50px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:50px;font-weight:400;hyphens:auto;line-height:50px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table>
+<table align="center" class="row btn-group" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
+ <center data-parsed="" style="min-width:490px;width:100%">
+ <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto;background:;background-color:;color:#fefefe;">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border:0 solid ;border-collapse:collapse!important;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <a href="https://example.com/resetPassword/MySuperLongSecureRandomToken" style="Margin:0;border:0 solid ;border-radius:2px;color:#ffffff;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid #ffffff;text-decoration:none">Set your password</a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <table class="button btn default secondary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#777;border:0 solid #777;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <a href="https://nextcloud.com/install/#install-clients" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">Install Client</a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </center>
+ </th>
+ <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+ </tr>
+ </table>
+ </th>
+ </tr>
+ </tbody>
+</table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</table><table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table>
+<table align="center" class="wrapper footer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <center data-parsed="" style="min-width:580px;width:100%">
+ <table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="15px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:15px;font-weight:400;hyphens:auto;line-height:15px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+ </table>
+ <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#C8C8C8;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center">TestCloud - <br>This is an automatically sent email, please do not reply.</p>
+ </center>
+ </td>
+ </tr>
+</table> </center>
+ </td>
+ </tr>
+ </table>
+ <!-- prevent Gmail on iOS font size manipulation -->
+ <div style="display:none;white-space:nowrap;font:15px courier;line-height:0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div>
+ </body>
+</html>
+EOF;
+ $expectedTextBody = <<<EOF
+Welcome aboard
+
+Welcome to your TestCloud account, you can add, protect, and share your data.
+
+Your username is: john
+
+Set your password: https://example.com/resetPassword/MySuperLongSecureRandomToken
+Install Client: https://nextcloud.com/install/#install-clients
+
+
+--
+TestCloud -
+This is an automatically sent email, please do not reply.
+EOF;
+
+ $result = $this->newUserMailHelper->generateTemplate($user, true);
+ $this->assertEquals($expectedHtmlBody, $result->renderHtml());
+ $this->assertEquals($expectedTextBody, $result->renderText());
+ $this->assertSame('OC\Mail\EMailTemplate', get_class($result));
+ }
+
+ public function testGenerateTemplateWithoutPasswordResetToken() {
+ $this->urlGenerator
+ ->expects($this->at(0))
+ ->method('getAbsoluteURL')
+ ->with('/')
+ ->willReturn('https://example.com/');
+
+ /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */
+ $user = $this->createMock(IUser::class);
+ $user
+ ->expects($this->any())
+ ->method('getDisplayName')
+ ->willReturn('John Doe');
+ $user
+ ->expects($this->any())
+ ->method('getUID')
+ ->willReturn('john');
+ $this->defaults
+ ->expects($this->any())
+ ->method('getName')
+ ->willReturn('TestCloud');
+ $this->defaults
+ ->expects($this->any())
+ ->method('getTextColorPrimary')
+ ->willReturn('#ffffff');
+
+ $expectedHtmlBody = <<<EOF
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="-webkit-font-smoothing:antialiased;background:#f3f3f3!important">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width">
+ <title></title>
+ <style type="text/css">@media only screen{html{min-height:100%;background:#F5F5F5}}@media only screen and (max-width:610px){table.body img{width:auto;height:auto}table.body center{min-width:0!important}table.body .container{width:95%!important}table.body .columns{height:auto!important;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:30px!important;padding-right:30px!important}th.small-12{display:inline-block!important;width:100%!important}table.menu{width:100%!important}table.menu td,table.menu th{width:auto!important;display:inline-block!important}table.menu.vertical td,table.menu.vertical th{display:block!important}table.menu[align=center]{width:auto!important}}</style>
+</head>
+<body style="-moz-box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-box-sizing:border-box;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;Margin:0;background:#f3f3f3!important;box-sizing:border-box;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;min-width:100%;padding:0;text-align:left;width:100%!important">
+ <span class="preheader" style="color:#F5F5F5;display:none!important;font-size:1px;line-height:1px;max-height:0;max-width:0;mso-hide:all!important;opacity:0;overflow:hidden;visibility:hidden">
+ </span>
+ <table class="body" style="-webkit-font-smoothing:antialiased;Margin:0;background:#f3f3f3!important;border-collapse:collapse;border-spacing:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;height:100%;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <center data-parsed="" style="min-width:580px;width:100%"><table align="center" class="wrapper header float-center" style="Margin:0 auto;background:#8a8a8a;background-color:;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:20px;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table align="center" class="container" style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table class="row collapse" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <center data-parsed="" style="min-width:580px;width:100%">
+ <img class="logo float-center" src="" alt="TestCloud" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;outline:0;text-align:center;text-decoration:none" height="50">
+ </center>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</table>
+<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="80px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:80px;font-weight:400;hyphens:auto;line-height:80px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table><table align="center" class="container main-heading float-center" style="Margin:0 auto;background:0 0!important;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:580px">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <h1 class="text-center" style="Margin:0;Margin-bottom:10px;color:inherit;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:24px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:center;word-wrap:normal">Welcome aboard John Doe</h1>
+ </td>
+ </tr>
+ </tbody>
+</table>
+<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="40px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:40px;font-weight:400;hyphens:auto;line-height:40px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table><table align="center" class="wrapper content float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table align="center" class="container has-shadow" style="Margin:0 auto;background:#fefefe;border-collapse:collapse;border-spacing:0;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 3px 0 rgba(0,0,0,.1);margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+ </table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
+ <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">Welcome to your TestCloud account, you can add, protect, and share your data.</p>
+ </th>
+ <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+ </tr>
+ </table>
+ </th>
+ </tr>
+ </tbody>
+</table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
+ <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">Your username is: john</p>
+ </th>
+ <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+ </tr>
+ </table>
+ </th>
+ </tr>
+ </tbody>
+</table><table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="50px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:50px;font-weight:400;hyphens:auto;line-height:50px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table>
+<table align="center" class="row btn-group" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
+ <center data-parsed="" style="min-width:490px;width:100%">
+ <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto;background:;background-color:;color:#fefefe;">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border:0 solid ;border-collapse:collapse!important;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <a href="https://example.com/" style="Margin:0;border:0 solid ;border-radius:2px;color:#ffffff;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid #ffffff;text-decoration:none">Go to TestCloud</a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <table class="button btn default secondary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#777;border:0 solid #777;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <a href="https://nextcloud.com/install/#install-clients" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">Install Client</a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </center>
+ </th>
+ <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+ </tr>
+ </table>
+ </th>
+ </tr>
+ </tbody>
+</table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</table><table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table>
+<table align="center" class="wrapper footer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <center data-parsed="" style="min-width:580px;width:100%">
+ <table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="15px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:15px;font-weight:400;hyphens:auto;line-height:15px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+ </table>
+ <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#C8C8C8;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center">TestCloud - <br>This is an automatically sent email, please do not reply.</p>
+ </center>
+ </td>
+ </tr>
+</table> </center>
+ </td>
+ </tr>
+ </table>
+ <!-- prevent Gmail on iOS font size manipulation -->
+ <div style="display:none;white-space:nowrap;font:15px courier;line-height:0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div>
+ </body>
+</html>
+EOF;
+ $expectedTextBody = <<<EOF
+Welcome aboard John Doe
+
+Welcome to your TestCloud account, you can add, protect, and share your data.
+
+Your username is: john
+
+Go to TestCloud: https://example.com/
+Install Client: https://nextcloud.com/install/#install-clients
+
+
+--
+TestCloud -
+This is an automatically sent email, please do not reply.
+EOF;
+
+ $result = $this->newUserMailHelper->generateTemplate($user, false);
+ $this->assertEquals($expectedHtmlBody, $result->renderHtml());
+ $this->assertEquals($expectedTextBody, $result->renderText());
+ $this->assertSame('OC\Mail\EMailTemplate', get_class($result));
+ }
+
+ public function testGenerateTemplateWithoutUserId() {
+ $this->urlGenerator
+ ->expects($this->at(0))
+ ->method('getAbsoluteURL')
+ ->with('/')
+ ->willReturn('https://example.com/');
+
+ /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */
+ $user = $this->createMock(IUser::class);
+ $user
+ ->expects($this->any())
+ ->method('getDisplayName')
+ ->willReturn('John Doe');
+ $user
+ ->expects($this->any())
+ ->method('getUID')
+ ->willReturn('john');
+ $user
+ ->expects($this->atLeastOnce())
+ ->method('getBackendClassName')
+ ->willReturn('LDAP');
+ $this->defaults
+ ->expects($this->any())
+ ->method('getName')
+ ->willReturn('TestCloud');
+ $this->defaults
+ ->expects($this->any())
+ ->method('getTextColorPrimary')
+ ->willReturn('#ffffff');
+
+ $expectedHtmlBody = <<<EOF
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="-webkit-font-smoothing:antialiased;background:#f3f3f3!important">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width">
+ <title></title>
+ <style type="text/css">@media only screen{html{min-height:100%;background:#F5F5F5}}@media only screen and (max-width:610px){table.body img{width:auto;height:auto}table.body center{min-width:0!important}table.body .container{width:95%!important}table.body .columns{height:auto!important;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:30px!important;padding-right:30px!important}th.small-12{display:inline-block!important;width:100%!important}table.menu{width:100%!important}table.menu td,table.menu th{width:auto!important;display:inline-block!important}table.menu.vertical td,table.menu.vertical th{display:block!important}table.menu[align=center]{width:auto!important}}</style>
+</head>
+<body style="-moz-box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-box-sizing:border-box;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;Margin:0;background:#f3f3f3!important;box-sizing:border-box;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;min-width:100%;padding:0;text-align:left;width:100%!important">
+ <span class="preheader" style="color:#F5F5F5;display:none!important;font-size:1px;line-height:1px;max-height:0;max-width:0;mso-hide:all!important;opacity:0;overflow:hidden;visibility:hidden">
+ </span>
+ <table class="body" style="-webkit-font-smoothing:antialiased;Margin:0;background:#f3f3f3!important;border-collapse:collapse;border-spacing:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;height:100%;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <center data-parsed="" style="min-width:580px;width:100%"><table align="center" class="wrapper header float-center" style="Margin:0 auto;background:#8a8a8a;background-color:;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:20px;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table align="center" class="container" style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table class="row collapse" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <center data-parsed="" style="min-width:580px;width:100%">
+ <img class="logo float-center" src="" alt="TestCloud" align="center" style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;margin:0 auto;outline:0;text-align:center;text-decoration:none" height="50">
+ </center>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</table>
+<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="80px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:80px;font-weight:400;hyphens:auto;line-height:80px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table><table align="center" class="container main-heading float-center" style="Margin:0 auto;background:0 0!important;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:580px">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <h1 class="text-center" style="Margin:0;Margin-bottom:10px;color:inherit;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:24px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:center;word-wrap:normal">Welcome aboard John Doe</h1>
+ </td>
+ </tr>
+ </tbody>
+</table>
+<table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="40px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:40px;font-weight:400;hyphens:auto;line-height:40px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table><table align="center" class="wrapper content float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table align="center" class="container has-shadow" style="Margin:0 auto;background:#fefefe;border-collapse:collapse;border-spacing:0;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 3px 0 rgba(0,0,0,.1);margin:0 auto;padding:0;text-align:inherit;vertical-align:top;width:580px">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+ </table><table class="row description" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
+ <p class="text-left" style="Margin:0;Margin-bottom:10px;color:#777;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;margin-bottom:10px;padding:0;text-align:left">Welcome to your TestCloud account, you can add, protect, and share your data.</p>
+ </th>
+ <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+ </tr>
+ </table>
+ </th>
+ </tr>
+ </tbody>
+</table><table class="spacer" style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="50px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:50px;font-weight:400;hyphens:auto;line-height:50px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table>
+<table align="center" class="row btn-group" style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th class="small-12 large-12 columns first last" style="Margin:0 auto;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0 auto;padding:0;padding-bottom:30px;padding-left:30px;padding-right:30px;text-align:left;width:550px">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
+ <center data-parsed="" style="min-width:490px;width:100%">
+ <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto;background:;background-color:;color:#fefefe;">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border:0 solid ;border-collapse:collapse!important;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <a href="https://example.com/" style="Margin:0;border:0 solid ;border-radius:2px;color:#ffffff;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid #ffffff;text-decoration:none">Go to TestCloud</a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <table class="button btn default secondary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#777;border:0 solid #777;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <a href="https://nextcloud.com/install/#install-clients" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">Install Client</a>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </center>
+ </th>
+ <th class="expander" style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
+ </tr>
+ </table>
+ </th>
+ </tr>
+ </tbody>
+</table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</table><table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="60px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:60px;font-weight:400;hyphens:auto;line-height:60px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+</table>
+<table align="center" class="wrapper footer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td class="wrapper-inner" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <center data-parsed="" style="min-width:580px;width:100%">
+ <table class="spacer float-center" style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:100%">
+ <tbody>
+ <tr style="padding:0;text-align:left;vertical-align:top">
+ <td height="15px" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:15px;font-weight:400;hyphens:auto;line-height:15px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">&#xA0;</td>
+ </tr>
+ </tbody>
+ </table>
+ <p class="text-center float-center" align="center" style="Margin:0;Margin-bottom:10px;color:#C8C8C8;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:12px;font-weight:400;line-height:16px;margin:0;margin-bottom:10px;padding:0;text-align:center">TestCloud - <br>This is an automatically sent email, please do not reply.</p>
+ </center>
+ </td>
+ </tr>
+</table> </center>
+ </td>
+ </tr>
+ </table>
+ <!-- prevent Gmail on iOS font size manipulation -->
+ <div style="display:none;white-space:nowrap;font:15px courier;line-height:0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div>
+ </body>
+</html>
+EOF;
+ $expectedTextBody = <<<EOF
+Welcome aboard John Doe
+
+Welcome to your TestCloud account, you can add, protect, and share your data.
+
+Go to TestCloud: https://example.com/
+Install Client: https://nextcloud.com/install/#install-clients
+
+
+--
+TestCloud -
+This is an automatically sent email, please do not reply.
+EOF;
+
+ $result = $this->newUserMailHelper->generateTemplate($user, false);
+ $this->assertEquals($expectedHtmlBody, $result->renderHtml());
+ $this->assertEquals($expectedTextBody, $result->renderText());
+ $this->assertSame('OC\Mail\EMailTemplate', get_class($result));
+ }
+
+ public function testSendMail() {
+ /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */
+ $user = $this->createMock(IUser::class);
+ $user
+ ->expects($this->at(0))
+ ->method('getEMailAddress')
+ ->willReturn('recipient@example.com');
+ $user
+ ->expects($this->at(1))
+ ->method('getDisplayName')
+ ->willReturn('John Doe');
+ /** @var IEMailTemplate|\PHPUnit_Framework_MockObject_MockObject $emailTemplate */
+ $emailTemplate = $this->createMock(IEMailTemplate::class);
+ $message = $this->createMock(Message::class);
+ $message
+ ->expects($this->at(0))
+ ->method('setTo')
+ ->with(['recipient@example.com' => 'John Doe']);
+ $message
+ ->expects($this->at(1))
+ ->method('setFrom')
+ ->with(['no-reply@nextcloud.com' => 'TestCloud']);
+ $message
+ ->expects($this->at(2))
+ ->method('useTemplate')
+ ->with($emailTemplate);
+ $this->defaults
+ ->expects($this->exactly(1))
+ ->method('getName')
+ ->willReturn('TestCloud');
+ $this->mailer
+ ->expects($this->once())
+ ->method('createMessage')
+ ->willReturn($message);
+
+ $this->newUserMailHelper->sendMail($user, $emailTemplate);
+ }
+}
diff --git a/apps/settings/tests/Middleware/SubadminMiddlewareTest.php b/apps/settings/tests/Middleware/SubadminMiddlewareTest.php
new file mode 100644
index 00000000000..752184bf7c7
--- /dev/null
+++ b/apps/settings/tests/Middleware/SubadminMiddlewareTest.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * @author Lukas Reschke
+ * @copyright 2014 Lukas Reschke lukas@owncloud.com
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\Settings\Tests\Middleware;
+
+use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException;
+use OC\AppFramework\Utility\ControllerMethodReflector;
+use OCA\Settings\Middleware\SubadminMiddleware;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IL10N;
+
+/**
+ * Verifies whether an user has at least subadmin rights.
+ * To bypass use the `@NoSubadminRequired` annotation
+ *
+ * @package Tests\Settings\Middleware
+ */
+class SubadminMiddlewareTest extends \Test\TestCase {
+ /** @var SubadminMiddleware */
+ private $subadminMiddlewareAsSubAdmin;
+ /** @var SubadminMiddleware */
+ private $subadminMiddleware;
+ /** @var ControllerMethodReflector */
+ private $reflector;
+ /** @var Controller */
+ private $controller;
+ /** @var IL10N */
+ private $l10n;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->reflector = $this->getMockBuilder(ControllerMethodReflector::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->controller = $this->getMockBuilder(Controller::class)
+ ->disableOriginalConstructor()->getMock();
+ $this->l10n = $this->createMock(IL10N::class);
+
+ $this->subadminMiddlewareAsSubAdmin = new SubadminMiddleware($this->reflector, true, $this->l10n);
+ $this->subadminMiddleware = new SubadminMiddleware($this->reflector, false, $this->l10n);
+ }
+
+ /**
+ * @expectedException \OC\AppFramework\Middleware\Security\Exceptions\NotAdminException
+ */
+ public function testBeforeControllerAsUserWithExemption() {
+ $this->reflector
+ ->expects($this->once())
+ ->method('hasAnnotation')
+ ->with('NoSubadminRequired')
+ ->will($this->returnValue(false));
+ $this->subadminMiddleware->beforeController($this->controller, 'foo');
+ }
+
+
+ public function testBeforeControllerAsUserWithoutExemption() {
+ $this->reflector
+ ->expects($this->once())
+ ->method('hasAnnotation')
+ ->with('NoSubadminRequired')
+ ->will($this->returnValue(true));
+ $this->subadminMiddleware->beforeController($this->controller, 'foo');
+ }
+
+ public function testBeforeControllerAsSubAdminWithoutExemption() {
+ $this->reflector
+ ->expects($this->once())
+ ->method('hasAnnotation')
+ ->with('NoSubadminRequired')
+ ->will($this->returnValue(false));
+ $this->subadminMiddlewareAsSubAdmin->beforeController($this->controller, 'foo');
+ }
+
+ public function testBeforeControllerAsSubAdminWithExemption() {
+ $this->reflector
+ ->expects($this->once())
+ ->method('hasAnnotation')
+ ->with('NoSubadminRequired')
+ ->will($this->returnValue(true));
+ $this->subadminMiddlewareAsSubAdmin->beforeController($this->controller, 'foo');
+ }
+
+ public function testAfterNotAdminException() {
+ $expectedResponse = new TemplateResponse('core', '403', array(), 'guest');
+ $expectedResponse->setStatus(403);
+ $this->assertEquals($expectedResponse, $this->subadminMiddleware->afterException($this->controller, 'foo', new NotAdminException('')));
+ }
+
+ /**
+ * @expectedException \Exception
+ */
+ public function testAfterRegularException() {
+ $expectedResponse = new TemplateResponse('core', '403', array(), 'guest');
+ $expectedResponse->setStatus(403);
+ $this->subadminMiddleware->afterException($this->controller, 'foo', new \Exception());
+ }
+}
diff --git a/apps/settings/tests/Personal/Security/AuthtokensTest.php b/apps/settings/tests/Personal/Security/AuthtokensTest.php
new file mode 100644
index 00000000000..8cb394101e2
--- /dev/null
+++ b/apps/settings/tests/Personal/Security/AuthtokensTest.php
@@ -0,0 +1,124 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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 Test\Settings\Personal\Security;
+
+use OC\Authentication\Token\DefaultToken;
+use OC\Authentication\Token\IProvider as IAuthTokenProvider;
+use OCA\Settings\Personal\Security;
+use OCA\Settings\Personal\Security\Authtokens;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IInitialStateService;
+use OCP\ISession;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class AuthtokensTest extends TestCase {
+
+ /** @var IAuthTokenProvider|MockObject */
+ private $authTokenProvider;
+
+ /** @var ISession|MockObject */
+ private $session;
+
+ /** @var IInitialStateService|MockObject */
+ private $initialStateService;
+
+ /** @var string */
+ private $uid;
+
+ /** @var Security\Authtokens */
+ private $section;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->authTokenProvider = $this->createMock(IAuthTokenProvider::class);
+ $this->session = $this->createMock(ISession::class);
+ $this->initialStateService = $this->createMock(IInitialStateService::class);
+ $this->uid = 'test123';
+
+ $this->section = new Authtokens(
+ $this->authTokenProvider,
+ $this->session,
+ $this->initialStateService,
+ $this->uid
+ );
+ }
+
+ public function testGetForm() {
+ $token1 = new DefaultToken();
+ $token1->setId(100);
+ $token2 = new DefaultToken();
+ $token2->setId(200);
+ $tokens = [
+ $token1,
+ $token2,
+ ];
+ $sessionToken = new DefaultToken();
+ $sessionToken->setId(100);
+
+ $this->authTokenProvider->expects($this->once())
+ ->method('getTokenByUser')
+ ->with($this->uid)
+ ->willReturn($tokens);
+ $this->session->expects($this->once())
+ ->method('getId')
+ ->willReturn('session123');
+ $this->authTokenProvider->expects($this->once())
+ ->method('getToken')
+ ->with('session123')
+ ->willReturn($sessionToken);
+ $this->initialStateService->expects($this->once())
+ ->method('provideInitialState')
+ ->with('settings', 'app_tokens', [
+ [
+ 'id' => 100,
+ 'name' => null,
+ 'lastActivity' => 0,
+ 'type' => 0,
+ 'canDelete' => false,
+ 'current' => true,
+ 'scope' => ['filesystem' => true],
+ 'canRename' => false,
+ ],
+ [
+ 'id' => 200,
+ 'name' => null,
+ 'lastActivity' => 0,
+ 'type' => 0,
+ 'canDelete' => true,
+ 'scope' => ['filesystem' => true],
+ 'canRename' => true,
+ ],
+ ]);
+
+ $form = $this->section->getForm();
+
+ $expected = new TemplateResponse('settings', 'settings/personal/security/authtokens');
+ $this->assertEquals($expected, $form);
+ }
+
+}
diff --git a/apps/settings/tests/Settings/Admin/MailTest.php b/apps/settings/tests/Settings/Admin/MailTest.php
new file mode 100644
index 00000000000..5e26454a6fa
--- /dev/null
+++ b/apps/settings/tests/Settings/Admin/MailTest.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @author Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\Settings\Tests\Settings\Admin;
+
+use OCA\Settings\Admin\Mail;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use Test\TestCase;
+
+class MailTest extends TestCase {
+ /** @var Mail */
+ private $admin;
+ /** @var IConfig */
+ private $config;
+
+ public function setUp() {
+ parent::setUp();
+ $this->config = $this->getMockBuilder(IConfig::class)->getMock();
+
+ $this->admin = new Mail(
+ $this->config
+ );
+ }
+
+ public function testGetForm() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('mail_domain', '')
+ ->willReturn('mx.nextcloud.com');
+ $this->config
+ ->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('mail_from_address', '')
+ ->willReturn('no-reply@nextcloud.com');
+ $this->config
+ ->expects($this->at(2))
+ ->method('getSystemValue')
+ ->with('mail_smtpmode', '')
+ ->willReturn('smtp');
+ $this->config
+ ->expects($this->at(3))
+ ->method('getSystemValue')
+ ->with('mail_smtpsecure', '')
+ ->willReturn(true);
+ $this->config
+ ->expects($this->at(4))
+ ->method('getSystemValue')
+ ->with('mail_smtphost', '')
+ ->willReturn('smtp.nextcloud.com');
+ $this->config
+ ->expects($this->at(5))
+ ->method('getSystemValue')
+ ->with('mail_smtpport', '')
+ ->willReturn(25);
+ $this->config
+ ->expects($this->at(6))
+ ->method('getSystemValue')
+ ->with('mail_smtpauthtype', '')
+ ->willReturn('login');
+ $this->config
+ ->expects($this->at(7))
+ ->method('getSystemValue')
+ ->with('mail_smtpauth', false)
+ ->willReturn(true);
+ $this->config
+ ->expects($this->at(8))
+ ->method('getSystemValue')
+ ->with('mail_smtpname', '')
+ ->willReturn('smtp.sender.com');
+ $this->config
+ ->expects($this->at(9))
+ ->method('getSystemValue')
+ ->with('mail_smtppassword', '')
+ ->willReturn('mypassword');
+ $this->config
+ ->expects($this->at(10))
+ ->method('getSystemValue')
+ ->with('mail_sendmailmode', 'smtp')
+ ->willReturn('smtp');
+
+ $expected = new TemplateResponse(
+ 'settings',
+ 'settings/admin/additional-mail',
+ [
+ 'sendmail_is_available' => (bool) \OC_Helper::findBinaryPath('sendmail'),
+ 'mail_domain' => 'mx.nextcloud.com',
+ 'mail_from_address' => 'no-reply@nextcloud.com',
+ 'mail_smtpmode' => 'smtp',
+ 'mail_smtpsecure' => true,
+ 'mail_smtphost' => 'smtp.nextcloud.com',
+ 'mail_smtpport' => 25,
+ 'mail_smtpauthtype' => 'login',
+ 'mail_smtpauth' => true,
+ 'mail_smtpname' => 'smtp.sender.com',
+ 'mail_smtppassword' => '********',
+ 'mail_sendmailmode' => 'smtp',
+ ],
+ ''
+ );
+
+ $this->assertEquals($expected, $this->admin->getForm());
+ }
+
+ public function testGetSection() {
+ $this->assertSame('server', $this->admin->getSection());
+ }
+
+ public function testGetPriority() {
+ $this->assertSame(10, $this->admin->getPriority());
+ }
+}
diff --git a/apps/settings/tests/Settings/Admin/SecurityTest.php b/apps/settings/tests/Settings/Admin/SecurityTest.php
new file mode 100644
index 00000000000..ea9222ab1a7
--- /dev/null
+++ b/apps/settings/tests/Settings/Admin/SecurityTest.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @author Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\Settings\Tests\Settings\Admin;
+
+use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor;
+use OC\Encryption\Manager;
+use OCA\Settings\Admin\Security;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IInitialStateService;
+use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class SecurityTest extends TestCase {
+ /** @var Security */
+ private $admin;
+ /** @var Manager */
+ private $manager;
+ /** @var IUserManager */
+ private $userManager;
+ /** @var MandatoryTwoFactor|MockObject */
+ private $mandatoryTwoFactor;
+ /** @var IInitialStateService|MockObject */
+ private $initialState;
+
+ public function setUp() {
+ parent::setUp();
+ $this->manager = $this->getMockBuilder(Manager::class)->disableOriginalConstructor()->getMock();
+ $this->userManager = $this->getMockBuilder(IUserManager::class)->getMock();
+ $this->mandatoryTwoFactor = $this->createMock(MandatoryTwoFactor::class);
+ $this->initialState = $this->createMock(IInitialStateService::class);
+
+ $this->admin = new Security(
+ $this->manager,
+ $this->userManager,
+ $this->mandatoryTwoFactor,
+ $this->initialState
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function encryptionSettingsProvider() {
+ return [
+ [true],
+ [false],
+ ];
+ }
+
+ /**
+ * @dataProvider encryptionSettingsProvider
+ * @param bool $enabled
+ */
+ public function testGetFormWithOnlyOneBackend($enabled) {
+ $this->manager
+ ->expects($this->once())
+ ->method('isEnabled')
+ ->willReturn($enabled);
+ $this->manager
+ ->expects($this->once())
+ ->method('isReady')
+ ->willReturn($enabled);
+ $this->manager
+ ->expects($this->once())
+ ->method('getEncryptionModules')
+ ->willReturn([]);
+ $this->userManager
+ ->expects($this->once())
+ ->method('getBackends')
+ ->willReturn(['entry']);
+ $expected = new TemplateResponse(
+ 'settings',
+ 'settings/admin/security',
+ [
+ 'encryptionEnabled' => $enabled,
+ 'encryptionReady' => $enabled,
+ 'externalBackendsEnabled' => false,
+ 'encryptionModules' => []
+ ],
+ ''
+ );
+ $this->assertEquals($expected, $this->admin->getForm());
+ }
+
+ /**
+ * @dataProvider encryptionSettingsProvider
+ * @param bool $enabled
+ */
+ public function testGetFormWithMultipleBackends($enabled) {
+ $this->manager
+ ->expects($this->once())
+ ->method('isEnabled')
+ ->willReturn($enabled);
+ $this->manager
+ ->expects($this->once())
+ ->method('isReady')
+ ->willReturn($enabled);
+ $this->manager
+ ->expects($this->once())
+ ->method('getEncryptionModules')
+ ->willReturn([]);
+ $this->userManager
+ ->expects($this->once())
+ ->method('getBackends')
+ ->willReturn(['entry', 'entry']);
+ $expected = new TemplateResponse(
+ 'settings',
+ 'settings/admin/security',
+ [
+ 'encryptionEnabled' => $enabled,
+ 'encryptionReady' => $enabled,
+ 'externalBackendsEnabled' => true,
+ 'encryptionModules' => []
+ ],
+ ''
+ );
+ $this->assertEquals($expected, $this->admin->getForm());
+ }
+
+ public function testGetSection() {
+ $this->assertSame('security', $this->admin->getSection());
+ }
+
+ public function testGetPriority() {
+ $this->assertSame(10, $this->admin->getPriority());
+ }
+}
diff --git a/apps/settings/tests/Settings/Admin/ServerTest.php b/apps/settings/tests/Settings/Admin/ServerTest.php
new file mode 100644
index 00000000000..bcb990b6b6b
--- /dev/null
+++ b/apps/settings/tests/Settings/Admin/ServerTest.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @author Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\Settings\Tests\Settings\Admin;
+
+use OCA\Settings\Admin\Server;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use Test\TestCase;
+
+class ServerTest extends TestCase {
+ /** @var Server */
+ private $admin;
+ /** @var IConfig */
+ private $config;
+
+ public function setUp() {
+ parent::setUp();
+ $this->config = $this->createMock(IConfig::class);
+
+ $this->admin = new Server(
+ $this->config
+ );
+ }
+
+ public function testGetForm() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getAppValue')
+ ->with('core', 'backgroundjobs_mode', 'ajax')
+ ->willReturn('ajax');
+ $this->config
+ ->expects($this->at(1))
+ ->method('getAppValue')
+ ->with('core', 'lastcron', false)
+ ->willReturn(false);
+ $this->config
+ ->expects($this->at(2))
+ ->method('getAppValue')
+ ->with('core', 'cronErrors')
+ ->willReturn('');
+ $expected = new TemplateResponse(
+ 'settings',
+ 'settings/admin/server',
+ [
+ 'backgroundjobs_mode' => 'ajax',
+ 'lastcron' => false,
+ 'cronErrors' => '',
+ 'cli_based_cron_possible' => true,
+ 'cli_based_cron_user' => function_exists('posix_getpwuid') ? posix_getpwuid(fileowner(\OC::$configDir . 'config.php'))['name'] : '', // to not explode here because of posix extension not being disabled - which is already checked in the line above
+ ],
+ ''
+ );
+
+ $this->assertEquals($expected, $this->admin->getForm());
+ }
+
+ public function testGetSection() {
+ $this->assertSame('server', $this->admin->getSection());
+ }
+
+ public function testGetPriority() {
+ $this->assertSame(0, $this->admin->getPriority());
+ }
+}
diff --git a/apps/settings/tests/Settings/Admin/SharingTest.php b/apps/settings/tests/Settings/Admin/SharingTest.php
new file mode 100644
index 00000000000..91b2edf14b1
--- /dev/null
+++ b/apps/settings/tests/Settings/Admin/SharingTest.php
@@ -0,0 +1,271 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @author Lukas Reschke <lukas@statuscode.ch>
+ *
+ * @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\Settings\Tests\Settings\Admin;
+
+use OCA\Settings\Admin\Sharing;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\Constants;
+use OCP\IConfig;
+use OCP\IL10N;
+use OCP\L10N\IFactory;
+use OCP\Share\IManager;
+use Test\TestCase;
+
+class SharingTest extends TestCase {
+ /** @var Sharing */
+ private $admin;
+ /** @var IConfig */
+ private $config;
+ /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
+ private $l10n;
+ /** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $shareManager;
+
+ public function setUp() {
+ parent::setUp();
+ $this->config = $this->getMockBuilder(IConfig::class)->getMock();
+ $this->l10n = $this->getMockBuilder(IL10N::class)->getMock();
+
+ $l10Factory = $this->createMock(IFactory::class);
+ $l10Factory->method('get')
+ ->willReturn($this->l10n);
+
+ $this->shareManager = $this->getMockBuilder(IManager::class)->getMock();
+
+ $this->admin = new Sharing(
+ $this->config,
+ $l10Factory,
+ $this->shareManager
+ );
+ }
+
+ public function testGetFormWithoutExcludedGroups() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_exclude_groups_list', '')
+ ->willReturn('');
+ $this->config
+ ->expects($this->at(1))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_group_sharing', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(2))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_links', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(3))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_public_upload', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(4))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_resharing', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(5))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(6))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_enabled', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(7))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_default_expire_date', 'no')
+ ->willReturn('no');
+ $this->config
+ ->expects($this->at(8))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_expire_after_n_days', '7')
+ ->willReturn('7');
+ $this->config
+ ->expects($this->at(9))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_enforce_expire_date', 'no')
+ ->willReturn('no');
+ $this->config
+ ->expects($this->at(10))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_exclude_groups', 'no')
+ ->willReturn('no');
+ $this->config
+ ->expects($this->at(11))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_public_link_disclaimertext', null)
+ ->willReturn('Lorem ipsum');
+ $this->config
+ ->expects($this->at(12))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_enable_link_password_by_default', 'no')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(13))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL)
+ ->willReturn(Constants::PERMISSION_ALL);
+
+ $expected = new TemplateResponse(
+ 'settings',
+ 'settings/admin/sharing',
+ [
+ 'allowGroupSharing' => 'yes',
+ 'allowLinks' => 'yes',
+ 'allowPublicUpload' => 'yes',
+ 'allowResharing' => 'yes',
+ 'allowShareDialogUserEnumeration' => 'yes',
+ 'enforceLinkPassword' => false,
+ 'onlyShareWithGroupMembers' => false,
+ 'shareAPIEnabled' => 'yes',
+ 'shareDefaultExpireDateSet' => 'no',
+ 'shareExpireAfterNDays' => '7',
+ 'shareEnforceExpireDate' => 'no',
+ 'shareExcludeGroups' => false,
+ 'shareExcludedGroupsList' => '',
+ 'publicShareDisclaimerText' => 'Lorem ipsum',
+ 'enableLinkPasswordByDefault' => 'yes',
+ 'shareApiDefaultPermissions' => Constants::PERMISSION_ALL,
+ 'shareApiDefaultPermissionsCheckboxes' => $this->invokePrivate($this->admin, 'getSharePermissionList', [])
+ ],
+ ''
+ );
+
+ $this->assertEquals($expected, $this->admin->getForm());
+ }
+
+ public function testGetFormWithExcludedGroups() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_exclude_groups_list', '')
+ ->willReturn('["NoSharers","OtherNoSharers"]');
+ $this->config
+ ->expects($this->at(1))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_group_sharing', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(2))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_links', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(3))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_public_upload', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(4))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_resharing', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(5))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(6))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_enabled', 'yes')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(7))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_default_expire_date', 'no')
+ ->willReturn('no');
+ $this->config
+ ->expects($this->at(8))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_expire_after_n_days', '7')
+ ->willReturn('7');
+ $this->config
+ ->expects($this->at(9))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_enforce_expire_date', 'no')
+ ->willReturn('no');
+ $this->config
+ ->expects($this->at(10))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_exclude_groups', 'no')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(11))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_public_link_disclaimertext', null)
+ ->willReturn('Lorem ipsum');
+ $this->config
+ ->expects($this->at(12))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_enable_link_password_by_default', 'no')
+ ->willReturn('yes');
+ $this->config
+ ->expects($this->at(13))
+ ->method('getAppValue')
+ ->with('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL)
+ ->willReturn(Constants::PERMISSION_ALL);
+
+
+ $expected = new TemplateResponse(
+ 'settings',
+ 'settings/admin/sharing',
+ [
+ 'allowGroupSharing' => 'yes',
+ 'allowLinks' => 'yes',
+ 'allowPublicUpload' => 'yes',
+ 'allowResharing' => 'yes',
+ 'allowShareDialogUserEnumeration' => 'yes',
+ 'enforceLinkPassword' => false,
+ 'onlyShareWithGroupMembers' => false,
+ 'shareAPIEnabled' => 'yes',
+ 'shareDefaultExpireDateSet' => 'no',
+ 'shareExpireAfterNDays' => '7',
+ 'shareEnforceExpireDate' => 'no',
+ 'shareExcludeGroups' => true,
+ 'shareExcludedGroupsList' => 'NoSharers|OtherNoSharers',
+ 'publicShareDisclaimerText' => 'Lorem ipsum',
+ 'enableLinkPasswordByDefault' => 'yes',
+ 'shareApiDefaultPermissions' => Constants::PERMISSION_ALL,
+ 'shareApiDefaultPermissionsCheckboxes' => $this->invokePrivate($this->admin, 'getSharePermissionList', [])
+ ],
+ ''
+ );
+
+ $this->assertEquals($expected, $this->admin->getForm());
+ }
+
+ public function testGetSection() {
+ $this->assertSame('sharing', $this->admin->getSection());
+ }
+
+ public function testGetPriority() {
+ $this->assertSame(0, $this->admin->getPriority());
+ }
+}
diff --git a/apps/settings/tests/Settings/Personal/SecurityTest.php b/apps/settings/tests/Settings/Personal/SecurityTest.php
new file mode 100644
index 00000000000..ee72ca00384
--- /dev/null
+++ b/apps/settings/tests/Settings/Personal/SecurityTest.php
@@ -0,0 +1,119 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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\Settings\Tests\Settings\Personal;
+
+use OC\Authentication\TwoFactorAuth\ProviderLoader;
+use OCP\IInitialStateService;
+use OCA\Settings\Personal\Security;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class SecurityTest extends TestCase {
+
+ /** @var IInitialStateService|MockObject */
+ private $initialStateService;
+
+ /** @var IUserManager|MockObject */
+ private $userManager;
+
+ /** @var ProviderLoader|MockObject */
+ private $providerLoader;
+
+ /** @var IUserSession|MockObject */
+ private $userSession;
+
+ /** @var IConfig|MockObject */
+ private $config;
+
+ /** @var string */
+ private $uid;
+
+ /** @var Security */
+ private $section;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->initialStateService = $this->createMock(IInitialStateService::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->providerLoader = $this->createMock(ProviderLoader::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->uid = 'test123';
+
+ $this->section = new Security(
+ $this->initialStateService,
+ $this->userManager,
+ $this->providerLoader,
+ $this->userSession,
+ $this->config,
+ $this->uid
+ );
+ }
+
+ public function testGetForm() {
+ $user = $this->createMock(IUser::class);
+ $this->userManager->expects($this->once())
+ ->method('get')
+ ->with($this->uid)
+ ->willReturn($user);
+ $user->expects($this->once())
+ ->method('canChangePassword')
+ ->willReturn(true);
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn($user);
+ $this->providerLoader->expects($this->once())
+ ->method('getProviders')
+ ->with($user)
+ ->willReturn([]);
+ $this->config->expects($this->once())
+ ->method('getUserValue')
+ ->with(
+ $this->uid,
+ 'accessibility',
+ 'theme',
+ false
+ )
+ ->willReturn(false);
+
+ $form = $this->section->getForm();
+
+ $expected = new TemplateResponse('settings', 'settings/personal/security', [
+ 'passwordChangeSupported' => true,
+ 'twoFactorProviderData' => [
+ 'providers' => [],
+ ],
+ 'themedark' => false,
+ ]);
+ $this->assertEquals($expected, $form);
+ }
+
+}