Source of file ControllerTest.php
Size: 16,446 Bytes - Last Modified: 2021-12-24T06:33:34+00:00
/var/www/docs.ssmods.com/process/src/tests/src/Control/ControllerTest.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 | <?php namespace Bigfork\SilverStripeOAuth\Client\Test\Control; use Bigfork\SilverStripeOAuth\Client\Control\Controller; use Bigfork\SilverStripeOAuth\Client\Factory\ProviderFactory; use Bigfork\SilverStripeOAuth\Client\Handler\TokenHandler; use Bigfork\SilverStripeOAuth\Client\Test\TestCase; use Embed\Providers\Provider; use League\OAuth2\Client\Provider\GenericProvider; use League\OAuth2\Client\Token\AccessToken; use ReflectionMethod; use SilverStripe\Control\Director; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Control\Session; use SilverStripe\Core\Config\Config; use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Injector\InjectorLoader; class ControllerTest extends TestCase { public function testFindBackUrl() { $back = Director::absoluteBaseURL() . 'test/'; $controller = new Controller; $reflectionMethod = new ReflectionMethod(Controller::class, 'findBackUrl'); $reflectionMethod->setAccessible(true); $mockSession = $this->getConstructorlessMock(Session::class, ['get']); $mockSession->expects($this->exactly(2)) ->method('get') ->with('BackURL') ->will($this->returnValue($back)); $mockRequest = $this->getConstructorlessMock(HTTPRequest::class, ['getSession']); $mockRequest->expects($this->exactly(3)) ->method('getSession') ->will($this->returnValue($mockSession)); $this->assertEquals($back, $reflectionMethod->invoke($controller, $mockRequest)); $mockRequest = $this->getConstructorlessMock(HTTPRequest::class, ['getSession', 'requestVar']); $mockRequest->expects($this->exactly(1)) ->method('getSession') ->will($this->returnValue(null)); $mockRequest->expects($this->exactly(2)) ->method('requestVar') ->with('BackURL') ->will($this->returnValue($back)); $this->assertEquals($back, $reflectionMethod->invoke($controller, $mockRequest)); $mockRequest = $this->getConstructorlessMock( HTTPRequest::class, ['getSession', 'requestVar', 'isAjax', 'getHeader'] ); $mockRequest->expects($this->exactly(1)) ->method('getSession') ->will($this->returnValue(null)); $mockRequest->expects($this->exactly(1)) ->method('requestVar') ->with('BackURL') ->will($this->returnValue(null)); $mockRequest->expects($this->exactly(1)) ->method('isAjax') ->will($this->returnValue(true)); $mockRequest->expects($this->exactly(2)) ->method('getHeader') ->with('X-Backurl') ->will($this->returnValue($back)); $this->assertEquals($back, $reflectionMethod->invoke($controller, $mockRequest)); $mockRequest = $this->getConstructorlessMock( HTTPRequest::class, ['getSession', 'requestVar', 'isAjax', 'getHeader'] ); $mockRequest->expects($this->exactly(1)) ->method('getSession') ->will($this->returnValue(null)); $mockRequest->expects($this->exactly(1)) ->method('requestVar') ->with('BackURL') ->will($this->returnValue(null)); $mockRequest->expects($this->exactly(1)) ->method('isAjax') ->will($this->returnValue(false)); $mockRequest->expects($this->exactly(2)) ->method('getHeader') ->with('Referer') ->will($this->returnValue($back)); $this->assertEquals($back, $reflectionMethod->invoke($controller, $mockRequest)); $mockRequest = $this->getConstructorlessMock(HTTPRequest::class, ['getSession', 'requestVar']); $mockRequest->expects($this->exactly(1)) ->method('getSession') ->will($this->returnValue(null)); $mockRequest->expects($this->exactly(2)) ->method('requestVar') ->with('BackURL') ->will($this->returnValue('http://1337h4x00r.com/geniune-oauth-url/i-promise')); $this->assertEquals(Director::absoluteBaseURL(), $reflectionMethod->invoke($controller, $mockRequest)); } public function testGetReturnUrl() { $back = Director::absoluteBaseURL() . 'test/'; $controller = new Controller; $reflectionMethod = new ReflectionMethod(Controller::class, 'getReturnUrl'); $reflectionMethod->setAccessible(true); $mockSession = $this->getConstructorlessMock(Session::class, ['get']); $mockSession->expects($this->once()) ->method('get') ->with('oauth2.backurl') ->will($this->returnValue($back)); $controller->getRequest()->setSession($mockSession); $this->assertEquals($back, $reflectionMethod->invoke($controller)); $mockSession = $this->getConstructorlessMock(Session::class, ['get']); $mockSession->expects($this->once()) ->method('get') ->with('oauth2.backurl') ->will($this->returnValue('http://1337h4x00r.com/geniune-oauth-url/i-promise')); $controller->getRequest()->setSession($mockSession); $this->assertEquals(Director::absoluteBaseURL(), $reflectionMethod->invoke($controller)); } public function testAuthenticate() { $mockRequest = $this->getConstructorlessMock(HTTPRequest::class, ['getVar']); $mockRequest->expects($this->at(0)) ->method('getVar') ->with('provider') ->will($this->returnValue('ProviderName')); $mockRequest->expects($this->at(1)) ->method('getVar') ->with('context') ->will($this->returnValue('testcontext')); $mockRequest->expects($this->at(2)) ->method('getVar') ->with('scope') ->will($this->returnValue(['test_scope'])); $mockProvider = $this->getConstructorlessMock( GenericProvider::class, ['getAuthorizationUrl', 'getState'] ); $mockProvider->expects($this->at(0)) ->method('getAuthorizationUrl') ->with(['scope' => ['test_scope']]) ->will($this->returnValue('http://example.com/oauth')); $mockProvider->expects($this->at(1)) ->method('getState') ->will($this->returnValue('mockstate')); $mockProviderFactory = $this->getMockBuilder(ProviderFactory::class) ->setMethods(['getProvider']) ->getMock(); $mockProviderFactory->expects($this->once()) ->method('getProvider') ->with('ProviderName') ->will($this->returnValue($mockProvider)); $mockSession = $this->getConstructorlessMock(Session::class, ['set']); $mockSession->expects($this->once()) ->method('set') ->with('oauth2', [ 'state' => 'mockstate', 'provider' => 'ProviderName', 'context' => 'testcontext', 'scope' => ['test_scope'], 'backurl' => 'http://mysite.com/return' ]); $mockInjector = $this->getMockBuilder(Injector::class) ->setMethods(['get']) ->getMock(); $mockInjector->expects($this->once()) ->method('get') ->with(ProviderFactory::class) ->will($this->returnValue($mockProviderFactory)); $mockController = $this->getMockBuilder(Controller::class) ->setMethods(['findBackUrl', 'redirect']) ->getMock(); $mockController->expects($this->at(0)) ->method('findBackUrl') ->with($mockRequest) ->will($this->returnValue('http://mysite.com/return')); $mockController->expects($this->at(1)) ->method('redirect') ->with('http://example.com/oauth') ->will($this->returnValue($response = new HTTPResponse)); // Inject mock InjectorLoader::inst()->pushManifest($mockInjector); $mockRequest->setSession($mockSession); $this->assertSame($response, $mockController->authenticate($mockRequest)); // Restore things InjectorLoader::inst()->popManifest(); } public function testAuthenticateMissingRequiredData() { $mockRequest = $this->getConstructorlessMock(HTTPRequest::class, ['getVar']); $mockRequest->expects($this->at(0)) ->method('getVar') ->with('provider') ->will($this->returnValue(null)); $mockRequest->expects($this->at(1)) ->method('getVar') ->with('context') ->will($this->returnValue(null)); $mockRequest->expects($this->at(2)) ->method('getVar') ->with('scope') ->will($this->returnValue(null)); $controller = new Controller(); try { $response = $controller->authenticate($mockRequest); $this->fail('SS_HTTPResponse_Exception was not thrown'); } catch (HTTPResponse_Exception $e) { $this->assertEquals(404, $e->getResponse()->getStatusCode()); } } public function testCallback() { // Store original $injector = Injector::inst(); $mockRequest = $this->getConstructorlessMock(HTTPRequest::class, ['getVar']); $mockRequest->expects($this->once()) ->method('getVar') ->with('code') ->will($this->returnValue('12345')); $mockAccessToken = $this->getConstructorlessMock(AccessToken::class); $mockProvider = $this->getConstructorlessMock(GenericProvider::class, ['getAccessToken']); $mockProvider->expects($this->once()) ->method('getAccessToken') ->with('authorization_code', ['code' => '12345']) ->will($this->returnValue($mockAccessToken)); $mockProviderFactory = $this->getMockBuilder(ProviderFactory::class) ->setMethods(['getProvider']) ->getMock(); $mockProviderFactory->expects($this->once()) ->method('getProvider') ->with('ProviderName') ->will($this->returnValue($mockProvider)); $mockTokenHandler = $this->getMockBuilder(TokenHandler::class) ->setMethods(['handleToken']) ->getMock(); $mockTokenHandler->expects($this->once()) ->method('handleToken') ->with($mockAccessToken, $mockProvider); $mockInjector = $this->getMockBuilder(Injector::class) ->setMethods(['get', 'create']) ->getMock(); $mockInjector->expects($this->at(0)) ->method('get') ->with(ProviderFactory::class) ->will($this->returnValue($mockProviderFactory)); $mockInjector->expects($this->at(1)) ->method('create') ->with('TestTokenHandler') ->will($this->returnValue($mockTokenHandler)); $mockSession = $this->getConstructorlessMock(Session::class, ['get', 'clear']); $mockSession->expects($this->at(0)) ->method('get') ->with('oauth2.provider') ->will($this->returnValue('ProviderName')); $mockSession->expects($this->at(1)) ->method('get') ->with('oauth2.context') ->will($this->returnValue('testcontext')); $mockSession->expects($this->at(2)) ->method('clear') ->with('oauth2'); $mockController = $this->getMockBuilder(Controller::class) ->setMethods(['validateState', 'getHandlersForContext', 'getReturnUrl', 'redirect']) ->getMock(); $mockController->expects($this->at(0)) ->method('validateState') ->with($mockRequest) ->will($this->returnValue(true)); $mockController->expects($this->at(1)) ->method('getReturnUrl') ->will($this->returnValue('http://mysite.com/return')); $mockController->expects($this->at(2)) ->method('getHandlersForContext') ->with('testcontext') ->will($this->returnValue([['priority' => 1, 'context' => 'testcontext', 'class' => 'TestTokenHandler']])); $mockController->expects($this->at(3)) ->method('redirect') ->with('http://mysite.com/return') ->will($this->returnValue($response = new HTTPResponse)); // Inject mock InjectorLoader::inst()->pushManifest($mockInjector); $mockRequest->setSession($mockSession); $this->assertSame($response, $mockController->callback($mockRequest)); // Restore things InjectorLoader::inst()->popManifest(); } public function testCallbackInvalidState() { $mockSession = $this->getConstructorlessMock(Session::class, ['clear']); $mockSession->expects($this->once()) ->method('clear') ->with('oauth2'); $mockRequest = $this->getConstructorlessMock(HTTPRequest::class, ['getSession']); $mockRequest->expects($this->once()) ->method('getSession') ->will($this->returnValue($mockSession)); $mockController = $this->getMockBuilder(Controller::class) ->setMethods(['validateState']) ->getMock(); $mockController->expects($this->at(0)) ->method('validateState') ->with($mockRequest) ->will($this->returnValue(false)); try { $response = $mockController->callback($mockRequest); $this->fail('HTTPResponse_Exception was not thrown'); } catch (HTTPResponse_Exception $e) { $this->assertEquals(400, $e->getResponse()->getStatusCode()); $this->assertEquals('Invalid session state.', $e->getResponse()->getBody()); } } /** * @expectedException \Exception */ public function testGetHandlersForContextWithNoHandlers() { Config::modify()->set(Controller::class, 'token_handlers', []); $controller = new Controller; $reflectionMethod = new ReflectionMethod(Controller::class, 'getHandlersForContext'); $reflectionMethod->setAccessible(true); $reflectionMethod->invoke($controller); } public function testGetHandlersForContext() { Config::modify()->set(Controller::class, 'token_handlers', [ 'globalhandlertwo' => [ 'priority' => 3, 'context' => '*', 'class' => 'GlobalHandlerTwo' ], 'namedhandlerone' => [ 'priority' => 1, 'context' => 'testcontext', 'class' => 'NamedHandlerOne' ], 'globalhandlerone' => [ 'priority' => 2, 'context' => '*', 'class' => 'GlobalHandlerOne' ], 'namedhandlertwo' => [ 'priority' => 1, 'context' => 'anothertestcontext', 'class' => 'NamedHandlerTwo' ] ]); $controller = new Controller; $reflectionMethod = new ReflectionMethod(Controller::class, 'getHandlersForContext'); $reflectionMethod->setAccessible(true); // Not giving a context should run all "global" handlers, but no named ones $expected = [ 'globalhandlerone' => [ 'priority' => 2, 'context' => '*', 'class' => 'GlobalHandlerOne' ], 'globalhandlertwo' => [ 'priority' => 3, 'context' => '*', 'class' => 'GlobalHandlerTwo' ] ]; $this->assertEquals($expected, $reflectionMethod->invoke($controller)); // Passing a context should run all "global" handlers, and those that match the context $expected = [ 'namedhandlerone' => [ 'priority' => 1, 'context' => 'testcontext', 'class' => 'NamedHandlerOne' ], 'globalhandlerone' => [ 'priority' => 2, 'context' => '*', 'class' => 'GlobalHandlerOne' ], 'globalhandlertwo' => [ 'priority' => 3, 'context' => '*', 'class' => 'GlobalHandlerTwo' ] ]; $this->assertEquals($expected, $reflectionMethod->invoke($controller, 'testcontext')); } } |