diff options
24 files changed, 730 insertions, 37 deletions
diff --git a/appinfo/routes.php b/appinfo/routes.php index 678482081..0bcdb712c 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -96,11 +96,12 @@ $app->registerRoutes($this, ], ], 'resources' => [ - 'autoComplete' => ['url' => '/api/autoComplete'], - 'localAttachments' => ['url' => '/api/attachments'], 'accounts' => ['url' => '/api/accounts'], + 'aliases' => ['url' => '/api/accounts/{accountId}/aliases'], + 'autoComplete' => ['url' => '/api/autoComplete'], 'folders' => ['url' => '/api/accounts/{accountId}/folders'], + 'localAttachments' => ['url' => '/api/attachments'], 'messages' => ['url' => '/api/accounts/{accountId}/folders/{folderId}/messages'], - 'aliases' => ['url' => '/api/accounts/{accountId}/aliases'], + 'preferences' => ['url' => '/api/preferences'], ] ]); @@ -42,26 +42,33 @@ define(function(require) { require('service/accountservice'); require('service/aliasesservice'); require('service/attachmentservice'); + require('service/backgroundsyncservice'); require('service/davservice'); require('service/folderservice'); require('service/foldersyncservice'); require('service/messageservice'); - require('service/backgroundsyncservice'); + require('service/preferenceservice'); require('util/notificationhandler'); var Mail = Marionette.Application.extend({ + _useExternalAvatars: false, + + getUseExternalAvatars: function() { + return this._useExternalAvatars; + }, + /** * Register the mailto protocol handler */ registerProtocolHandler: function() { if (window.navigator.registerProtocolHandler) { var url = window.location.protocol + '//' + - window.location.host + - OC.generateUrl('apps/mail/compose?uri=%s'); + window.location.host + + OC.generateUrl('apps/mail/compose?uri=%s'); try { window.navigator - .registerProtocolHandler('mailto', url, OC.theme.name + ' Mail'); + .registerProtocolHandler('mailto', url, OC.theme.name + ' Mail'); } catch (e) { } } @@ -91,6 +98,8 @@ define(function(require) { Mail = new Mail(); Mail.on('start', function() { + this._useExternalAvatars = $('#external-avatars').val() === 'true'; + this.view = new AppView(); Cache.init(); diff --git a/js/radio.js b/js/radio.js index c26b06a1a..ff1592fef 100644 --- a/js/radio.js +++ b/js/radio.js @@ -24,6 +24,7 @@ define(function(require) { 'message', 'navigation', 'notification', + 'preference', 'state', 'sync', 'ui' diff --git a/js/service/preferenceservice.js b/js/service/preferenceservice.js new file mode 100644 index 000000000..a73c18091 --- /dev/null +++ b/js/service/preferenceservice.js @@ -0,0 +1,74 @@ +/* global Promise */ + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 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/>. + * + */ + +define(function(require) { + 'use strict'; + + var $ = require('jquery'); + var OC = require('OC'); + var Radio = require('radio'); + + Radio.preference.reply('save', savePreference); + Radio.preference.reply('get', savePreference); + + function savePreference(key, value) { + var url = OC.generateUrl('/apps/mail/api/preferences/{key}', { + key: key + }); + + return new Promise(function(resolve, reject) { + return $.ajax(url, { + method: 'PUT', + data: { + key: key, + value: value + }, + success: resolve, + error: reject + }); + }).then(function(data) { + return data.value; + }); + } + + function getPreference(key) { + var url = OC.generateUrl('/apps/mail/api/preferences/{key}', { + key: key + }); + + return new Promise(function(resolve, reject) { + return $.ajax(url, { + success: resolve, + error: reject + }); + }).then(function(data) { + return data.value; + }); + } + + return { + savePreference: savePreference, + getPreference: getPreference + }; +}); diff --git a/js/templates/settings.html b/js/templates/settings.html index fb6f9a51c..e46c639fa 100644 --- a/js/templates/settings.html +++ b/js/templates/settings.html @@ -6,11 +6,20 @@ class="button new-button" href="{{addAccountUrl}}">{{ t 'Add mail account' }}</a> - <p class="app-settings-hint"> - <a id="keyboard-shortcuts" - href="{{keyboardShortcutUrl}}">{{ t 'Keyboard shortcuts' }}</a></p> + <p> + <input class="checkbox" + id="gravatar-enabled" + {{#if useExternalAvatars}}checked="checked"{{/if}} + type="checkbox"> + <label for="gravatar-enabled">{{ t 'Use Gravatar and favicon avatars' }}</label> + </p> <p class="app-settings-hint"> - {{{ t 'Looking to encrypt your emails? Install the <a href="https://www.mailvelope.com/" target="_blank">Mailvelope browser extension</a>!' }}} - </p> -</div>
\ No newline at end of file + <a id="keyboard-shortcuts" + href="{{keyboardShortcutUrl}}">{{ t 'Keyboard shortcuts' }}</a> + </p> + + <p class="app-settings-hint"> + {{{ t 'Looking to encrypt your emails? Install the <a href="https://www.mailvelope.com/" target="_blank">Mailvelope browser extension</a>!' }}} + </p> + </div> diff --git a/js/tests/service/preferenceservice_spec.js b/js/tests/service/preferenceservice_spec.js new file mode 100644 index 000000000..d982b1af7 --- /dev/null +++ b/js/tests/service/preferenceservice_spec.js @@ -0,0 +1,92 @@ +/* global sinon, expect */ + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 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/>. + * + */ + +define([ + 'service/preferenceservice' +], function(PreferenceService) { + 'use strict'; + + describe('PreferenceService', function() { + var server; + + beforeEach(function() { + server = sinon.fakeServer.create(); + }); + + afterEach(function() { + server.restore(); + }); + + it('retrieves a preference from the back-end', function(done) { + var retrieving = PreferenceService.getPreference('test'); + + expect(server.requests.length).toBe(1); + server.requests[0].respond( + 200, + { + 'Content-Type': 'application/json' + }, + JSON.stringify({ + value: '123' + }) + ); + + retrieving.then(function(value) { + expect(value).toBe('123'); + + done(); + }).catch(done.fail); + }); + + it('retrieves an error from the back-end', function(done) { + var retrieving = PreferenceService.getPreference('test'); + + expect(server.requests.length).toBe(1); + server.requests[0].respond(500, null, null); + + retrieving.then(done.fail).catch(done); + }); + + it('stores a preference on the back-end', function(done) { + var storing = PreferenceService.savePreference('test', '123'); + + expect(server.requests.length).toBe(1); + server.requests[0].respond( + 200, + { + 'Content-Type': 'application/json' + }, + JSON.stringify({ + value: '123' + }) + ); + + storing.then(function(value) { + expect(value).toBe('123'); + + done(); + }).catch(done.fail); + }); + }); +}); diff --git a/js/views/settings.js b/js/views/settings.js index ec15056fc..12eca1e21 100644 --- a/js/views/settings.js +++ b/js/views/settings.js @@ -17,28 +17,44 @@ define(function(require) { var SettingsTemplate = require('templates/settings.html'); return Marionette.View.extend({ + accounts: null, + template: SettingsTemplate, + templateContext: function() { + var app = require('app'); return { addAccountUrl: OC.generateUrl('apps/mail/#setup'), + useExternalAvatars: app.getUseExternalAvatars(), keyboardShortcutUrl: OC.generateUrl('apps/mail/#shortcuts') }; }, + regions: { accountsList: '#settings-accounts' }, + events: { 'click #new-mail-account': 'addAccount', + 'change #gravatar-enabled': 'toggleExternalAvatars', 'click #keyboard-shortcuts': 'showKeyboardShortcuts' }, + addAccount: function(e) { e.preventDefault(); Radio.navigation.trigger('setup'); }, + + toggleExternalAvatars: function() { + var enabled = this.$('#gravatar-enabled').attr('checked') === 'checked'; + Radio.preference.request('save', 'external-avatars', enabled ? 'true' : 'false'); + }, + showKeyboardShortcuts: function(e) { e.preventDefault(); Radio.navigation.trigger('keyboardshortcuts'); } + }); }); diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 3ef9e3d81..15229fab6 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -26,10 +26,12 @@ use OCA\Mail\Contracts\IAttachmentService; use OCA\Mail\Contracts\IAvatarService; use OCA\Mail\Contracts\IMailManager; use OCA\Mail\Contracts\IMailTransmission; +use OCA\Mail\Contracts\IUserPreferences; use OCA\Mail\Service\Attachment\AttachmentService; use OCA\Mail\Service\AvatarService; use OCA\Mail\Service\MailManager; use OCA\Mail\Service\MailTransmission; +use OCA\Mail\Service\UserPreferenceSevice; use OCP\AppFramework\App; use OCP\Util; @@ -48,9 +50,10 @@ class Application extends App { $testSmtp = $transport === 'smtp'; $container->registerAlias(IAvatarService::class, AvatarService::class); - $container->registerAlias(IMailManager::class, MailManager::class); $container->registerAlias(IAttachmentService::class, AttachmentService::class); + $container->registerAlias(IMailManager::class, MailManager::class); $container->registerAlias(IMailTransmission::class, MailTransmission::class); + $container->registerAlias(IUserPreferences::class, UserPreferenceSevice::class); $container->registerService('OCP\ISession', function ($c) { return $c->getServer()->getSession(); }); diff --git a/lib/Contracts/IUserPreferences.php b/lib/Contracts/IUserPreferences.php new file mode 100644 index 000000000..55b0d93af --- /dev/null +++ b/lib/Contracts/IUserPreferences.php @@ -0,0 +1,40 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 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\Mail\Contracts; + +interface IUserPreferences { + + /** + * @param string $key + * @param mixed $value + */ + public function setPreference($key, $value); + + /** + * @param string $key + * @param mixed|null $default + */ + public function getPreference($key, $default = null); +} diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 086a5f164..10b2fea2a 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -24,6 +24,7 @@ namespace OCA\Mail\Controller; +use OCA\Mail\Contracts\IUserPreferences; use OCA\Mail\Service\AccountService; use OCA\Mail\Service\AliasesService; use OCP\AppFramework\Controller; @@ -55,6 +56,9 @@ class PageController extends Controller { /** @var IUserSession */ private $userSession; + /** @var IUserPreferences */ + private $preferences; + /** * @param string $appName * @param IRequest $request @@ -63,8 +67,12 @@ class PageController extends Controller { * @param AccountService $accountService * @param AliasesService $aliasesService * @param string $UserId + * @param IUserPreferences */ - public function __construct($appName, IRequest $request, IURLGenerator $urlGenerator, IConfig $config, AccountService $accountService, AliasesService $aliasesService, $UserId, IUserSession $userSession) { + public function __construct($appName, IRequest $request, + IURLGenerator $urlGenerator, IConfig $config, AccountService $accountService, + AliasesService $aliasesService, $UserId, IUserSession $userSession, + IUserPreferences $preferences) { parent::__construct($appName, $request); $this->urlGenerator = $urlGenerator; $this->config = $config; @@ -72,6 +80,7 @@ class PageController extends Controller { $this->aliasesService = $aliasesService; $this->currentUserId = $UserId; $this->userSession = $userSession; + $this->preferences = $preferences; } /** @@ -86,17 +95,21 @@ class PageController extends Controller { $accountsJson = []; foreach ($mailAccounts as $mailAccount) { $json = $mailAccount->jsonSerialize(); - $json['aliases'] = $this->aliasesService->findAll($mailAccount->getId(), $this->currentUserId); + $json['aliases'] = $this->aliasesService->findAll($mailAccount->getId(), + $this->currentUserId); $accountsJson[] = $json; } $user = $this->userSession->getUser(); - $response = new TemplateResponse($this->appName, 'index', [ + $response = new TemplateResponse($this->appName, 'index', + [ 'debug' => $this->config->getSystemValue('debug', false), 'app-version' => $this->config->getAppValue('mail', 'installed_version'), 'accounts' => base64_encode(json_encode($accountsJson)), + 'external-avatars' => $this->preferences->getPreference('external-avatars', 'true'), 'prefill_displayName' => $user->getDisplayName(), - 'prefill_email' => $this->config->getUserValue($user->getUID(), 'settings', 'email', ''), + 'prefill_email' => $this->config->getUserValue($user->getUID(), 'settings', + 'email', ''), ]); $csp = new ContentSecurityPolicy(); @@ -124,7 +137,8 @@ class PageController extends Controller { } } - array_walk($params, function (&$value, $key) { + array_walk($params, + function (&$value, $key) { $value = "$key=" . urlencode($value); }); diff --git a/lib/Controller/PreferencesController.php b/lib/Controller/PreferencesController.php new file mode 100644 index 000000000..cdaa28bcc --- /dev/null +++ b/lib/Controller/PreferencesController.php @@ -0,0 +1,76 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 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\Mail\Controller; + +use OCA\Mail\Contracts\IUserPreferences; +use OCA\Mail\Http\JSONResponse; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\IRequest; + +class PreferencesController extends Controller { + + /** @var IUserPreferences */ + private $userPreference; + + /** + * @param IRequest $request + * @param IUserPreferences $userPreference + */ + public function __construct(IRequest $request, IUserPreferences $userPreference) { + parent::__construct('mail', $request); + $this->userPreference = $userPreference; + } + + /** + * @NoAdminRequired + * + * @param string $id + * @return JSONResponse + */ + public function show($id) { + return new JSONResponse([ + 'value' => $this->userPreference->getPreference($id) + ]); + } + + /** + * @NoAdminRequired + * + * @param string $key + * @param string $value + * @return JSONResponse + */ + public function update($key, $value) { + if (is_null($key) || is_null($value)) { + return new JSONResponse(null, Http::STATUS_BAD_REQUEST); + } + + $this->userPreference->setPreference($key, $value); + + return new JSONResponse(); + } + +} diff --git a/lib/Service/Avatar/AddressbookSource.php b/lib/Service/Avatar/AddressbookSource.php index 44b920f92..b65cc69c6 100644 --- a/lib/Service/Avatar/AddressbookSource.php +++ b/lib/Service/Avatar/AddressbookSource.php @@ -41,6 +41,15 @@ class AddressbookSource implements IAvatarSource { } /** + * Does this source query external services? + * + * @return bool + */ + public function isExternal() { + return false; + } + + /** * @param string $email sender email address * @param AvatarFactory $factory * @return Avatar|null avatar URL if one can be found diff --git a/lib/Service/Avatar/CompositeAvatarSource.php b/lib/Service/Avatar/CompositeAvatarSource.php index 344e63c77..46e2b576f 100644 --- a/lib/Service/Avatar/CompositeAvatarSource.php +++ b/lib/Service/Avatar/CompositeAvatarSource.php @@ -27,7 +27,7 @@ namespace OCA\Mail\Service\Avatar; /** * Composition of all avatar sources for easier usage */ -class CompositeAvatarSource implements IAvatarSource { +class CompositeAvatarSource { /** @var IAvatarSource[] */ private $sources; @@ -49,10 +49,16 @@ class CompositeAvatarSource implements IAvatarSource { /** * @param string $email sender email address * @param AvatarFactory $factory + * @param bool $queryExternal * @return Avatar|null avatar URL if one can be found */ - public function fetch($email, AvatarFactory $factory) { + public function fetch($email, AvatarFactory $factory, $queryExternal) { foreach ($this->sources as $source) { + if (!$queryExternal && $source->isExternal()) { + // Skip this one + continue; + } + $avatar = $source->fetch($email, $factory); if (is_null($avatar)) { diff --git a/lib/Service/Avatar/FaviconSource.php b/lib/Service/Avatar/FaviconSource.php index 9861592dd..f5b02302a 100644 --- a/lib/Service/Avatar/FaviconSource.php +++ b/lib/Service/Avatar/FaviconSource.php @@ -50,6 +50,15 @@ class FaviconSource implements IAvatarSource { } /** + * Does this source query external services? + * + * @return bool + */ + public function isExternal() { + return true; + } + + /** * @param string $email sender email address * @param AvatarFactory $factory * @return Avatar|null avatar URL if one can be found diff --git a/lib/Service/Avatar/GravatarSource.php b/lib/Service/Avatar/GravatarSource.php index 1c4132597..a22ad13bc 100644 --- a/lib/Service/Avatar/GravatarSource.php +++ b/lib/Service/Avatar/GravatarSource.php @@ -39,6 +39,15 @@ class GravatarSource implements IAvatarSource { } /** + * Does this source query external services? + * + * @return bool + */ + public function isExternal() { + return true; + } + + /** * @param string $email sender email address * @param AvatarFactory $factory * @return Avatar|null avatar URL if one can be found diff --git a/lib/Service/Avatar/IAvatarSource.php b/lib/Service/Avatar/IAvatarSource.php index 4be65d597..98e1930f7 100644 --- a/lib/Service/Avatar/IAvatarSource.php +++ b/lib/Service/Avatar/IAvatarSource.php @@ -24,11 +24,16 @@ namespace OCA\Mail\Service\Avatar; -use OCP\Files\IMimeTypeDetector; - interface IAvatarSource { /** + * Does this source query external services? + * + * @return bool + */ + public function isExternal(); + + /** * @param string $email sender email address * @param AvatarFactory $factory * @return Avatar|null avatar URL if one can be found diff --git a/lib/Service/AvatarService.php b/lib/Service/AvatarService.php index d3d5656fc..f9236a879 100644 --- a/lib/Service/AvatarService.php +++ b/lib/Service/AvatarService.php @@ -22,12 +22,12 @@ namespace OCA\Mail\Service; use OCA\Mail\Contracts\IAvatarService; +use OCA\Mail\Contracts\IUserPreferences; use OCA\Mail\Service\Avatar\Avatar; use OCA\Mail\Service\Avatar\AvatarFactory; use OCA\Mail\Service\Avatar\Cache as AvatarCache; use OCA\Mail\Service\Avatar\CompositeAvatarSource; use OCA\Mail\Service\Avatar\Downloader; -use OCA\Mail\Service\Avatar\IAvatarSource; use OCP\IURLGenerator; class AvatarService implements IAvatarService { @@ -38,7 +38,7 @@ class AvatarService implements IAvatarService { /** @var Downloader */ private $downloader; - /** @var IAvatarSource */ + /** @var CompositeAvatarSource */ private $source; /** @var IURLGenerator */ @@ -47,19 +47,33 @@ class AvatarService implements IAvatarService { /** @var AvatarFactory */ private $avatarFactory; + /** @var IUserPreferences */ + private $preferences; + /** * @param CompositeAvatarSource $source * @param Downloader $downloader * @param AvatarCache $cache * @param IURLGenerator $urlGenerator * @param AvatarFactory $avatarFactory + * @param IUserPreferences $preferences */ - public function __construct(CompositeAvatarSource $source, Downloader $downloader, AvatarCache $cache, IURLGenerator $urlGenerator, AvatarFactory $avatarFactory) { + public function __construct(CompositeAvatarSource $source, + Downloader $downloader, AvatarCache $cache, IURLGenerator $urlGenerator, + AvatarFactory $avatarFactory, IUserPreferences $preferences) { $this->source = $source; $this->cache = $cache; $this->urlGenerator = $urlGenerator; $this->downloader = $downloader; $this->avatarFactory = $avatarFactory; + $this->preferences = $preferences; + } + + /** + * @return bool + */ + private function externalAvatarsAllowed() { + return $this->preferences->getPreference('external-avatars', 'true') === 'true'; } /** @@ -69,7 +83,8 @@ class AvatarService implements IAvatarService { if ($avatar->isExternal()) { $mime = $avatar->getMime(); - return in_array($mime, [ + return in_array($mime, + [ 'image/jpeg', 'image/png', 'image/x-icon', @@ -91,7 +106,7 @@ class AvatarService implements IAvatarService { return $cachedAvatar; } - $avatar = $this->source->fetch($email, $this->avatarFactory); + $avatar = $this->source->fetch($email, $this->avatarFactory, $this->externalAvatarsAllowed()); if (is_null($avatar) || !$this->hasAllowedMime($avatar)) { // Cannot locate any avatar -> nothing to do here return null; diff --git a/lib/Service/UserPreferenceSevice.php b/lib/Service/UserPreferenceSevice.php new file mode 100644 index 000000000..5f45c8438 --- /dev/null +++ b/lib/Service/UserPreferenceSevice.php @@ -0,0 +1,63 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 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\Mail\Service; + +use OCA\Mail\Contracts\IUserPreferences; +use OCP\IConfig; + +class UserPreferenceSevice implements IUserPreferences { + + /** @var IConfig */ + private $config; + + /** @var string */ + private $UserId; + + /** + * @param IConfig $config + * @param string $UserId + */ + public function __construct(IConfig $config, $UserId) { + $this->UserId = $UserId; + $this->config = $config; + } + + /** + * @param string $key + * @param mixed $value + */ + public function setPreference($key, $value) { + $this->config->setUserValue($this->UserId, 'mail', $key, $value); + } + + /** + * @param string $key + * @param mixed|null $default + */ + public function getPreference($key, $default = null) { + return $this->config->getUserValue($this->UserId, 'mail', $key, $default); + } + +} diff --git a/templates/index.php b/templates/index.php index 0e78e1236..0ca81710a 100644 --- a/templates/index.php +++ b/templates/index.php @@ -31,6 +31,7 @@ script('mail', 'build/build'); <input type="hidden" id="config-installed-version" value="<?php p($_['app-version']); ?>"> <input type="hidden" id="serialized-accounts" value="<?php p($_['accounts']); ?>"> +<input type="hidden" id="external-avatars" value="<?php p($_['external-avatars']); ?>"> <div id="user-displayname" style="display: none"><?php p($_['prefill_displayName']); ?></div> diff --git a/tests/Controller/PageControllerTest.php b/tests/Controller/PageControllerTest.php index 1d0ffca8e..468a6c5f4 100644 --- a/tests/Controller/PageControllerTest.php +++ b/tests/Controller/PageControllerTest.php @@ -21,6 +21,7 @@ namespace OCA\Mail\Tests\Controller; +use OCA\Mail\Contracts\IUserPreferences; use OCA\Mail\Controller\PageController; use OCA\Mail\Service\AccountService; use OCA\Mail\Service\AliasesService; @@ -62,6 +63,9 @@ class PageControllerTest extends PHPUnit_Framework_TestCase { /** @var IUserSession|PHPUnit_Framework_MockObject_MockObject */ private $userSession; + /** @var IUserPreferences|PHPUnit_Framework_MockObject_MockObject */ + private $preferences; + /** @var PageController */ private $controller; @@ -76,13 +80,21 @@ class PageControllerTest extends PHPUnit_Framework_TestCase { $this->accountService = $this->createMock(AccountService::class); $this->aliasesService = $this->createMock(AliasesService::class); $this->userSession = $this->createMock(IUserSession::class); - $this->controller = new PageController($this->appName, $this->request, $this->urlGenerator, $this->config, $this->accountService, $this->aliasesService, $this->userId, $this->userSession); + $this->preferences = $this->createMock(IUserPreferences::class); + + $this->controller = new PageController($this->appName, $this->request, + $this->urlGenerator, $this->config, $this->accountService, + $this->aliasesService, $this->userId, $this->userSession, $this->preferences); } public function testIndex() { $account1 = $this->createMock(IAccount::class); $account2 = $this->createMock(IAccount::class); + $this->preferences->expects($this->once()) + ->method('getPreference') + ->with('external-avatars', 'true') + ->willReturn('true'); $this->accountService->expects($this->once()) ->method('findByUserId') ->with($this->userId) @@ -149,11 +161,14 @@ class PageControllerTest extends PHPUnit_Framework_TestCase { ->will($this->returnValue('jane')); $this->config->expects($this->once()) ->method('getUserValue') - ->with($this->equalTo('jane'), $this->equalTo('settings'), $this->equalTo('email'), $this->equalTo('')) + ->with($this->equalTo('jane'), $this->equalTo('settings'), + $this->equalTo('email'), $this->equalTo('')) ->will($this->returnValue('jane@doe.cz')); - $expected = new TemplateResponse($this->appName, 'index', [ + $expected = new TemplateResponse($this->appName, 'index', + [ 'debug' => true, + 'external-avatars' => 'true', 'app-version' => '1.2.3', 'accounts' => base64_encode(json_encode($accountsJson)), 'prefill_displayName' => 'Jane Doe', diff --git a/tests/Controller/PreferencesControllerTest.php b/tests/Controller/PreferencesControllerTest.php new file mode 100644 index 000000000..a8bd9845c --- /dev/null +++ b/tests/Controller/PreferencesControllerTest.php @@ -0,0 +1,74 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 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\Mail\Tests\Controller; + +use OCA\Mail\Contracts\IUserPreferences; +use OCA\Mail\Controller\PreferencesController; +use OCA\Mail\Http\JSONResponse; +use OCA\Mail\Tests\TestCase; +use OCP\IRequest; +use PHPUnit_Framework_MockObject_MockObject; + +class PreferencesControllerTest extends TestCase { + + /** @var IUserPreferences|PHPUnit_Framework_MockObject_MockObject */ + private $preferences; + + /** @var PreferencesController */ + private $controller; + + protected function setUp() { + parent::setUp(); + + $request = $this->createMock(IRequest::class); + $this->preferences = $this->createMock(IUserPreferences::class); + + $this->controller = new PreferencesController($request, $this->preferences); + } + + public function testGetPreference() { + $this->preferences->expects($this->once()) + ->method('getPreference') + ->with('test') + ->willReturn(123); + $expected = new JSONResponse(['value' => 123]); + + $actual = $this->controller->show('test'); + + $this->assertEquals($expected, $actual); + } + + public function testSetPreference() { + $this->preferences->expects($this->once()) + ->method('setPreference') + ->with('test'); + $expected = new JSONResponse(); + + $actual = $this->controller->update('test', 123); + + $this->assertEquals($expected, $actual); + } + +} diff --git a/tests/Service/Avatar/CompositeAvatarSourceTest.php b/tests/Service/Avatar/CompositeAvatarSourceTest.php index e3511c5ee..37088b20d 100644 --- a/tests/Service/Avatar/CompositeAvatarSourceTest.php +++ b/tests/Service/Avatar/CompositeAvatarSourceTest.php @@ -60,20 +60,59 @@ class CompositeAvatarSourceTest extends TestCase { public function testFetchNoneFound() { $email = 'jane@doe.com'; $avatarFactory = $this->createMock(AvatarFactory::class); + $this->addressbookSource->expects($this->any()) + ->method('isExternal') + ->willReturn(false); $this->addressbookSource->expects($this->once()) ->method('fetch') ->with($email, $avatarFactory) ->willReturn(null); + $this->gravatarSource->expects($this->any()) + ->method('isExternal') + ->willReturn(true); $this->gravatarSource->expects($this->once()) ->method('fetch') ->with($email, $avatarFactory) ->willReturn(null); + $this->faviconSource->expects($this->any()) + ->method('isExternal') + ->willReturn(true); $this->faviconSource->expects($this->once()) ->method('fetch') ->with($email, $avatarFactory) ->willReturn(null); - $actualAvatar = $this->source->fetch($email, $avatarFactory); + $actualAvatar = $this->source->fetch($email, $avatarFactory, true); + + $this->assertNull($actualAvatar); + } + + public function testFetchNoneFoundQueryOnlyInternal() { + $email = 'jane@doe.com'; + $avatarFactory = $this->createMock(AvatarFactory::class); + $this->addressbookSource->expects($this->once()) + ->method('isExternal') + ->willReturn(false); + $this->addressbookSource->expects($this->once()) + ->method('fetch') + ->with($email, $avatarFactory) + ->willReturn(null); + $this->gravatarSource->expects($this->once()) + ->method('isExternal') + ->willReturn(true); + $this->gravatarSource->expects($this->never()) + ->method('fetch') + ->with($email, $avatarFactory) + ->willReturn(null); + $this->faviconSource->expects($this->once()) + ->method('isExternal') + ->willReturn(true); + $this->faviconSource->expects($this->never()) + ->method('fetch') + ->with($email, $avatarFactory) + ->willReturn(null); + + $actualAvatar = $this->source->fetch($email, $avatarFactory, false); $this->assertNull($actualAvatar); } @@ -91,7 +130,7 @@ class CompositeAvatarSourceTest extends TestCase { ->with($email, $avatarFactory) ->willReturn($avatar); - $actualAvatar = $this->source->fetch($email, $avatarFactory); + $actualAvatar = $this->source->fetch($email, $avatarFactory, true); $this->assertEquals($avatar, $actualAvatar); } diff --git a/tests/Service/AvatarServiceTest.php b/tests/Service/AvatarServiceTest.php index 6a642d628..348efe287 100644 --- a/tests/Service/AvatarServiceTest.php +++ b/tests/Service/AvatarServiceTest.php @@ -24,6 +24,7 @@ namespace OCA\Mail\Tests\Service; +use OCA\Mail\Contracts\IUserPreferences; use OCA\Mail\Service\Avatar\Avatar; use OCA\Mail\Service\Avatar\AvatarFactory; use OCA\Mail\Service\Avatar\Cache; @@ -54,6 +55,9 @@ class AvatarServiceTest extends TestCase { /** @var AvatarFactory|PHPUnit_Framework_MockObject_MockObject */ private $avatarFactory; + /** @var IUserPreferences */ + private $preferences; + /** @var AvatarService */ private $avatarService; @@ -65,8 +69,10 @@ class AvatarServiceTest extends TestCase { $this->cache = $this->createMock(Cache::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->avatarFactory = $this->createMock(AvatarFactory::class); + $this->preferences = $this->createMock(IUserPreferences::class); - $this->avatarService = new AvatarService($this->source, $this->downloader, $this->cache, $this->urlGenerator, $this->avatarFactory); + $this->avatarService = new AvatarService($this->source, $this->downloader, + $this->cache, $this->urlGenerator, $this->avatarFactory, $this->preferences); } public function testGetCachedAvatarUrl() { @@ -85,13 +91,17 @@ class AvatarServiceTest extends TestCase { public function testGetAvatarNoAvatarFound() { $email = 'jane@doe.com'; $uid = 'john'; + $this->preferences->expects($this->once()) + ->method('getPreference') + ->with('external-avatars', 'true') + ->willReturn('true'); $this->cache->expects($this->once()) ->method('get') ->with($email) ->willReturn(null); $this->source->expects($this->once()) ->method('fetch') - ->with($email, $this->avatarFactory) + ->with($email, $this->avatarFactory, true) ->willReturn(null); $this->cache->expects($this->never()) ->method('add'); @@ -104,6 +114,10 @@ class AvatarServiceTest extends TestCase { public function testGetAvatarMimeNotAllowed() { $email = 'jane@doe.com'; $uid = 'john'; + $this->preferences->expects($this->once()) + ->method('getPreference') + ->with('external-avatars', 'true') + ->willReturn('true'); $this->cache->expects($this->once()) ->method('get') ->with($email) @@ -111,7 +125,7 @@ class AvatarServiceTest extends TestCase { $avatar = new Avatar('http://…', 'application/xml'); $this->source->expects($this->once()) ->method('fetch') - ->with($email, $this->avatarFactory) + ->with($email, $this->avatarFactory, true) ->willReturn($avatar); $this->cache->expects($this->never()) ->method('add'); @@ -121,17 +135,46 @@ class AvatarServiceTest extends TestCase { $this->assertNull($url); } + public function testGetAvatarOnlyInternalAllowed() { + $email = 'jane@doe.com'; + $uid = 'john'; + $avatar = new Avatar('https://doe.com/favicon.ico', 'image/png'); + $this->preferences->expects($this->once()) + ->method('getPreference') + ->with('external-avatars', 'true') + ->willReturn('false'); + $this->cache->expects($this->once()) + ->method('get') + ->with($email) + ->willReturn(null); + $this->source->expects($this->once()) + ->method('fetch') + ->with($email, $this->avatarFactory, false) + ->willReturn($avatar); + $this->cache->expects($this->once()) + ->method('add') + ->with($email, $uid, $avatar); + + $actualAvatar = $this->avatarService->getAvatar($email, $uid); + + $this->assertEquals($avatar, $actualAvatar); + } + public function testGetAvatar() { $email = 'jane@doe.com'; $uid = 'john'; $avatar = new Avatar('https://doe.com/favicon.ico', 'image/png'); + $this->preferences->expects($this->once()) + ->method('getPreference') + ->with('external-avatars', 'true') + ->willReturn('true'); $this->cache->expects($this->once()) ->method('get') ->with($email) ->willReturn(null); $this->source->expects($this->once()) ->method('fetch') - ->with($email, $this->avatarFactory) + ->with($email, $this->avatarFactory, true) ->willReturn($avatar); $this->cache->expects($this->once()) ->method('add') diff --git a/tests/Service/UserPreferenceServiceTest.php b/tests/Service/UserPreferenceServiceTest.php new file mode 100644 index 000000000..4e5a0e079 --- /dev/null +++ b/tests/Service/UserPreferenceServiceTest.php @@ -0,0 +1,70 @@ +<?php + +/** + * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2017 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\Mail\Tests\Service; + +use OCA\Mail\Service\UserPreferenceSevice; +use OCA\Mail\Tests\TestCase; +use OCP\IConfig; + +class UserPreferenceServiceTest extends TestCase { + + /** @var IConfig */ + private $config; + + /** @var string */ + private $userId = 'claire'; + + /** @var UserPreferenceSevice */ + private $service; + + protected function setUp() { + parent::setUp(); + + $this->config = $this->createMock(IConfig::class); + $this->service = new UserPreferenceSevice($this->config, $this->userId); + } + + public function testGetPreference() { + $this->config->expects($this->once()) + ->method('getUserValue') + ->with($this->userId, 'mail', 'test', null) + ->willReturn('123'); + $expected = '123'; + + $actual = $this->service->getPreference('test'); + + $this->assertEquals($expected, $actual); + } + + public function testSetPreference() { + $this->config->expects($this->once()) + ->method('setUserValue') + ->with($this->userId, 'mail', 'test', '123') + ->willReturn('123'); + + $this->service->setPreference('test', '123'); + } + +} |