nextcloud/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php

346 lines
7.9 KiB
PHP
Raw Normal View History

2013-08-17 13:16:48 +04:00
<?php
/**
* ownCloud - App Framework
*
* @author Bernhard Posselt
* @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com>
2013-08-17 13:16:48 +04:00
*
* 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\AppFramework\Middleware\Security;
use OC\AppFramework\Http;
2013-08-17 13:16:48 +04:00
use OC\AppFramework\Http\Request;
use OC\AppFramework\Utility\ControllerMethodReflector;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\JSONResponse;
2013-08-17 13:16:48 +04:00
class SecurityMiddlewareTest extends \Test\TestCase {
2013-08-17 13:16:48 +04:00
private $middleware;
private $controller;
private $secException;
private $secAjaxException;
private $request;
private $reader;
private $logger;
private $navigationManager;
private $urlGenerator;
2013-08-17 13:16:48 +04:00
protected function setUp() {
parent::setUp();
$this->controller = $this->getMockBuilder('OCP\AppFramework\Controller')
->disableOriginalConstructor()
->getMock();
$this->reader = new ControllerMethodReflector();
$this->logger = $this->getMockBuilder(
'OCP\ILogger')
->disableOriginalConstructor()
->getMock();
$this->navigationManager = $this->getMockBuilder(
'OCP\INavigationManager')
->disableOriginalConstructor()
->getMock();
$this->urlGenerator = $this->getMockBuilder(
'OCP\IURLGenerator')
->disableOriginalConstructor()
->getMock();
$this->request = $this->getMockBuilder(
'OCP\IRequest')
->disableOriginalConstructor()
->getMock();
$this->middleware = $this->getMiddleware(true, true);
2013-08-17 13:16:48 +04:00
$this->secException = new SecurityException('hey', false);
$this->secAjaxException = new SecurityException('hey', true);
}
private function getMiddleware($isLoggedIn, $isAdminUser){
return new SecurityMiddleware(
$this->request,
$this->reader,
$this->navigationManager,
$this->urlGenerator,
$this->logger,
'files',
$isLoggedIn,
$isAdminUser
);
2013-08-17 13:16:48 +04:00
}
/**
* @PublicPage
* @NoCSRFRequired
2013-08-17 13:16:48 +04:00
*/
public function testSetNavigationEntry(){
$this->navigationManager->expects($this->once())
->method('setActiveEntry')
->with($this->equalTo('files'));
$this->reader->reflect(__CLASS__, __FUNCTION__);
$this->middleware->beforeController(__CLASS__, __FUNCTION__);
2013-08-17 13:16:48 +04:00
}
/**
* @param string $method
* @param string $test
*/
2013-08-17 13:16:48 +04:00
private function ajaxExceptionStatus($method, $test, $status) {
$isLoggedIn = false;
$isAdminUser = false;
2013-08-17 13:16:48 +04:00
// isAdminUser requires isLoggedIn call to return true
if ($test === 'isAdminUser') {
$isLoggedIn = true;
}
$sec = $this->getMiddleware($isLoggedIn, $isAdminUser);
2013-08-17 13:16:48 +04:00
try {
$this->reader->reflect(__CLASS__, $method);
$sec->beforeController(__CLASS__, $method);
2013-08-17 13:16:48 +04:00
} catch (SecurityException $ex){
$this->assertEquals($status, $ex->getCode());
}
2014-05-28 17:23:57 +04:00
// add assertion if everything should work fine otherwise phpunit will
// complain
if ($status === 0) {
$this->assertTrue(true);
}
2013-08-17 13:16:48 +04:00
}
public function testAjaxStatusLoggedInCheck() {
$this->ajaxExceptionStatus(
2014-05-28 17:23:57 +04:00
__FUNCTION__,
2013-08-17 13:16:48 +04:00
'isLoggedIn',
Http::STATUS_UNAUTHORIZED
);
}
/**
* @NoCSRFRequired
2013-08-17 13:16:48 +04:00
*/
public function testAjaxNotAdminCheck() {
$this->ajaxExceptionStatus(
2014-05-28 17:23:57 +04:00
__FUNCTION__,
2013-08-17 13:16:48 +04:00
'isAdminUser',
Http::STATUS_FORBIDDEN
);
}
/**
* @PublicPage
2013-08-17 13:16:48 +04:00
*/
public function testAjaxStatusCSRFCheck() {
$this->ajaxExceptionStatus(
2014-05-28 17:23:57 +04:00
__FUNCTION__,
2013-08-17 13:16:48 +04:00
'passesCSRFCheck',
Http::STATUS_PRECONDITION_FAILED
);
}
/**
* @PublicPage
* @NoCSRFRequired
2013-08-17 13:16:48 +04:00
*/
public function testAjaxStatusAllGood() {
$this->ajaxExceptionStatus(
2014-05-28 17:23:57 +04:00
__FUNCTION__,
2013-08-17 13:16:48 +04:00
'isLoggedIn',
0
);
$this->ajaxExceptionStatus(
2014-05-28 17:23:57 +04:00
__FUNCTION__,
2013-08-17 13:16:48 +04:00
'isAdminUser',
0
);
$this->ajaxExceptionStatus(
2014-05-28 17:23:57 +04:00
__FUNCTION__,
2013-08-17 13:16:48 +04:00
'isSubAdminUser',
0
);
$this->ajaxExceptionStatus(
2014-05-28 17:23:57 +04:00
__FUNCTION__,
2013-08-17 13:16:48 +04:00
'passesCSRFCheck',
0
);
}
2013-08-17 13:16:48 +04:00
/**
* @PublicPage
* @NoCSRFRequired
2013-08-17 13:16:48 +04:00
*/
public function testNoChecks(){
$this->request->expects($this->never())
2013-08-17 13:16:48 +04:00
->method('passesCSRFCheck')
->will($this->returnValue(false));
$sec = $this->getMiddleware(false, false);
$this->reader->reflect(__CLASS__, __FUNCTION__);
$sec->beforeController(__CLASS__, __FUNCTION__);
2013-08-17 13:16:48 +04:00
}
/**
* @param string $method
* @param string $expects
*/
2013-08-17 13:16:48 +04:00
private function securityCheck($method, $expects, $shouldFail=false){
// admin check requires login
if ($expects === 'isAdminUser') {
$isLoggedIn = true;
$isAdminUser = !$shouldFail;
} else {
$isLoggedIn = !$shouldFail;
$isAdminUser = false;
}
$sec = $this->getMiddleware($isLoggedIn, $isAdminUser);
2013-08-17 13:16:48 +04:00
if($shouldFail){
$this->setExpectedException('\OC\AppFramework\Middleware\Security\SecurityException');
} else {
2014-05-28 17:23:57 +04:00
$this->assertTrue(true);
2013-08-17 13:16:48 +04:00
}
$this->reader->reflect(__CLASS__, $method);
$sec->beforeController(__CLASS__, $method);
2013-08-17 13:16:48 +04:00
}
/**
* @PublicPage
2013-10-07 13:25:50 +04:00
* @expectedException \OC\AppFramework\Middleware\Security\SecurityException
2013-08-17 13:16:48 +04:00
*/
public function testCsrfCheck(){
$this->request->expects($this->once())
2013-10-07 13:25:50 +04:00
->method('passesCSRFCheck')
->will($this->returnValue(false));
$this->reader->reflect(__CLASS__, __FUNCTION__);
$this->middleware->beforeController(__CLASS__, __FUNCTION__);
2013-10-07 13:25:50 +04:00
}
/**
* @PublicPage
* @NoCSRFRequired
*/
public function testNoCsrfCheck(){
$this->request->expects($this->never())
2013-10-07 13:25:50 +04:00
->method('passesCSRFCheck')
->will($this->returnValue(false));
$this->reader->reflect(__CLASS__, __FUNCTION__);
$this->middleware->beforeController(__CLASS__, __FUNCTION__);
2013-08-17 13:16:48 +04:00
}
/**
* @PublicPage
2013-08-17 13:16:48 +04:00
*/
public function testFailCsrfCheck(){
$this->request->expects($this->once())
2013-10-07 13:25:50 +04:00
->method('passesCSRFCheck')
->will($this->returnValue(true));
$this->reader->reflect(__CLASS__, __FUNCTION__);
$this->middleware->beforeController(__CLASS__, __FUNCTION__);
2013-08-17 13:16:48 +04:00
}
/**
* @NoCSRFRequired
* @NoAdminRequired
2013-08-17 13:16:48 +04:00
*/
public function testLoggedInCheck(){
$this->securityCheck(__FUNCTION__, 'isLoggedIn');
2013-08-17 13:16:48 +04:00
}
/**
* @NoCSRFRequired
* @NoAdminRequired
2013-08-17 13:16:48 +04:00
*/
public function testFailLoggedInCheck(){
$this->securityCheck(__FUNCTION__, 'isLoggedIn', true);
2013-08-17 13:16:48 +04:00
}
/**
* @NoCSRFRequired
2013-08-17 13:16:48 +04:00
*/
public function testIsAdminCheck(){
$this->securityCheck(__FUNCTION__, 'isAdminUser');
2013-08-17 13:16:48 +04:00
}
/**
* @NoCSRFRequired
2013-08-17 13:16:48 +04:00
*/
public function testFailIsAdminCheck(){
$this->securityCheck(__FUNCTION__, 'isAdminUser', true);
2013-08-17 13:16:48 +04:00
}
public function testAfterExceptionNotCaughtThrowsItAgain(){
$ex = new \Exception();
$this->setExpectedException('\Exception');
$this->middleware->afterException($this->controller, 'test', $ex);
}
public function testAfterExceptionReturnsRedirect(){
$this->request = new Request(
[
'server' =>
[
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'REQUEST_URI' => 'owncloud/index.php/apps/specialapp'
]
],
$this->getMock('\OCP\Security\ISecureRandom'),
$this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->middleware = $this->getMiddleware(true, true);
2013-08-17 13:16:48 +04:00
$response = $this->middleware->afterException($this->controller, 'test',
$this->secException);
$this->assertTrue($response instanceof RedirectResponse);
2014-07-02 03:06:58 +04:00
$this->assertEquals('?redirect_url=owncloud%2Findex.php%2Fapps%2Fspecialapp', $response->getRedirectURL());
2013-08-17 13:16:48 +04:00
}
public function testAfterAjaxExceptionReturnsJSONError(){
$response = $this->middleware->afterException($this->controller, 'test',
$this->secAjaxException);
$this->assertTrue($response instanceof JSONResponse);
}
}