Refactor MailSettings controller

- Do not store the password (fixes https://github.com/owncloud/core/issues/11385)
- Refactor to AppFramework
- Add unit tests

Conflicts:
	settings/admin/controller.php
This commit is contained in:
Lukas Reschke 2014-10-03 15:14:22 +02:00 committed by Thomas Müller
parent 766314a6be
commit 13b1b45ee4
9 changed files with 527 additions and 203 deletions

View File

@ -1,123 +0,0 @@
<?php
/**
* @author Joas Schilling
* @copyright 2014 Joas Schilling nickvergessen@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 library. If not, see <http://www.gnu.org/licenses/>.
*/
namespace OC\Settings\Admin;
class Controller {
/**
* Set mail settings
*/
public static function setMailSettings() {
\OC_Util::checkAdminUser();
\OCP\JSON::callCheck();
$l = \OC::$server->getL10N('settings');
$smtp_settings = array(
'mail_domain' => null,
'mail_from_address' => null,
'mail_smtpmode' => array('sendmail', 'smtp', 'qmail', 'php'),
'mail_smtpsecure' => array('', 'ssl', 'tls'),
'mail_smtphost' => null,
'mail_smtpport' => null,
'mail_smtpauthtype' => array('LOGIN', 'PLAIN', 'NTLM'),
'mail_smtpauth' => true,
'mail_smtpname' => null,
'mail_smtppassword' => null,
);
foreach ($smtp_settings as $setting => $validate) {
if (!$validate) {
if (!isset($_POST[$setting]) || $_POST[$setting] === '') {
\OC_Config::deleteKey( $setting );
} else {
\OC_Config::setValue( $setting, $_POST[$setting] );
}
}
else if (is_bool($validate)) {
if (!empty($_POST[$setting])) {
\OC_Config::setValue( $setting, (bool) $_POST[$setting] );
} else {
\OC_Config::deleteKey( $setting );
}
}
else if (is_array($validate)) {
if (!isset($_POST[$setting]) || $_POST[$setting] === '') {
\OC_Config::deleteKey( $setting );
} else if (in_array($_POST[$setting], $validate)) {
\OC_Config::setValue( $setting, $_POST[$setting] );
} else {
$message = $l->t('Invalid value supplied for %s', array(self::getFieldname($setting, $l)));
\OC_JSON::error( array( "data" => array( "message" => $message)) );
exit;
}
}
}
\OC_JSON::success(array("data" => array( "message" => $l->t("Saved") )));
}
/**
* Send a mail to test the settings
*/
public static function sendTestMail() {
\OC_Util::checkAdminUser();
\OCP\JSON::callCheck();
$l = \OC::$server->getL10N('settings');
$email = \OC_Preferences::getValue(\OC_User::getUser(), 'settings', 'email', '');
if (!empty($email)) {
$defaults = new \OC_Defaults();
try {
\OC_Mail::send($email, \OC_User::getDisplayName(),
$l->t('test email settings'),
$l->t('If you received this email, the settings seem to be correct.'),
\OCP\Util::getDefaultEmailAddress('no-reply'), $defaults->getName());
} catch (\Exception $e) {
$message = $l->t('A problem occurred while sending the e-mail. Please revisit your settings.');
\OC_JSON::error( array( "data" => array( "message" => $message)) );
exit;
}
\OC_JSON::success(array("data" => array( "message" => $l->t("Email sent") )));
} else {
$message = $l->t('You need to set your user email before being able to send test emails.');
\OC_JSON::error( array( "data" => array( "message" => $message)) );
}
}
/**
* Get the field name to use it in error messages
*
* @param string $setting
* @param \OC_L10N $l
* @return string
*/
public static function getFieldname($setting, $l) {
switch ($setting) {
case 'mail_smtpmode':
return $l->t( 'Send mode' );
case 'mail_smtpsecure':
return $l->t( 'Encryption' );
case 'mail_smtpauthtype':
return $l->t( 'Authentication method' );
}
}
}

70
settings/application.php Normal file
View File

@ -0,0 +1,70 @@
<?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 OC\Settings;
use OC\AppFramework\Utility\SimpleContainer;
use OC\Settings\Controller\MailSettingsController;
use \OCP\AppFramework\App;
use \OCP\Util;
/**
* @package OC\Settings
*/
class Application extends App {
/**
* @param array $urlParams
*/
public function __construct(array $urlParams=array()){
parent::__construct('settings', $urlParams);
$container = $this->getContainer();
/**
* Controllers
*/
$container->registerService('MailSettingsController', function(SimpleContainer $c) {
return new MailSettingsController(
$c->query('AppName'),
$c->query('Request'),
$c->query('L10N'),
$c->query('Config'),
$c->query('UserSession'),
$c->query('Defaults'),
$c->query('Mail'),
$c->query('DefaultMailAddress')
);
});
/**
* Core class wrappers
*/
$container->registerService('Config', function(SimpleContainer $c) {
return $c->query('ServerContainer')->getConfig();
});
$container->registerService('L10N', function(SimpleContainer $c) {
return $c->query('ServerContainer')->getL10N('settings');
});
$container->registerService('UserSession', function(SimpleContainer $c) {
return $c->query('ServerContainer')->getUserSession();
});
$container->registerService('Mail', function(SimpleContainer $c) {
return new \OC_Mail;
});
$container->registerService('Defaults', function(SimpleContainer $c) {
return new \OC_Defaults;
});
$container->registerService('DefaultMailAddress', function(SimpleContainer $c) {
return Util::getDefaultEmailAddress('no-reply');
});
}
}

View File

@ -0,0 +1,166 @@
<?php
/**
* @author Joas Schilling
* @author Lukas Reschke
* @copyright 2014 Joas Schilling nickvergessen@owncloud.com
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Settings\Controller;
use OC\User\Session;
use \OCP\AppFramework\Controller;
use OCP\IRequest;
use OCP\IL10N;
use OCP\IConfig;
/**
* @package OC\Settings\Controller
*/
class MailSettingsController extends Controller {
/** @var \OCP\IL10N */
private $l10n;
/** @var \OCP\IConfig */
private $config;
/** @var Session */
private $userSession;
/** @var \OC_Defaults */
private $defaults;
/** @var \OC_Mail */
private $mail;
/** @var string */
private $defaultMailAddress;
/**
* @param string $appName
* @param IRequest $request
* @param IL10N $l10n
* @param IConfig $config
* @param Session $userSession
* @param \OC_Defaults $defaults
* @param \OC_Mail $mail
* @param string $defaultMailAddress
*/
public function __construct($appName,
IRequest $request,
IL10N $l10n,
IConfig $config,
Session $userSession,
\OC_Defaults $defaults,
\OC_Mail $mail,
$defaultMailAddress) {
parent::__construct($appName, $request);
$this->l10n = $l10n;
$this->config = $config;
$this->userSession = $userSession;
$this->defaults = $defaults;
$this->mail = $mail;
$this->defaultMailAddress = $defaultMailAddress;
}
/**
* Sets the email settings
* @param string $mail_domain
* @param string $mail_from_address
* @param string $mail_smtpmode
* @param string $mail_smtpsecure
* @param string $mail_smtphost
* @param string $mail_smtpauthtype
* @param int $mail_smtpauth
* @param string $mail_smtpport
* @return array
*/
public function setMailSettings($mail_domain,
$mail_from_address,
$mail_smtpmode,
$mail_smtpsecure,
$mail_smtphost,
$mail_smtpauthtype,
$mail_smtpauth,
$mail_smtpport) {
$params = get_defined_vars();
foreach($params as $key => $value) {
if(empty($value)) {
$this->config->deleteSystemValue($key);
} else {
$this->config->setSystemValue($key, $value);
}
}
// Delete passwords from config in case no auth is specified
if($params['mail_smtpauth'] !== 1) {
$this->config->deleteSystemValue('mail_smtpname');
$this->config->deleteSystemValue('mail_smtppassword');
}
return array('data' =>
array('message' =>
(string) $this->l10n->t('Saved')
),
'status' => 'success'
);
}
/**
* Store the credentials used for SMTP in the config
* @param string $mail_smtpname
* @param string $mail_smtppassword
* @return array
*/
public function storeCredentials($mail_smtpname, $mail_smtppassword) {
$this->config->setSystemValue('mail_smtpname', $mail_smtpname);
$this->config->setSystemValue('mail_smtppassword', $mail_smtppassword);
return array('data' =>
array('message' =>
(string) $this->l10n->t('Saved')
),
'status' => 'success'
);
}
/**
* Send a mail to test the settings
* @return array
*/
public function sendTestMail() {
$email = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'email', '');
if (!empty($email)) {
try {
$this->mail->send($email, $this->userSession->getUser()->getDisplayName(),
$this->l10n->t('test email settings'),
$this->l10n->t('If you received this email, the settings seems to be correct.'),
$this->defaultMailAddress,
$this->defaults->getName()
);
} catch (\Exception $e) {
return array('data' =>
array('message' =>
(string) $this->l10n->t('A problem occurred while sending the e-mail. Please revisit your settings.'),
),
'status' => 'error'
);
}
return array('data' =>
array('message' =>
(string) $this->l10n->t('Email sent')
),
'status' => 'success'
);
}
return array('data' =>
array('message' =>
(string) $this->l10n->t('You need to set your user email before being able to send test emails.'),
),
'status' => 'error'
);
}
}

View File

@ -178,12 +178,12 @@ span.securitywarning, span.connectionwarning, .setupwarning {
padding-left: 56px;
}
#mail_settings p label:first-child {
.mail_settings p label:first-child {
display: inline-block;
width: 300px;
text-align: right;
}
#mail_settings p select:nth-child(2) {
.mail_settings p select:nth-child(2) {
width: 143px;
}
#mail_smtpport {

View File

@ -103,14 +103,22 @@ $(document).ready(function(){
}
});
$('#mail_settings').change(function(){
$('#mail_general_settings').change(function(){
OC.msg.startSaving('#mail_settings_msg');
var post = $( "#mail_settings" ).serialize();
var post = $( "#mail_general_settings" ).serialize();
$.post(OC.generateUrl('/settings/admin/mailsettings'), post, function(data){
OC.msg.finishedSaving('#mail_settings_msg', data);
});
});
$('#mail_credentials_settings_submit').click(function(){
OC.msg.startSaving('#mail_settings_msg');
var post = $( "#mail_credentials_settings" ).serialize();
$.post(OC.generateUrl('/settings/admin/mailsettings/credentials'), post, function(data){
OC.msg.finishedSaving('#mail_settings_msg', data);
});
});
$('#sendtestemail').click(function(event){
event.preventDefault();
OC.msg.startAction('#sendtestmail_msg', t('settings', 'Sending...'));

View File

@ -6,7 +6,16 @@
* See the COPYING-README file.
*/
/** @var $this OCP\Route\IRouter */
namespace OC\Settings;
$application = new Application();
$application->registerRoutes($this, array('routes' =>array(
array('name' => 'MailSettings#setMailSettings', 'url' => '/settings/admin/mailsettings', 'verb' => 'POST'),
array('name' => 'MailSettings#storeCredentials', 'url' => '/settings/admin/mailsettings/credentials', 'verb' => 'POST'),
array('name' => 'MailSettings#sendTestMail', 'url' => '/settings/admin/mailtest', 'verb' => 'POST'),
)));
/** @var $this \OCP\Route\IRouter */
// Settings pages
$this->create('settings_help', '/settings/help')
@ -88,12 +97,6 @@ $this->create('settings_ajax_getlog', '/settings/ajax/getlog.php')
->actionInclude('settings/ajax/getlog.php');
$this->create('settings_ajax_setloglevel', '/settings/ajax/setloglevel.php')
->actionInclude('settings/ajax/setloglevel.php');
$this->create('settings_mail_settings', '/settings/admin/mailsettings')
->post()
->action('OC\Settings\Admin\Controller', 'setMailSettings');
$this->create('settings_admin_mail_test', '/settings/admin/mailtest')
->post()
->action('OC\Settings\Admin\Controller', 'sendTestMail');
$this->create('settings_ajax_setsecurity', '/settings/ajax/setsecurity.php')
->actionInclude('settings/ajax/setsecurity.php');
$this->create('settings_ajax_excludegroups', '/settings/ajax/excludegroups.php')

View File

@ -333,7 +333,8 @@ if ($_['suggestedOverwriteWebroot']) {
</p>
</div>
<div class="section"><form id="mail_settings">
<div class="section">
<form id="mail_general_settings" class="mail_settings">
<h2><?php p($l->t('Email Server'));?></h2>
<p><?php p($l->t('This is used for sending out notifications.')); ?> <span id="mail_settings_msg" class="msg"></span></p>
@ -370,7 +371,6 @@ if ($_['suggestedOverwriteWebroot']) {
<label for="mail_from_address"><?php p($l->t( 'From address' )); ?></label>
<input type="text" name='mail_from_address' id="mail_from_address" placeholder="<?php p($l->t('mail'))?>"
value='<?php p($_['mail_from_address']) ?>' />
@
<input type="text" name='mail_domain' id="mail_domain" placeholder="example.com"
value='<?php p($_['mail_domain']) ?>' />
</p>
@ -400,20 +400,23 @@ if ($_['suggestedOverwriteWebroot']) {
<input type="text" name='mail_smtpport' id="mail_smtpport" placeholder="<?php p($l->t('Port'))?>"
value='<?php p($_['mail_smtpport']) ?>' />
</p>
</form>
<form class="mail_settings" id="mail_credentials_settings">
<p id="mail_credentials" <?php if (!$_['mail_smtpauth'] || $_['mail_smtpmode'] != 'smtp') print_unescaped(' class="hidden"'); ?>>
<label for="mail_smtpname"><?php p($l->t( 'Credentials' )); ?></label>
<input type="text" name='mail_smtpname' id="mail_smtpname" placeholder="<?php p($l->t('SMTP Username'))?>"
value='<?php p($_['mail_smtpname']) ?>' />
<input type="password" name='mail_smtppassword' id="mail_smtppassword"
placeholder="<?php p($l->t('SMTP Password'))?>" value='<?php p($_['mail_smtppassword']) ?>' />
<input id="mail_credentials_settings_submit" type="button" value="<?php p($l->t('Store credentials')) ?>">
</p>
</form>
<br />
<em><?php p($l->t( 'Test email settings' )); ?></em>
<input type="submit" name="sendtestemail" id="sendtestemail" value="<?php p($l->t( 'Send email' )); ?>"/>
<span id="sendtestmail_msg" class="msg"></span>
</form></div>
</div>
<div class="section">
<h2><?php p($l->t('Log'));?></h2>

View File

@ -8,6 +8,7 @@
>
<testsuite name='ownCloud'>
<directory suffix='.php'>lib/</directory>
<directory suffix='.php'>settings/</directory>
<file>apps.php</file>
</testsuite>
<!-- filters for code coverage -->

View File

@ -0,0 +1,196 @@
<?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 OC\Settings\Controller;
use \OC\Settings\Application;
/**
* @package OC\Settings\Controller
*/
class MailSettingscontrollerTest extends \PHPUnit_Framework_TestCase {
private $container;
protected function setUp() {
$app = new Application();
$this->container = $app->getContainer();
$this->container['Config'] = $this->getMockBuilder('\OCP\IConfig')
->disableOriginalConstructor()->getMock();
$this->container['L10N'] = $this->getMockBuilder('\OCP\IL10N')
->disableOriginalConstructor()->getMock();
$this->container['AppName'] = 'settings';
$this->container['UserSession'] = $this->getMockBuilder('\OC\User\Session')
->disableOriginalConstructor()->getMock();
$this->container['Mail'] = $this->getMockBuilder('\OC_Mail')
->disableOriginalConstructor()->getMock();
$this->container['Defaults'] = $this->getMockBuilder('\OC_Defaults')
->disableOriginalConstructor()->getMock();
$this->container['DefaultMailAddress'] = 'no-reply@owncloud.com';
}
public function testSetMailSettings() {
$this->container['L10N']
->expects($this->exactly(2))
->method('t')
->will($this->returnValue('Saved'));
/**
* FIXME: Use the following block once Jenkins uses PHPUnit >= 4.1
*/
/*
$this->container['Config']
->expects($this->exactly(15))
->method('setSystemValue')
->withConsecutive(
array($this->equalTo('mail_domain'), $this->equalTo('owncloud.com')),
array($this->equalTo('mail_from_address'), $this->equalTo('demo@owncloud.com')),
array($this->equalTo('mail_smtpmode'), $this->equalTo('smtp')),
array($this->equalTo('mail_smtpsecure'), $this->equalTo('ssl')),
array($this->equalTo('mail_smtphost'), $this->equalTo('mx.owncloud.org')),
array($this->equalTo('mail_smtpauthtype'), $this->equalTo('NTLM')),
array($this->equalTo('mail_smtpauth'), $this->equalTo(1)),
array($this->equalTo('mail_smtpport'), $this->equalTo('25')),
array($this->equalTo('mail_domain'), $this->equalTo('owncloud.com')),
array($this->equalTo('mail_from_address'), $this->equalTo('demo@owncloud.com')),
array($this->equalTo('mail_smtpmode'), $this->equalTo('smtp')),
array($this->equalTo('mail_smtpsecure'), $this->equalTo('ssl')),
array($this->equalTo('mail_smtphost'), $this->equalTo('mx.owncloud.org')),
array($this->equalTo('mail_smtpauthtype'), $this->equalTo('NTLM')),
array($this->equalTo('mail_smtpport'), $this->equalTo('25'))
);
*/
$this->container['Config']
->expects($this->exactly(15))
->method('setSystemValue');
/**
* FIXME: Use the following block once Jenkins uses PHPUnit >= 4.1
*/
/*
$this->container['Config']
->expects($this->exactly(3))
->method('deleteSystemValue')
->withConsecutive(
array($this->equalTo('mail_smtpauth')),
array($this->equalTo('mail_smtpname')),
array($this->equalTo('mail_smtppassword'))
);
*/
$this->container['Config']
->expects($this->exactly(3))
->method('deleteSystemValue');
// With authentication
$response = $this->container['MailSettingsController']->setMailSettings(
'owncloud.com',
'demo@owncloud.com',
'smtp',
'ssl',
'mx.owncloud.org',
'NTLM',
1,
'25'
);
$expectedResponse = array('data' => array('message' =>'Saved'), 'status' => 'success');
$this->assertSame($expectedResponse, $response);
// Without authentication (testing the deletion of the stored password)
$response = $this->container['MailSettingsController']->setMailSettings(
'owncloud.com',
'demo@owncloud.com',
'smtp',
'ssl',
'mx.owncloud.org',
'NTLM',
0,
'25'
);
$expectedResponse = array('data' => array('message' =>'Saved'), 'status' => 'success');
$this->assertSame($expectedResponse, $response);
}
public function testStoreCredentials() {
$this->container['L10N']
->expects($this->once())
->method('t')
->will($this->returnValue('Saved'));
/**
* FIXME: Use this block once Jenkins uses PHPUnit >= 4.1
*/
/*
$this->container['Config']
->expects($this->exactly(2))
->method('setSystemValue')
->withConsecutive(
array($this->equalTo('mail_smtpname'), $this->equalTo('UsernameToStore')),
array($this->equalTo('mail_smtppassword'), $this->equalTo('PasswordToStore'))
);
*/
$this->container['Config']
->expects($this->exactly(2))
->method('setSystemValue');
$response = $this->container['MailSettingsController']->storeCredentials('UsernameToStore', 'PasswordToStore');
$expectedResponse = array('data' => array('message' =>'Saved'), 'status' => 'success');
$this->assertSame($expectedResponse, $response);
}
public function testSendTestMail() {
$user = $this->getMockBuilder('\OC\User\User')
->disableOriginalConstructor()
->getMock();
$user->expects($this->any())
->method('getUID')
->will($this->returnValue('Werner'));
$user->expects($this->any())
->method('getDisplayName')
->will($this->returnValue('Werner Brösel'));
$this->container['L10N']
->expects($this->any())
->method('t')
->will(
$this->returnValueMap(
array(
array('You need to set your user email before being able to send test emails.', array(),
'You need to set your user email before being able to send test emails.'),
array('A problem occurred while sending the e-mail. Please revisit your settings.', array(),
'A problem occurred while sending the e-mail. Please revisit your settings.'),
array('Email sent', array(), 'Email sent'),
array('test email settings', array(), 'test email settings'),
array('If you received this email, the settings seems to be correct.', array(),
'If you received this email, the settings seems to be correct.')
)
));
$this->container['UserSession']
->expects($this->any())
->method('getUser')
->will($this->returnValue($user));
// Ensure that it fails when no mail address has been specified
$response = $this->container['MailSettingsController']->sendTestMail();
$expectedResponse = array('data' => array('message' =>'You need to set your user email before being able to send test emails.'), 'status' => 'error');
$this->assertSame($expectedResponse, $response);
// If no exception is thrown it should work
$this->container['Config']
->expects($this->any())
->method('getUserValue')
->will($this->returnValue('mail@example.invalid'));
$response = $this->container['MailSettingsController']->sendTestMail();
$expectedResponse = array('data' => array('message' =>'Email sent'), 'status' => 'success');
$this->assertSame($expectedResponse, $response);
}
}