diff options
-rw-r--r-- | apps/encryption/appinfo/application.php | 14 | ||||
-rw-r--r-- | apps/encryption/appinfo/routes.php | 5 | ||||
-rw-r--r-- | apps/encryption/controller/settingscontroller.php | 131 | ||||
-rw-r--r-- | apps/encryption/js/settings-personal.js | 17 | ||||
-rw-r--r-- | apps/encryption/tests/controller/SettingsControllerTest.php | 222 |
5 files changed, 379 insertions, 10 deletions
diff --git a/apps/encryption/appinfo/application.php b/apps/encryption/appinfo/application.php index 5d0fe2c9184..243e227b6bb 100644 --- a/apps/encryption/appinfo/application.php +++ b/apps/encryption/appinfo/application.php @@ -171,6 +171,20 @@ class Application extends \OCP\AppFramework\App { ); }); + $container->registerService('SettingsController', function (IAppContainer $c) { + $server = $c->getServer(); + return new \OCA\Encryption\Controller\SettingsController( + $c->getAppName(), + $server->getRequest(), + $server->getL10N($c->getAppName()), + $server->getUserManager(), + $server->getUserSession(), + $c->query('KeyManager'), + $c->query('Crypt'), + $c->query('Session') + ); + }); + $container->registerService('UserSetup', function (IAppContainer $c) { $server = $c->getServer(); diff --git a/apps/encryption/appinfo/routes.php b/apps/encryption/appinfo/routes.php index 4194308a0ce..8fa163d0751 100644 --- a/apps/encryption/appinfo/routes.php +++ b/apps/encryption/appinfo/routes.php @@ -31,6 +31,11 @@ namespace OCA\Encryption\AppInfo; 'verb' => 'POST' ], [ + 'name' => 'Settings#updatePrivateKeyPassword', + 'url' => '/ajax/updatePrivateKeyPassword', + 'verb' => 'POST' + ], + [ 'name' => 'Recovery#changeRecoveryPassword', 'url' => '/ajax/changeRecoveryPassword', 'verb' => 'POST' diff --git a/apps/encryption/controller/settingscontroller.php b/apps/encryption/controller/settingscontroller.php new file mode 100644 index 00000000000..7fa3f469a14 --- /dev/null +++ b/apps/encryption/controller/settingscontroller.php @@ -0,0 +1,131 @@ +<?php +/** + * @author Björn Schießle <schiessle@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\Encryption\Controller; + +use OCA\Encryption\Crypto\Crypt; +use OCA\Encryption\KeyManager; +use OCA\Encryption\Session; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; +use OCP\IL10N; +use OCP\IRequest; +use OCP\IUserManager; +use OCP\IUserSession; + +class SettingsController extends Controller { + + /** @var IL10N */ + private $l; + + /** @var IUserManager */ + private $userManager; + + /** @var IUserSession */ + private $userSession; + + /** @var KeyManager */ + private $keyManager; + + /** @var Crypt */ + private $crypt; + + /** @var Session */ + private $session; + + /** + * @param string $AppName + * @param IRequest $request + * @param IL10N $l10n + * @param IUserManager $userManager + * @param IUserSession $userSession + * @param KeyManager $keyManager + * @param Crypt $crypt + * @param Session $session + */ + public function __construct($AppName, + IRequest $request, + IL10N $l10n, + IUserManager $userManager, + IUserSession $userSession, + KeyManager $keyManager, + Crypt $crypt, + Session $session) { + parent::__construct($AppName, $request); + $this->l = $l10n; + $this->userSession = $userSession; + $this->userManager = $userManager; + $this->keyManager = $keyManager; + $this->crypt = $crypt; + $this->session = $session; + } + + + /** + * @NoAdminRequired + * @UseSession + * + * @param string $oldPassword + * @param string $newPassword + * @return DataResponse + */ + public function updatePrivateKeyPassword($oldPassword, $newPassword) { + $result = false; + $uid = $this->userSession->getUser()->getUID(); + $errorMessage = $this->l->t('Could not update the private key password.'); + + //check if password is correct + $passwordCorrect = $this->userManager->checkPassword($uid, $newPassword); + + if ($passwordCorrect !== false) { + $encryptedKey = $this->keyManager->getPrivateKey($uid); + $decryptedKey = $this->crypt->decryptPrivateKey($encryptedKey, $oldPassword); + + if ($decryptedKey) { + $encryptedKey = $this->crypt->symmetricEncryptFileContent($decryptedKey, $newPassword); + $header = $this->crypt->generateHeader(); + if ($encryptedKey) { + $this->keyManager->setPrivateKey($uid, $header . $encryptedKey); + $this->session->setPrivateKey($decryptedKey); + $result = true; + } + } else { + $errorMessage = $this->l->t('The old password was not correct, please try again.'); + } + } else { + $errorMessage = $this->l->t('The current log-in password was not correct, please try again.'); + } + + if ($result === true) { + $this->session->setStatus(Session::INIT_SUCCESSFUL); + return new DataResponse( + ['message' => (string) $this->l->t('Private key password successfully updated.')] + ); + } else { + return new DataResponse( + ['message' => (string) $errorMessage], + Http::STATUS_BAD_REQUEST + ); + } + + } +} diff --git a/apps/encryption/js/settings-personal.js b/apps/encryption/js/settings-personal.js index dcfbba4ecde..68609877c05 100644 --- a/apps/encryption/js/settings-personal.js +++ b/apps/encryption/js/settings-personal.js @@ -9,16 +9,13 @@ function updatePrivateKeyPasswd() { var newPrivateKeyPassword = $('input:password[id="newPrivateKeyPassword"]').val(); OC.msg.startSaving('#encryption .msg'); $.post( - OC.generateUrl('/apps/encryption/ajax/updatePrivateKeyPassword') - , { oldPassword: oldPrivateKeyPassword, newPassword: newPrivateKeyPassword } - , function( data ) { - if (data.status === "error") { - OC.msg.finishedSaving('#encryption .msg', data); - } else { - OC.msg.finishedSaving('#encryption .msg', data); - } - } - ); + OC.generateUrl('/apps/encryption/ajax/updatePrivateKeyPassword'), + { oldPassword: oldPrivateKeyPassword, newPassword: newPrivateKeyPassword } + ).success(function(response) { + OC.msg.finishedSuccess('#encryption .msg', response.message); + }).fail(function(response) { + OC.msg.finishedError('#encryption .msg', response.responseJSON.message); + }); } $(document).ready(function(){ diff --git a/apps/encryption/tests/controller/SettingsControllerTest.php b/apps/encryption/tests/controller/SettingsControllerTest.php new file mode 100644 index 00000000000..478bf8213b5 --- /dev/null +++ b/apps/encryption/tests/controller/SettingsControllerTest.php @@ -0,0 +1,222 @@ +<?php +/** + * @author Björn Schießle <schiessle@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\Encryption\Tests\Controller; + +use OCA\Encryption\Controller\SettingsController; +use OCA\Encryption\Session; +use OCP\AppFramework\Http; +use Test\TestCase; + +class SettingsControllerTest extends TestCase { + + /** @var SettingsController */ + private $controller; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $requestMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $l10nMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $userManagerMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $userSessionMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $keyManagerMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $cryptMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $sessionMock; + + protected function setUp() { + + parent::setUp(); + + $this->requestMock = $this->getMock('OCP\IRequest'); + + $this->l10nMock = $this->getMockBuilder('OCP\IL10N') + ->disableOriginalConstructor()->getMock(); + + $this->l10nMock->expects($this->any()) + ->method('t') + ->will($this->returnCallback(function($message) { + return $message; + })); + + $this->userManagerMock = $this->getMockBuilder('OCP\IUserManager') + ->disableOriginalConstructor()->getMock(); + + $this->keyManagerMock = $this->getMockBuilder('OCA\Encryption\KeyManager') + ->disableOriginalConstructor()->getMock(); + + $this->cryptMock = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt') + ->disableOriginalConstructor()->getMock(); + + $this->userSessionMock = $this->getMockBuilder('OCP\IUserSession') + ->disableOriginalConstructor() + ->setMethods([ + 'isLoggedIn', + 'getUID', + 'login', + 'logout', + 'setUser', + 'getUser', + 'canChangePassword', + ]) + ->getMock(); + + $this->userSessionMock->expects($this->any()) + ->method('getUID') + ->willReturn('testUser'); + + $this->userSessionMock->expects($this->any()) + ->method($this->anything()) + ->will($this->returnSelf()); + + $this->sessionMock = $this->getMockBuilder('OCA\Encryption\Session') + ->disableOriginalConstructor()->getMock(); + + $this->controller = new SettingsController( + 'encryption', + $this->requestMock, + $this->l10nMock, + $this->userManagerMock, + $this->userSessionMock, + $this->keyManagerMock, + $this->cryptMock, + $this->sessionMock + ); + } + + /** + * test updatePrivateKeyPassword() if wrong new password was entered + */ + public function testUpdatePrivateKeyPasswordWrongNewPassword() { + + $oldPassword = 'old'; + $newPassword = 'new'; + + $this->userManagerMock + ->expects($this->once()) + ->method('checkPassword') + ->willReturn(false); + + $result = $this->controller->updatePrivateKeyPassword($oldPassword, $newPassword); + + $data = $result->getData(); + + $this->assertSame(Http::STATUS_BAD_REQUEST, $result->getStatus()); + $this->assertSame('The current log-in password was not correct, please try again.', + $data['message']); + } + + /** + * test updatePrivateKeyPassword() if wrong old password was entered + */ + public function testUpdatePrivateKeyPasswordWrongOldPassword() { + + $oldPassword = 'old'; + $newPassword = 'new'; + + $this->userManagerMock + ->expects($this->once()) + ->method('checkPassword') + ->willReturn(true); + + $this->cryptMock + ->expects($this->once()) + ->method('decryptPrivateKey') + ->willReturn(false); + + $result = $this->controller->updatePrivateKeyPassword($oldPassword, $newPassword); + + $data = $result->getData(); + + $this->assertSame(Http::STATUS_BAD_REQUEST, $result->getStatus()); + $this->assertSame('The old password was not correct, please try again.', + $data['message']); + } + + /** + * test updatePrivateKeyPassword() with the correct old and new password + */ + public function testUpdatePrivateKeyPassword() { + + $oldPassword = 'old'; + $newPassword = 'new'; + + $this->userSessionMock + ->expects($this->once()) + ->method('getUID') + ->willReturn('testUser'); + + $this->userManagerMock + ->expects($this->once()) + ->method('checkPassword') + ->willReturn(true); + + $this->cryptMock + ->expects($this->once()) + ->method('decryptPrivateKey') + ->willReturn('decryptedKey'); + + $this->cryptMock + ->expects($this->once()) + ->method('symmetricEncryptFileContent') + ->willReturn('encryptedKey'); + + $this->cryptMock + ->expects($this->once()) + ->method('generateHeader') + ->willReturn('header.'); + + // methods which must be called after successful changing the key password + $this->keyManagerMock + ->expects($this->once()) + ->method('setPrivateKey') + ->with($this->equalTo('testUser'), $this->equalTo('header.encryptedKey')); + + $this->sessionMock + ->expects($this->once()) + ->method('setPrivateKey') + ->with($this->equalTo('decryptedKey')); + + $this->sessionMock + ->expects($this->once()) + ->method('setStatus') + ->with($this->equalTo(Session::INIT_SUCCESSFUL)); + + $result = $this->controller->updatePrivateKeyPassword($oldPassword, $newPassword); + + $data = $result->getData(); + + $this->assertSame(Http::STATUS_OK, $result->getStatus()); + $this->assertSame('Private key password successfully updated.', + $data['message']); + } + +} |