From 4172068e8927fd4dea6a62ae2def9371d3f814a3 Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 16 Aug 2014 13:46:11 +0200 Subject: [PATCH 1/9] Added a session layer between the session drivers and the other classes --- src/Cartalyst/Sentry/Sentry.php | 62 ++++++++---------- src/Cartalyst/Sentry/Sessions/Session.php | 76 +++++++++++++++++++++++ tests/SentryTest.php | 6 +- 3 files changed, 106 insertions(+), 38 deletions(-) create mode 100644 src/Cartalyst/Sentry/Sessions/Session.php diff --git a/src/Cartalyst/Sentry/Sentry.php b/src/Cartalyst/Sentry/Sentry.php index c0c2e8c02..df25d0308 100644 --- a/src/Cartalyst/Sentry/Sentry.php +++ b/src/Cartalyst/Sentry/Sentry.php @@ -34,8 +34,11 @@ use Cartalyst\Sentry\Users\UserInterface; use Cartalyst\Sentry\Users\UserNotFoundException; use Cartalyst\Sentry\Users\UserNotActivatedException; +use Cartalyst\Sentry\Sessions\Session; class Sentry { + const SESSION_KEY_PERSIST_CODE = 'persistCode'; + const SESSION_KEY_USER_ID = 'userId'; /** * The user that's been retrieved and is used @@ -47,19 +50,6 @@ class Sentry { */ protected $user; - /** - * The session driver used by Sentry. - * - * @var \Cartalyst\Sentry\Sessions\SessionInterface - */ - protected $session; - - /** - * The cookie driver used by Sentry. - * - * @var \Cartalyst\Sentry\Cookies\CookieInterface - */ - protected $cookie; /** * The user provider, used for retrieving @@ -95,6 +85,14 @@ class Sentry { */ protected $ipAddress = '0.0.0.0'; + + /** + * The session class + * + * @var \Cartalyst\Sentry\Groups\Sessions\Sentry + */ + protected $session; + /** * Create a new Sentry object. * @@ -119,8 +117,7 @@ public function __construct( $this->groupProvider = $groupProvider ?: new GroupProvider; $this->throttleProvider = $throttleProvider ?: new ThrottleProvider($this->userProvider); - $this->session = $session ?: new NativeSession; - $this->cookie = $cookie ?: new NativeCookie; + $this->session = new Session($session, $cookie); if (isset($ipAddress)) { @@ -245,21 +242,16 @@ public function check() { if (is_null($this->user)) { - // Check session first, follow by cookie - if ( ! $userArray = $this->session->get() and ! $userArray = $this->cookie->get()) - { - return false; - } + $id = $this->session->get(self::SESSION_KEY_USER_ID); + $persistCode = $this->session->get(self::SESSION_KEY_PERSIST_CODE); + - // Now check our user is an array with two elements, - // the username followed by the persist code - if ( ! is_array($userArray) or count($userArray) !== 2) + // If either user id or persist code is not set we are not logged in + if ($id == null || $persistCode == null) { return false; } - list($id, $persistCode) = $userArray; - // Let's find our user try { @@ -321,18 +313,15 @@ public function login(UserInterface $user, $remember = false) throw new UserNotActivatedException("Cannot login user [$login] as they are not activated."); } - $this->user = $user; - // Create an array of data to persist to the session and / or cookie - $toPersist = array($user->getId(), $user->getPersistCode()); + + $this->user = $user; // Set sessions - $this->session->put($toPersist); + $this->session->set(self::SESSION_KEY_USER_ID, $user->getId()); + $this->session->set(self::SESSION_KEY_PERSIST_CODE, $user->getPersistCode()); - if ($remember) - { - $this->cookie->forever($toPersist); - } + $remember && $this->session->forever(); // The user model can attach any handlers // to the "recordLogin" event. @@ -358,8 +347,7 @@ public function logout() { $this->user = null; - $this->session->forget(); - $this->cookie->forget(); + $this->session->destroy(); } /** @@ -397,7 +385,7 @@ public function getUser() */ public function setSession(SessionInterface $session) { - $this->session = $session; + $this->session->setSession($session); } /** @@ -407,7 +395,7 @@ public function setSession(SessionInterface $session) */ public function getSession() { - return $this->session; + return $this->session->getSession(); } /** diff --git a/src/Cartalyst/Sentry/Sessions/Session.php b/src/Cartalyst/Sentry/Sessions/Session.php new file mode 100644 index 000000000..fb106e166 --- /dev/null +++ b/src/Cartalyst/Sentry/Sessions/Session.php @@ -0,0 +1,76 @@ +session = $session ?: new NativeSession; + $this->cookie = $cookie ?: new NativeCookie; + } + + /** + * Sets a value in the session + */ + public function set($key, $value) + { + $values = $this->session->get(); + $values[$key] = $value; + $this->session->put($values); + } + + public function get($key) + { + $values = $this->session->get(); + !$values && $this->cookie->get(); + + return isset($values[$key]) ? $values[$key] : null; + } + + /** + * Destroys the session + */ + public function destroy() + { + $this->session->forget(); + $this->cookie->forget(); + } + + public function setSession(SessionInterface $session) + { + $this->session = $session; + } + + public function getSession() + { + return $this->session; + } + + public function forever() + { + $this->cookie->forever($this->session->get()); + } +} diff --git a/tests/SentryTest.php b/tests/SentryTest.php index 8e3be3c78..fe10459bd 100644 --- a/tests/SentryTest.php +++ b/tests/SentryTest.php @@ -87,7 +87,11 @@ public function testLoggingInUser() $user->shouldReceive('getPersistCode')->once()->andReturn('persist_code'); $user->shouldReceive('recordLogin')->once(); - $this->session->shouldReceive('put')->with(array('foo', 'persist_code'))->once(); + $session = m::mock('Cartalyst\Sentry\Sessions\Session'); + + $session->shouldReceive('set')->with(Sentry::SESSION_KEY_USER_ID, 'foo')->once(); + $session->shouldReceive('set')->with(Sentry::SESSION_KEY_PERSIST_CODE, 'persist_code')->once(); + $this->sentry->login($user); } From dce775f4e62d1c87b91bf96d1663217ef3bebc58 Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 16 Aug 2014 14:29:26 +0200 Subject: [PATCH 2/9] Renamed session.php to SessionHandlers, created an interface for it --- src/Cartalyst/Sentry/Sentry.php | 13 ++-- .../SessionHandlers/NativeSessionHandler.php | 76 +++++++++++++++++++ .../SessionHandlerInterface.php | 26 +++++++ src/Cartalyst/Sentry/Sessions/Session.php | 76 ------------------- tests/SentryTest.php | 40 +++++----- 5 files changed, 127 insertions(+), 104 deletions(-) create mode 100644 src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php create mode 100644 src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php diff --git a/src/Cartalyst/Sentry/Sentry.php b/src/Cartalyst/Sentry/Sentry.php index df25d0308..6b65c220a 100644 --- a/src/Cartalyst/Sentry/Sentry.php +++ b/src/Cartalyst/Sentry/Sentry.php @@ -25,6 +25,8 @@ use Cartalyst\Sentry\Hashing\NativeHasher; use Cartalyst\Sentry\Sessions\NativeSession; use Cartalyst\Sentry\Sessions\SessionInterface; +use Cartalyst\Sentry\SessionHandlers\SessionHandlerInterface; +use Cartalyst\Sentry\SessionHandlers\NativeSessionHandler; use Cartalyst\Sentry\Throttling\Eloquent\Provider as ThrottleProvider; use Cartalyst\Sentry\Throttling\ProviderInterface as ThrottleProviderInterface; use Cartalyst\Sentry\Users\LoginRequiredException; @@ -34,7 +36,6 @@ use Cartalyst\Sentry\Users\UserInterface; use Cartalyst\Sentry\Users\UserNotFoundException; use Cartalyst\Sentry\Users\UserNotActivatedException; -use Cartalyst\Sentry\Sessions\Session; class Sentry { const SESSION_KEY_PERSIST_CODE = 'persistCode'; @@ -87,9 +88,9 @@ class Sentry { /** - * The session class + * The session handler class * - * @var \Cartalyst\Sentry\Groups\Sessions\Sentry + * @var \Cartalyst\Sentry\SessionHandler\SessionHandlerInterface */ protected $session; @@ -108,8 +109,7 @@ public function __construct( UserProviderInterface $userProvider = null, GroupProviderInterface $groupProvider = null, ThrottleProviderInterface $throttleProvider = null, - SessionInterface $session = null, - CookieInterface $cookie = null, + SessionHandlerInterface $sessionHandler = null, $ipAddress = null ) { @@ -117,7 +117,8 @@ public function __construct( $this->groupProvider = $groupProvider ?: new GroupProvider; $this->throttleProvider = $throttleProvider ?: new ThrottleProvider($this->userProvider); - $this->session = new Session($session, $cookie); + + $this->session = $sessionHandler ?: new NativeSessionHandler(); if (isset($ipAddress)) { diff --git a/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php new file mode 100644 index 000000000..937ddd873 --- /dev/null +++ b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php @@ -0,0 +1,76 @@ +session = $session ?: new NativeSession; + $this->cookie = $cookie ?: new NativeCookie; + } + + /** + * Sets a value in the session + */ + public function set($key, $value) + { + $values = $this->session->get(); + $values[$key] = $value; + $this->session->put($values); + } + + public function get($key) + { + $values = $this->session->get(); + !$values && $this->cookie->get(); + + return isset($values[$key]) ? $values[$key] : null; + } + + /** + * Destroys the session + */ + public function destroy() + { + $this->session->forget(); + $this->cookie->forget(); + } + + public function setSession(SessionInterface $session) + { + $this->session = $session; + } + + public function getSession() + { + return $this->session; + } + + public function forever() + { + $this->cookie->forever($this->session->get()); + } +} diff --git a/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php b/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php new file mode 100644 index 000000000..a75b04926 --- /dev/null +++ b/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php @@ -0,0 +1,26 @@ +session = $session ?: new NativeSession; - $this->cookie = $cookie ?: new NativeCookie; - } - - /** - * Sets a value in the session - */ - public function set($key, $value) - { - $values = $this->session->get(); - $values[$key] = $value; - $this->session->put($values); - } - - public function get($key) - { - $values = $this->session->get(); - !$values && $this->cookie->get(); - - return isset($values[$key]) ? $values[$key] : null; - } - - /** - * Destroys the session - */ - public function destroy() - { - $this->session->forget(); - $this->cookie->forget(); - } - - public function setSession(SessionInterface $session) - { - $this->session = $session; - } - - public function getSession() - { - return $this->session; - } - - public function forever() - { - $this->cookie->forever($this->session->get()); - } -} diff --git a/tests/SentryTest.php b/tests/SentryTest.php index fe10459bd..b93ed165d 100644 --- a/tests/SentryTest.php +++ b/tests/SentryTest.php @@ -35,9 +35,7 @@ class SentryTest extends PHPUnit_Framework_TestCase { protected $hasher; - protected $session; - - protected $cookie; + protected $sessionHandler; protected $sentry; @@ -52,8 +50,7 @@ public function setUp() $this->userProvider = m::mock('Cartalyst\Sentry\Users\ProviderInterface'), $this->groupProvider = m::mock('Cartalyst\Sentry\Groups\ProviderInterface'), $this->throttleProvider = m::mock('Cartalyst\Sentry\Throttling\ProviderInterface'), - $this->session = m::mock('Cartalyst\Sentry\Sessions\SessionInterface'), - $this->cookie = m::mock('Cartalyst\Sentry\Cookies\CookieInterface') + $this->sessionHandler = m::mock('Cartalyst\Sentry\SessionHandlers\SessionHandlerInterface') ); } @@ -76,6 +73,7 @@ public function testLoggingInUnactivatedUser() $user->shouldReceive('isActivated')->once()->andReturn(false); $user->shouldReceive('getLogin')->once()->andReturn('foo'); + $this->sentry->login($user); } @@ -87,10 +85,9 @@ public function testLoggingInUser() $user->shouldReceive('getPersistCode')->once()->andReturn('persist_code'); $user->shouldReceive('recordLogin')->once(); - $session = m::mock('Cartalyst\Sentry\Sessions\Session'); - $session->shouldReceive('set')->with(Sentry::SESSION_KEY_USER_ID, 'foo')->once(); - $session->shouldReceive('set')->with(Sentry::SESSION_KEY_PERSIST_CODE, 'persist_code')->once(); + $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_USER_ID, 'foo')->once(); + $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_PERSIST_CODE, 'persist_code')->once(); $this->sentry->login($user); @@ -227,8 +224,7 @@ public function testAuthenticatingUser() $this->userProvider, $this->groupProvider, $this->throttleProvider, - $this->session, - $this->cookie + $this->sessionHandler ); $credentials = array( @@ -256,8 +252,7 @@ public function testAuthenticatingUserWithThrottling() $this->userProvider, $this->groupProvider, $this->throttleProvider, - $this->session, - $this->cookie + $this->sessionHandler ); $credentials = array( @@ -310,12 +305,11 @@ public function testAuthenticatingUserAndRemembering() public function testCheckLoggingOut() { $this->sentry->setUser(m::mock('Cartalyst\Sentry\Users\UserInterface')); - $this->session->shouldReceive('get')->once(); - $this->session->shouldReceive('forget')->once(); - $this->cookie->shouldReceive('get')->once(); - $this->cookie->shouldReceive('forget')->once(); - + $this->sessionHandler->shouldReceive('destroy')->once(); $this->sentry->logout(); + + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_USER_ID)->once()->andReturn(null); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_PERSIST_CODE)->once()->andReturn(null); $this->assertNull($this->sentry->getUser()); } @@ -345,14 +339,14 @@ public function testCheckingUserWhenUserIsSetAndSuspended() $throttle->shouldReceive('isBanned')->once()->andReturn(false); $throttle->shouldReceive('isSuspended')->once()->andReturn(true); - $session->shouldReceive('forget')->once(); - $cookie->shouldReceive('forget')->once(); - $user->shouldReceive('isActivated')->once()->andReturn(true); $this->throttleProvider->shouldReceive('findByUser')->once()->andReturn($throttle); $this->throttleProvider->shouldReceive('isEnabled')->once()->andReturn(true); + $this->sessionHandler->shouldReceive('setSession')->once(); + $this->sessionHandler->shouldReceive('destroy')->once(); + $this->sentry->setSession($session); $this->sentry->setCookie($cookie); $this->sentry->setUser($user); @@ -368,8 +362,8 @@ public function testCheckingUserWhenUserIsSetAndBanned() $throttle->shouldReceive('isBanned')->once()->andReturn(true); - $session->shouldReceive('forget')->once(); - $cookie->shouldReceive('forget')->once(); + $this->sessionHandler->shouldReceive('setSession')->once(); + $this->sessionHandler->shouldReceive('destroy')->once(); $user->shouldReceive('isActivated')->once()->andReturn(true); @@ -388,6 +382,8 @@ public function testCheckingUserWhenUserIsSetAndNotActivated() $user->shouldReceive('isActivated')->once()->andReturn(false); $this->sentry->setUser($user); + + $this->assertFalse($this->sentry->check()); } From 28007ed0d1ef79e107f8a58566d3e8ad0646231d Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 16 Aug 2014 14:38:13 +0200 Subject: [PATCH 3/9] Fixed existing test cases. Deleted irrelevant test cases, added some new test cases --- tests/SentryTest.php | 61 +++++++++----------------------------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/tests/SentryTest.php b/tests/SentryTest.php index b93ed165d..7f0aea4b1 100644 --- a/tests/SentryTest.php +++ b/tests/SentryTest.php @@ -387,65 +387,28 @@ public function testCheckingUserWhenUserIsSetAndNotActivated() $this->assertFalse($this->sentry->check()); } - public function testCheckingUserChecksSessionFirst() - { - $this->session->shouldReceive('get')->once()->andReturn(array('foo', 'persist_code')); - $this->cookie->shouldReceive('get')->never(); - - $throttle = m::mock('Cartalyst\Sentry\Throttling\ThrottleInterface'); - $throttle->shouldReceive('isBanned')->once()->andReturn(false); - $throttle->shouldReceive('isSuspended')->once()->andReturn(false); - - $this->throttleProvider->shouldReceive('findByUser')->once()->andReturn($throttle); - $this->throttleProvider->shouldReceive('isEnabled')->once()->andReturn(true); - - $this->userProvider->shouldReceive('findById')->andReturn($user = m::mock('Cartalyst\Sentry\Users\UserInterface')); - - $user->shouldReceive('checkPersistCode')->with('persist_code')->once()->andReturn(true); - $user->shouldReceive('isActivated')->once()->andReturn(true); - $this->assertTrue($this->sentry->check()); - } - - public function testCheckingUserChecksSessionFirstAndThenCookie() + public function testCheckingUserReturnsFalseIfUseridIsNull() { - $this->session->shouldReceive('get')->once(); - $this->cookie->shouldReceive('get')->once()->andReturn(array('foo', 'persist_code')); - - $throttle = m::mock('Cartalyst\Sentry\Throttling\ThrottleInterface'); - $throttle->shouldReceive('isBanned')->once()->andReturn(false); - $throttle->shouldReceive('isSuspended')->once()->andReturn(false); - - $this->userProvider->shouldReceive('findById')->andReturn($user = m::mock('Cartalyst\Sentry\Users\UserInterface')); - $this->throttleProvider->shouldReceive('findByUser')->once()->andReturn($throttle); - $this->throttleProvider->shouldReceive('isEnabled')->once()->andReturn(true); - - $user->shouldReceive('checkPersistCode')->with('persist_code')->once()->andReturn(true); - $user->shouldReceive('isActivated')->once()->andReturn(true); - - $this->assertTrue($this->sentry->check()); - } - - public function testCheckingUserReturnsFalseIfNoArrayIsReturned() - { - $this->session->shouldReceive('get')->once()->andReturn('we_should_never_return_a_string'); - + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_USER_ID)->once()->andReturn(null); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_PERSIST_CODE)->once()->andReturn('persist_code'); + $this->assertFalse($this->sentry->check()); } - public function testCheckingUserReturnsFalseIfIncorrectArrayIsReturned() + public function testCheckingUserReturnsFalseIfPersistCodeIsNull() { - $this->session->shouldReceive('get')->once()->andReturn(array('we', 'should', 'never', 'have', 'more', 'than', 'two')); - + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_USER_ID)->once()->andReturn('user_id'); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_PERSIST_CODE)->once()->andReturn(null); + $this->assertFalse($this->sentry->check()); } - public function testCheckingUserWhenNothingIsFound() + public function testCheckingUserReturnsFalseIfPersistCodeAndUserIdIsNull() { - $this->session->shouldReceive('get')->once()->andReturn(null); - - $this->cookie->shouldReceive('get')->once()->andReturn(null); - + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_USER_ID)->once()->andReturn(null); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_PERSIST_CODE)->once()->andReturn(null); + $this->assertFalse($this->sentry->check()); } From 76c0704e35b27ebf78b7bfcbaa2db265822fb383 Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 16 Aug 2014 15:16:25 +0200 Subject: [PATCH 4/9] Made test cases for NativeSessionHandler --- .../SessionHandlers/NativeSessionHandler.php | 13 +- tests/NativeSessionHandlerTest.php | 191 ++++++++++++++++++ 2 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 tests/NativeSessionHandlerTest.php diff --git a/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php index 937ddd873..1c082e368 100644 --- a/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php +++ b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php @@ -45,7 +45,7 @@ public function set($key, $value) public function get($key) { $values = $this->session->get(); - !$values && $this->cookie->get(); + !isset($values[$key]) && $values = $this->cookie->get(); return isset($values[$key]) ? $values[$key] : null; } @@ -71,6 +71,15 @@ public function getSession() public function forever() { - $this->cookie->forever($this->session->get()); + // Make sure that the values that are forever are not lost + $cookie = $this->cookie->get(); + $session = $this->session->get(); + if ($cookie == null) { + $cookie = $session; + } else if($session != null) { + $cookie = array_merge($cookie, $this->session->get()); + } + + $this->cookie->forever($cookie); } } diff --git a/tests/NativeSessionHandlerTest.php b/tests/NativeSessionHandlerTest.php new file mode 100644 index 000000000..b97fde50e --- /dev/null +++ b/tests/NativeSessionHandlerTest.php @@ -0,0 +1,191 @@ +sessionHandler = new NativeSessionHandler( + $this->session = m::mock('Cartalyst\Sentry\Sessions\SessionInterface'), + $this->cookie = m::mock('Cartalyst\Sentry\Cookies\CookieInterface') + ); + } + + /** + * Check if a session is set correctly if the session is empty before + */ + public function testSetWithEmptySession() { + $this->session->shouldReceive('get')->once()->andReturn(null); + $this->session->shouldReceive('put')->once()->with(array('test' => 1)); + $this->sessionHandler->set('test', 1); + } + + /** + * check if a session is set correctly if the session was not empty before + */ + public function testSetWithNonEmptySession() { + $this->session->shouldReceive('get')->once()->andReturn(array('foo' => 'bar')); + $this->session->shouldReceive('put')->once()->with(array('test' => 1, 'foo' => 'bar')); + + $this->sessionHandler->set('test', 1); + } + + /** + * Check if get($key) return null if the key does not exists + */ + public function testGetReturnsNullIfValueDoesNotExist() { + $this->session->shouldReceive('get')->once()->andReturn(array('foo' => 'bar')); + $this->cookie->shouldReceive('get')->once()->andReturn(array('foo' => 'bar')); + $this->assertNull($this->sessionHandler->get('bizz')); + } + + /** + * Check if get($key) return null if no session is set + */ + public function testGetReturnsNullIfNoSessionIsSet() { + $this->session->shouldReceive('get')->once()->andReturn(null); + $this->cookie->shouldReceive('get')->once()->andReturn(null); + $this->assertNull($this->sessionHandler->get('bizz')); + } + + /** + * check if get($key) returns the correct value if it is set in session + */ + public function testGetReturnsIfIsSetInSession() { + $this->session->shouldReceive('get')->once()->andReturn(array('foo' => 'bar')); + $this->assertEquals('bar', $this->sessionHandler->get('foo')); + } + + /** + * check if get($key) returns the correct value if it is set in Cookie, and not in session + */ + public function testGetReturnsIfIsSetInCookieNoSession() { + $this->session->shouldReceive('get')->once()->andReturn(null); + $this->cookie->shouldReceive('get')->once()->andReturn(array('foo' => 'bar')); + $this->assertEquals('bar', $this->sessionHandler->get('foo')); + } + + /** + * check if get($key) returns the correct value if it is set in Cookie, and session is set + * but with different values + */ + public function testGetReturnsIfIsSetInCookieWithSession() { + $this->session->shouldReceive('get')->once()->andReturn(array('fuzz' => 'bizz')); + $this->cookie->shouldReceive('get')->once()->andReturn(array('foo' => 'bar')); + $this->assertEquals('bar', $this->sessionHandler->get('foo')); + } + + /** + * Checks if the destroy method destroys both the session and cookie + */ + public function testDestroyShouldForgetBothSessionAndCookie() { + $this->session->shouldReceive('forget')->once(); + $this->cookie->shouldReceive('forget')->once(); + $this->sessionHandler->destroy(); + } + + /** + * Check if setSession/getSession works + */ + public function testSetGetSession() { + $newSession = m::mock('Cartalyst\Sentry\Sessions\SessionInterface'); + $this->sessionHandler->setSession($newSession); + + $newSession->shouldReceive('put')->with(array('foo' => 'bar'))->once(); + $newSession->shouldReceive('get')->andReturn(null); + $this->sessionHandler->set('foo', 'bar'); + $this->assertEquals($newSession, $this->sessionHandler->getSession()); + } + + /** + * Forever should push the current session to the cookie + */ + public function testForeverPushesSessionToCookie() { + $this->cookie->shouldReceive('get')->andReturn(null); + $this->session->shouldReceive('get')->andReturn(array('foo' => 'bar')); + $this->cookie->shouldReceive('forever')->with(array('foo' => 'bar')); + $this->sessionHandler->forever(); + } + + /** + * Forever should push the current session to the cookie, but keep the existing values + */ + public function testForeverKeepsCookieValues() { + $this->cookie->shouldReceive('get')->andReturn(array('fizz' => 'buzz')); + $this->session->shouldReceive('get')->andReturn(array('foo' => 'bar')); + $this->cookie->shouldReceive('forever')->with(array('foo' => 'bar', 'fizz' => 'buzz')); + $this->sessionHandler->forever(); + } + + /** + * Forever should do nothing if the session is null + */ + public function testForeverKeepsCookieValuesIfSessionIsNull() { + $this->cookie->shouldReceive('get')->andReturn(array('fizz' => 'buzz')); + $this->session->shouldReceive('get')->andReturn(null); + $this->cookie->shouldReceive('forever')->with(array('fizz' => 'buzz')); + $this->sessionHandler->forever(); + } + + + /** + * Forever should do nothing if the session is null and cookie is null + */ + public function testForeverDoesNothingIfSessionAndCookieAreNull() { + $this->cookie->shouldReceive('get')->andReturn(null); + $this->session->shouldReceive('get')->andReturn(null); + $this->cookie->shouldReceive('forever')->with(null); + $this->sessionHandler->forever(); + } + + /** + * If a value exists in both the cookie as well as in the session, the cookie should be overridden + */ + public function testForeverSessionShouldOverrideCookie() { + $this->cookie->shouldReceive('get')->andReturn(array('foo' => 'bar1')); + $this->session->shouldReceive('get')->andReturn(array('foo' => 'bar2')); + $this->cookie->shouldReceive('forever')->with(array('foo' => 'bar2')); + $this->sessionHandler->forever(); + } + +} From 3831ff4cecf8c96725177b9798ef149876230cd2 Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 16 Aug 2014 15:23:32 +0200 Subject: [PATCH 5/9] Added documentation --- .../SessionHandlers/NativeSessionHandler.php | 27 ++++++++-- .../SessionHandlerInterface.php | 50 ++++++++++++++++++- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php index 1c082e368..96bcbe271 100644 --- a/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php +++ b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php @@ -3,9 +3,26 @@ use Cartalyst\Sentry\Cookies\NativeCookie; use Cartalyst\Sentry\Sessions\NativeSession; use Cartalyst\Sentry\Sessions\SessionInterface; + /** - * General session class. Will handle sessions more easily + * Part of the Sentry package. + * + * NOTICE OF LICENSE + * + * Licensed under the 3-clause BSD License. + * + * This source file is subject to the 3-clause BSD License that is + * bundled with this package in the LICENSE file. It is also available at + * the following URL: http://www.opensource.org/licenses/BSD-3-Clause + * + * @package Sentry + * @version 2.0.0 + * @author Cartalyst LLC + * @license BSD License (3-clause) + * @copyright (c) 2011 - 2013, Cartalyst LLC + * @link http://cartalyst.com */ + class NativeSessionHandler implements SessionHandlerInterface { /** @@ -22,8 +39,12 @@ class NativeSessionHandler implements SessionHandlerInterface */ protected $cookie; - - + /** + * Construct a new SessionHandler + * + * @param Cartalyst\Sentry\Sessions\SessionInterface $session The sessiondriver + * @param Cartalyst\Sentry\Cookies\CookieInterface $cookie The CookieInterface + */ public function __construct( SessionInterface $session = null, CookieInterface $cookie = null diff --git a/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php b/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php index a75b04926..4ebcd0ccf 100644 --- a/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php +++ b/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php @@ -3,24 +3,72 @@ use Cartalyst\Sentry\Cookies\NativeCookie; use Cartalyst\Sentry\Sessions\NativeSession; use Cartalyst\Sentry\Sessions\SessionInterface; + /** - * General session class. Will handle sessions more easily + * Part of the Sentry package. + * + * NOTICE OF LICENSE + * + * Licensed under the 3-clause BSD License. + * + * This source file is subject to the 3-clause BSD License that is + * bundled with this package in the LICENSE file. It is also available at + * the following URL: http://www.opensource.org/licenses/BSD-3-Clause + * + * @package Sentry + * @version 2.0.0 + * @author Cartalyst LLC + * @license BSD License (3-clause) + * @copyright (c) 2011 - 2013, Cartalyst LLC + * @link http://cartalyst.com */ + interface SessionHandlerInterface { /** * Sets a value in the session + * + * @param string $key The key of the value to be set + * @param mixed $value The value to be set + * @return void */ public function set($key, $value); + /** + * Get a value in the session + * + * @param string $key The key of the value to get + * @return void + */ public function get($key); + /** + * Completely destroy the session + * + * @return true; + */ public function destroy(); + /** + * Set the session interface for this handler + * + * @param Cartalyst\Sentry\Sessions\SessionInterface $session The Sessioninterface to set + * @return void + */ public function setSession(SessionInterface $session); + /** + * Get the sessiondriver + * + * @return Cartalyst\Sentry\Sessions\SessionInterface + */ public function getSession(); + /** + * Make the session be kept forever + * + * @return void + */ public function forever(); } From cabb7d11ccfb3df4a071de27e710a9086386bf65 Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 16 Aug 2014 15:33:13 +0200 Subject: [PATCH 6/9] Updated facades --- src/Cartalyst/Sentry/Facades/CI/Sentry.php | 7 +++++-- src/Cartalyst/Sentry/Facades/FuelPHP/Sentry.php | 7 +++++-- src/Cartalyst/Sentry/Facades/Kohana/Sentry.php | 7 +++++-- src/Cartalyst/Sentry/Facades/Native/Sentry.php | 7 +++++-- .../Sentry/SessionHandlers/SessionHandlerInterface.php | 1 - src/Cartalyst/Sentry/Sessions/Session.php | 0 6 files changed, 20 insertions(+), 9 deletions(-) delete mode 100644 src/Cartalyst/Sentry/Sessions/Session.php diff --git a/src/Cartalyst/Sentry/Facades/CI/Sentry.php b/src/Cartalyst/Sentry/Facades/CI/Sentry.php index ebd84eef2..c0939cef3 100644 --- a/src/Cartalyst/Sentry/Facades/CI/Sentry.php +++ b/src/Cartalyst/Sentry/Facades/CI/Sentry.php @@ -27,6 +27,7 @@ use Cartalyst\Sentry\Sentry as BaseSentry; use Cartalyst\Sentry\Throttling\Eloquent\Provider as ThrottleProvider; use Cartalyst\Sentry\Users\Eloquent\Provider as UserProvider; +use Cartalyst\Sentry\SessionHandlers\NativeSessionHandler; use Illuminate\Database\Eloquent\Model as Eloquent; use PDO; @@ -89,8 +90,10 @@ public static function createSentry() $userProvider = new UserProvider(new NativeHasher), new GroupProvider, new ThrottleProvider($userProvider), - new CISession($ci->session), - new CICookie($ci->input), + new NativeSessionHandler( + new CISession($ci->session), + new CICookie($ci->input) + ), $ci->input->ip_address() ); } diff --git a/src/Cartalyst/Sentry/Facades/FuelPHP/Sentry.php b/src/Cartalyst/Sentry/Facades/FuelPHP/Sentry.php index 9b5abcf2c..d8080f27f 100644 --- a/src/Cartalyst/Sentry/Facades/FuelPHP/Sentry.php +++ b/src/Cartalyst/Sentry/Facades/FuelPHP/Sentry.php @@ -23,6 +23,7 @@ use Cartalyst\Sentry\Facades\Facade; use Cartalyst\Sentry\Groups\Eloquent\Provider as GroupProvider; use Cartalyst\Sentry\Hashing\NativeHasher; +use Cartalyst\Sentry\SessionHandlers\NativeSessionHandler; use Cartalyst\Sentry\Sessions\FuelPHPSession; use Cartalyst\Sentry\Sentry as BaseSentry; use Cartalyst\Sentry\Throttling\Eloquent\Provider as ThrottleProvider; @@ -65,8 +66,10 @@ public static function createSentry() $userProvider = new UserProvider(new NativeHasher), new GroupProvider, new ThrottleProvider($userProvider), - new FuelPHPSession(Session::instance()), - new FuelPHPCookie, + new NativeSessionHandler( + new FuelPHPSession(Session::instance()), + new FuelPHPCookie + ), Input::real_ip() ); } diff --git a/src/Cartalyst/Sentry/Facades/Kohana/Sentry.php b/src/Cartalyst/Sentry/Facades/Kohana/Sentry.php index 183157ca4..d484416ab 100644 --- a/src/Cartalyst/Sentry/Facades/Kohana/Sentry.php +++ b/src/Cartalyst/Sentry/Facades/Kohana/Sentry.php @@ -23,6 +23,7 @@ use Cartalyst\Sentry\Groups\Kohana\Provider as GroupProvider; use Cartalyst\Sentry\Sessions\KohanaSession; use Cartalyst\Sentry\Sentry as BaseSentry; +use Cartalyst\Sentry\SessionHandlers\NativeSessionHandler; use Cartalyst\Sentry\Throttling\Kohana\Provider as ThrottleProvider; use Cartalyst\Sentry\Users\Kohana\Provider as UserProvider; @@ -67,8 +68,10 @@ public static function createSentry() $userProvider = new UserProvider($hasher), new GroupProvider, new ThrottleProvider($userProvider), - new KohanaSession(\Session::instance($config['session_driver']), $config['session_key']), - new KohanaCookie($config['cookie_key']), + new NativeSessionHandler( + new KohanaSession(\Session::instance($config['session_driver']), $config['session_key']), + new KohanaCookie($config['cookie_key']) + ), \Request::$client_ip ); } diff --git a/src/Cartalyst/Sentry/Facades/Native/Sentry.php b/src/Cartalyst/Sentry/Facades/Native/Sentry.php index d696c08d2..73a7fa881 100644 --- a/src/Cartalyst/Sentry/Facades/Native/Sentry.php +++ b/src/Cartalyst/Sentry/Facades/Native/Sentry.php @@ -27,6 +27,7 @@ use Cartalyst\Sentry\Hashing\NativeHasher; use Cartalyst\Sentry\Sessions\NativeSession; use Cartalyst\Sentry\Sessions\SessionInterface; +use Cartalyst\Sentry\SessionHandlers\NativeSessionHandler; use Cartalyst\Sentry\Sentry as BaseSentry; use Cartalyst\Sentry\Throttling\Eloquent\Provider as ThrottleProvider; use Cartalyst\Sentry\Throttling\ProviderInterface as ThrottleProviderInterface; @@ -63,8 +64,10 @@ public static function createSentry( $userProvider, $groupProvider ?: new GroupProvider, $throttleProvider ?: new ThrottleProvider($userProvider), - $session ?: new NativeSession, - $cookie ?: new NativeCookie, + new NativeSessionHandler( + $session ?: new NativeSession, + $cookie ?: new NativeCookie, + ), $ipAddress ?: static::guessIpAddress() ); } diff --git a/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php b/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php index 4ebcd0ccf..46d5e7d19 100644 --- a/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php +++ b/src/Cartalyst/Sentry/SessionHandlers/SessionHandlerInterface.php @@ -25,7 +25,6 @@ interface SessionHandlerInterface { - /** * Sets a value in the session * diff --git a/src/Cartalyst/Sentry/Sessions/Session.php b/src/Cartalyst/Sentry/Sessions/Session.php deleted file mode 100644 index e69de29bb..000000000 From 82bcb2221c78e9de56d39fcf2132f173c15793fd Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 16 Aug 2014 16:31:18 +0200 Subject: [PATCH 7/9] Added Masquerading feature --- src/Cartalyst/Sentry/Sentry.php | 37 ++++ tests/SentryTest.php | 329 ++++++++++++++++++++++---------- 2 files changed, 265 insertions(+), 101 deletions(-) diff --git a/src/Cartalyst/Sentry/Sentry.php b/src/Cartalyst/Sentry/Sentry.php index 6b65c220a..3d79a4957 100644 --- a/src/Cartalyst/Sentry/Sentry.php +++ b/src/Cartalyst/Sentry/Sentry.php @@ -40,6 +40,7 @@ class Sentry { const SESSION_KEY_PERSIST_CODE = 'persistCode'; const SESSION_KEY_USER_ID = 'userId'; + const SESSION_MASQUERADE_STACK = 'masqueradeStack'; /** * The user that's been retrieved and is used @@ -702,6 +703,42 @@ public function findThrottlerByUserLogin($login, $ipAddress = null) return $this->throttleProvider->findByUserLogin($login,$ipAddress); } + /** + * Masquerades as another user + * + * @param \Cartalyst\Sentry\User\UserInterface $user User to masquerade as + * @return void + */ + public function masquerade(UserInterface $user) + { + if (!$this->check()) { + throw new LoginRequiredException(); + } + + $old[static::SESSION_KEY_USER_ID] = $this->session->get(static::SESSION_KEY_USER_ID); + $old[static::SESSION_KEY_PERSIST_CODE] = $this->session->get(static::SESSION_KEY_PERSIST_CODE); + $stack = $this->session->get(static::SESSION_MASQUERADE_STACK) ?: array(); + array_push($stack, $old); + $this->session->set(static::SESSION_MASQUERADE_STACK, $stack); + $this->login($user); + } + + /** + * LogOut of masquerade. Behaves like a normal logout of person is not masqueraded + * + * @return void + */ + public function masqueradedLogout() { + $stack = $this->session->get(static::SESSION_MASQUERADE_STACK); + if ($stack == null || !($oldUser = array_pop($stack))) { + return $this->LogOut(); + } + + $this->session->set(static::SESSION_KEY_USER_ID, $oldUser[static::SESSION_KEY_USER_ID]); + $this->session->set(static::SESSION_KEY_PERSIST_CODE, $oldUser[static::SESSION_KEY_PERSIST_CODE]); + $this->user = $this->userProvider->findUserById($oldUser[static::SESSION_KEY_USER_ID]); + } + /** * Handle dynamic method calls into the method. * diff --git a/tests/SentryTest.php b/tests/SentryTest.php index 7f0aea4b1..729b389c5 100644 --- a/tests/SentryTest.php +++ b/tests/SentryTest.php @@ -455,106 +455,233 @@ public function testGetUserWithCheck() $sentry->getUser(); } - public function testFindGroupById() - { - $this->groupProvider->shouldReceive('findById')->once()->andReturn(true); - $this->assertTrue($this->sentry->findGroupByID(1)); - } - - public function testFindGroupByName() - { - $this->groupProvider->shouldReceive('findByName')->once()->andReturn(true); - $this->assertTrue($this->sentry->findGroupByName("name")); - } - - public function testFindAllGroups() - { - $this->groupProvider->shouldReceive('findAll')->once()->andReturn(true); - $this->assertTrue($this->sentry->findAllGroups()); - } - - public function testCreateGroup() - { - $this->groupProvider->shouldReceive('create')->once()->andReturn(true); - $this->assertTrue($this->sentry->createGroup(array())); - } - - public function testFindUserByID() - { - $this->userProvider->shouldReceive('findById')->once()->andReturn(true); - $this->assertTrue($this->sentry->findUserById(1)); - } - public function testFindUserByLogin() - { - $this->userProvider->shouldReceive('findByLogin')->once()->andReturn(true); - $this->assertTrue($this->sentry->findUserByLogin("login")); - } - - public function testFindUserByCredentials() - { - $this->userProvider->shouldReceive('findByCredentials')->once()->andReturn(true); - $this->assertTrue($this->sentry->findUserByCredentials(array())); - } - - public function testFindUserByActivationCode() - { - $this->userProvider->shouldReceive('findByActivationCode')->once()->andReturn(true); - $this->assertTrue($this->sentry->findUserByActivationCode("x")); - } - - public function testFindUserByResetPasswordCode() - { - $this->userProvider->shouldReceive('findByResetPasswordCode')->once()->andReturn(true); - $this->assertTrue($this->sentry->findUserByResetPasswordCode("x")); - } - - public function testFindAllUsers() - { - $this->userProvider->shouldReceive('findAll')->once()->andReturn(true); - $this->assertTrue($this->sentry->findAllUsers()); - } - - public function testFindAllUsersInGroup() - { - $group = m::mock('Cartalyst\Sentry\Groups\GroupInterface'); - $this->userProvider->shouldReceive('findAllInGroup')->once()->andReturn(true); - $this->assertTrue($this->sentry->findAllUsersInGroup($group)); - } - - public function testFindAllUsersWithAccess() - { - $this->userProvider->shouldReceive('findAllWithAccess')->once()->andReturn(true); - $this->assertTrue($this->sentry->findAllUsersWithAccess("")); - } - - public function testFindAllUsersWithAnyAccess() - { - $this->userProvider->shouldReceive('findAllWithAnyAccess')->once()->andReturn(true); - $this->assertTrue($this->sentry->findAllUsersWithAnyAccess(array())); - } - - public function testCreateUser() - { - $this->userProvider->shouldReceive('create')->once()->andReturn(true); - $this->assertTrue($this->sentry->createUser(array())); - } - - public function testGetEmptyUser() - { - $this->userProvider->shouldReceive('getEmptyUser')->once()->andReturn(true); - $this->assertTrue($this->sentry->getEmptyUser()); - } - - public function testFindThrottlerByUserID() - { - $this->throttleProvider->shouldReceive('findByUserId')->once()->andReturn(true); - $this->assertTrue($this->sentry->findThrottlerByUserId(1)); - } - - public function testFindThrottlerByUserLogin() - { - $this->throttleProvider->shouldReceive('findByUserLogin')->once()->andReturn(true); - $this->assertTrue($this->sentry->findThrottlerByUserLogin("X")); - } + public function testFindGroupById() + { + $this->groupProvider->shouldReceive('findById')->once()->andReturn(true); + $this->assertTrue($this->sentry->findGroupByID(1)); + } + + public function testFindGroupByName() + { + $this->groupProvider->shouldReceive('findByName')->once()->andReturn(true); + $this->assertTrue($this->sentry->findGroupByName("name")); + } + + public function testFindAllGroups() + { + $this->groupProvider->shouldReceive('findAll')->once()->andReturn(true); + $this->assertTrue($this->sentry->findAllGroups()); + } + + public function testCreateGroup() + { + $this->groupProvider->shouldReceive('create')->once()->andReturn(true); + $this->assertTrue($this->sentry->createGroup(array())); + } + + public function testFindUserByID() + { + $this->userProvider->shouldReceive('findById')->once()->andReturn(true); + $this->assertTrue($this->sentry->findUserById(1)); + } + public function testFindUserByLogin() + { + $this->userProvider->shouldReceive('findByLogin')->once()->andReturn(true); + $this->assertTrue($this->sentry->findUserByLogin("login")); + } + + public function testFindUserByCredentials() + { + $this->userProvider->shouldReceive('findByCredentials')->once()->andReturn(true); + $this->assertTrue($this->sentry->findUserByCredentials(array())); + } + + public function testFindUserByActivationCode() + { + $this->userProvider->shouldReceive('findByActivationCode')->once()->andReturn(true); + $this->assertTrue($this->sentry->findUserByActivationCode("x")); + } + public function testFindUserByResetPasswordCode() + { + $this->userProvider->shouldReceive('findByResetPasswordCode')->once()->andReturn(true); + $this->assertTrue($this->sentry->findUserByResetPasswordCode("x")); + } + + public function testFindAllUsers() + { + $this->userProvider->shouldReceive('findAll')->once()->andReturn(true); + $this->assertTrue($this->sentry->findAllUsers()); + } + + public function testFindAllUsersInGroup() + { + $group = m::mock('Cartalyst\Sentry\Groups\GroupInterface'); + $this->userProvider->shouldReceive('findAllInGroup')->once()->andReturn(true); + $this->assertTrue($this->sentry->findAllUsersInGroup($group)); + } + + public function testFindAllUsersWithAccess() + { + $this->userProvider->shouldReceive('findAllWithAccess')->once()->andReturn(true); + $this->assertTrue($this->sentry->findAllUsersWithAccess("")); + } + + public function testFindAllUsersWithAnyAccess() + { + $this->userProvider->shouldReceive('findAllWithAnyAccess')->once()->andReturn(true); + $this->assertTrue($this->sentry->findAllUsersWithAnyAccess(array())); + } + + public function testCreateUser() + { + $this->userProvider->shouldReceive('create')->once()->andReturn(true); + $this->assertTrue($this->sentry->createUser(array())); + } + + public function testGetEmptyUser() + { + $this->userProvider->shouldReceive('getEmptyUser')->once()->andReturn(true); + $this->assertTrue($this->sentry->getEmptyUser()); + } + + public function testFindThrottlerByUserID() + { + $this->throttleProvider->shouldReceive('findByUserId')->once()->andReturn(true); + $this->assertTrue($this->sentry->findThrottlerByUserId(1)); + } + + public function testFindThrottlerByUserLogin() + { + $this->throttleProvider->shouldReceive('findByUserLogin')->once()->andReturn(true); + $this->assertTrue($this->sentry->findThrottlerByUserLogin("X")); + } + + /** + * Simple masquerade check + */ + public function testSimpleMasquerade() + { + $user = m::mock('Cartalyst\Sentry\Users\UserInterface'); + + $this->userProvider->shouldReceive('findById')->once()->andReturn($userOld = m::mock('Cartalyst\Sentry\Users\UserInterface')); + + + $userOld->shouldReceive('checkPersistCode')->andReturn(true); + $userOld->shouldReceive('isActivated')->andReturn(true); + $userOld->shouldReceive('isEnabled')->andReturn(true); + $userOld->shouldReceive('isBanned')->andReturn(false); + $userOld->shouldReceive('isSuspended')->andReturn(false); + + $this->throttleProvider->shouldReceive('findByUser')->andReturn($user); + $this->throttleProvider->shouldReceive('isEnabled')->andReturn(true); + + $user->shouldReceive('isActivated')->andReturn(true); + $user->shouldReceive('isEnabled')->andReturn(true); + $user->shouldReceive('isBanned')->andReturn(false); + $user->shouldReceive('isSuspended')->andReturn(false); + $user->shouldReceive('getId')->andReturn('test'); + $user->shouldReceive('getPersistCode')->andReturn('persist_code'); + $user->shouldReceive('recordLogin'); + + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_PERSIST_CODE)->andReturn('foo'); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_USER_ID)->andReturn('bar'); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_MASQUERADE_STACK)->andReturn(null); + $this->sessionHandler->shouldReceive('set') + ->with(Sentry::SESSION_MASQUERADE_STACK, array( + array(Sentry::SESSION_KEY_PERSIST_CODE => 'foo', Sentry::SESSION_KEY_USER_ID => 'bar') + ));; + $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_USER_ID, 'test'); + $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_PERSIST_CODE, 'persist_code'); + + $this->sentry->masquerade($user); + } + + /** + * @expectedException Cartalyst\Sentry\Users\LoginRequiredException + */ + public function testMasqueradeNogLoggedInException() { + $user = m::mock('Cartalyst\Sentry\Users\UserInterface'); + + $this->sessionHandler->shouldReceive('get')->andReturn(null); + + $this->sentry->masquerade($user); + } + + /** + * tests If current masquerades are not lost if you masquerade + */ + public function testMasqueradeStackNotLost() + { + $user = m::mock('Cartalyst\Sentry\Users\UserInterface'); + + $this->userProvider->shouldReceive('findById')->once()->andReturn($userOld = m::mock('Cartalyst\Sentry\Users\UserInterface')); + + + $userOld->shouldReceive('checkPersistCode')->andReturn(true); + $userOld->shouldReceive('isActivated')->andReturn(true); + $userOld->shouldReceive('isEnabled')->andReturn(true); + $userOld->shouldReceive('isBanned')->andReturn(false); + $userOld->shouldReceive('isSuspended')->andReturn(false); + + $this->throttleProvider->shouldReceive('findByUser')->andReturn($user); + $this->throttleProvider->shouldReceive('isEnabled')->andReturn(true); + + $user->shouldReceive('isActivated')->andReturn(true); + $user->shouldReceive('isEnabled')->andReturn(true); + $user->shouldReceive('isBanned')->andReturn(false); + $user->shouldReceive('isSuspended')->andReturn(false); + $user->shouldReceive('getId')->andReturn('test'); + $user->shouldReceive('getPersistCode')->andReturn('persist_code'); + $user->shouldReceive('recordLogin'); + + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_PERSIST_CODE)->andReturn('foo'); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_USER_ID)->andReturn('bar'); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_MASQUERADE_STACK)->andReturn(array( + array(Sentry::SESSION_KEY_PERSIST_CODE => 'foo_old', Sentry::SESSION_KEY_USER_ID => 'bar_old') + )); + $this->sessionHandler->shouldReceive('set') + ->with(Sentry::SESSION_MASQUERADE_STACK, array( + array(Sentry::SESSION_KEY_PERSIST_CODE => 'foo_old', Sentry::SESSION_KEY_USER_ID => 'bar_old'), + array(Sentry::SESSION_KEY_PERSIST_CODE => 'foo', Sentry::SESSION_KEY_USER_ID => 'bar') + ));; + $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_USER_ID, 'test'); + $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_PERSIST_CODE, 'persist_code'); + + $this->sentry->masquerade($user); + } + + /** + * Test if a normal masqueradedLogout works if the person is nog masqueraded + */ + public function testCheckMasqueradedLoggingOut() + { + $this->sentry->setUser(m::mock('Cartalyst\Sentry\Users\UserInterface')); + $this->sessionHandler->shouldReceive('destroy')->once(); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_MASQUERADE_STACK)->once()->andReturn(null); + $this->sentry->masqueradedLogout(); + + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_USER_ID)->once()->andReturn(null); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_KEY_PERSIST_CODE)->once()->andReturn(null); + $this->assertNull($this->sentry->getUser()); + } + + /** + * Test if a masqueraded logout goes back to the last user + */ + public function testMasqueradedLogOutGoBack() + { + $this->sentry->setUser(m::mock('Cartalyst\Sentry\Users\UserInterface')); + $this->sessionHandler->shouldReceive('get')->with(Sentry::SESSION_MASQUERADE_STACK)->once()->andReturn(array( + array(Sentry::SESSION_KEY_PERSIST_CODE => 'foo_old', Sentry::SESSION_KEY_USER_ID => 'bar_old'), + array(Sentry::SESSION_KEY_PERSIST_CODE => 'foo', Sentry::SESSION_KEY_USER_ID => 'bar') + )); + + $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_USER_ID, 'bar')->once(); + $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_PERSIST_CODE, 'foo')->once(); + + $this->userProvider->shouldReceive('findUserById')->with('bar')->andReturn('test'); + $this->sentry->masqueradedLogout(); + $this->assertEquals('test', $this->sentry->getUser()); + } } From e99e057b96f03a2cf75f2edb78ea5c71ca5097a7 Mon Sep 17 00:00:00 2001 From: Stefan Majoor Date: Sat, 16 Aug 2014 17:01:01 +0200 Subject: [PATCH 8/9] Fixed some mistakes --- src/Cartalyst/Sentry/Facades/Native/Sentry.php | 2 +- src/Cartalyst/Sentry/Sentry.php | 3 ++- src/Cartalyst/Sentry/SentryServiceProvider.php | 7 +++++-- .../Sentry/SessionHandlers/NativeSessionHandler.php | 3 +-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Cartalyst/Sentry/Facades/Native/Sentry.php b/src/Cartalyst/Sentry/Facades/Native/Sentry.php index 73a7fa881..2f5e86366 100644 --- a/src/Cartalyst/Sentry/Facades/Native/Sentry.php +++ b/src/Cartalyst/Sentry/Facades/Native/Sentry.php @@ -66,7 +66,7 @@ public static function createSentry( $throttleProvider ?: new ThrottleProvider($userProvider), new NativeSessionHandler( $session ?: new NativeSession, - $cookie ?: new NativeCookie, + $cookie ?: new NativeCookie ), $ipAddress ?: static::guessIpAddress() ); diff --git a/src/Cartalyst/Sentry/Sentry.php b/src/Cartalyst/Sentry/Sentry.php index 3d79a4957..217c04eb1 100644 --- a/src/Cartalyst/Sentry/Sentry.php +++ b/src/Cartalyst/Sentry/Sentry.php @@ -736,7 +736,8 @@ public function masqueradedLogout() { $this->session->set(static::SESSION_KEY_USER_ID, $oldUser[static::SESSION_KEY_USER_ID]); $this->session->set(static::SESSION_KEY_PERSIST_CODE, $oldUser[static::SESSION_KEY_PERSIST_CODE]); - $this->user = $this->userProvider->findUserById($oldUser[static::SESSION_KEY_USER_ID]); + $this->session->set(static::SESSION_MASQUERADE_STACK, $stack); + $this->user = $this->userProvider->findById($oldUser[static::SESSION_KEY_USER_ID]); } /** diff --git a/src/Cartalyst/Sentry/SentryServiceProvider.php b/src/Cartalyst/Sentry/SentryServiceProvider.php index bbf7dc0e8..3c91d291d 100644 --- a/src/Cartalyst/Sentry/SentryServiceProvider.php +++ b/src/Cartalyst/Sentry/SentryServiceProvider.php @@ -25,6 +25,7 @@ use Cartalyst\Sentry\Hashing\Sha256Hasher; use Cartalyst\Sentry\Hashing\WhirlpoolHasher; use Cartalyst\Sentry\Sentry; +use Cartalyst\Sentry\SessionHandlers\NativeSessionHandler; use Cartalyst\Sentry\Sessions\IlluminateSession; use Cartalyst\Sentry\Throttling\Eloquent\Provider as ThrottleProvider; use Cartalyst\Sentry\Users\Eloquent\Provider as UserProvider; @@ -289,8 +290,10 @@ protected function registerSentry() $app['sentry.user'], $app['sentry.group'], $app['sentry.throttle'], - $app['sentry.session'], - $app['sentry.cookie'], + new NativeSessionHandler( + $app['sentry.session'], + $app['sentry.cookie'] + ), $app['request']->getClientIp() ); }); diff --git a/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php index 96bcbe271..f7f0562b4 100644 --- a/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php +++ b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php @@ -66,8 +66,7 @@ public function set($key, $value) public function get($key) { $values = $this->session->get(); - !isset($values[$key]) && $values = $this->cookie->get(); - + !isset($values[$key]) && $values = (array)$this->cookie->get(); return isset($values[$key]) ? $values[$key] : null; } From 5055533750394b23e920903da0fa16fa3748ef8e Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 16 Aug 2014 17:17:27 +0200 Subject: [PATCH 9/9] Fixed unittest. Fixed some documentation --- .../SessionHandlers/NativeSessionHandler.php | 30 ++++++++++++++++++- tests/SentryTest.php | 6 ++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php index f7f0562b4..bf4ecf9bb 100644 --- a/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php +++ b/src/Cartalyst/Sentry/SessionHandlers/NativeSessionHandler.php @@ -55,6 +55,10 @@ public function __construct( /** * Sets a value in the session + * + * @param string $key The key of the value to be set + * @param mixed $value The value to be set + * @return void */ public function set($key, $value) { @@ -63,6 +67,12 @@ public function set($key, $value) $this->session->put($values); } + /** + * Get a value in the session + * + * @param string $key The key of the value to get + * @return void + */ public function get($key) { $values = $this->session->get(); @@ -71,7 +81,9 @@ public function get($key) } /** - * Destroys the session + * Completely destroy the session + * + * @return true; */ public function destroy() { @@ -79,16 +91,32 @@ public function destroy() $this->cookie->forget(); } + /** + * Set the session interface for this handler + * + * @param Cartalyst\Sentry\Sessions\SessionInterface $session The Sessioninterface to set + * @return void + */ public function setSession(SessionInterface $session) { $this->session = $session; } + /** + * Get the sessiondriver + * + * @return Cartalyst\Sentry\Sessions\SessionInterface + */ public function getSession() { return $this->session; } + /** + * Make the session be kept forever + * + * @return void + */ public function forever() { // Make sure that the values that are forever are not lost diff --git a/tests/SentryTest.php b/tests/SentryTest.php index 729b389c5..b064b1114 100644 --- a/tests/SentryTest.php +++ b/tests/SentryTest.php @@ -679,8 +679,10 @@ public function testMasqueradedLogOutGoBack() $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_USER_ID, 'bar')->once(); $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_KEY_PERSIST_CODE, 'foo')->once(); - - $this->userProvider->shouldReceive('findUserById')->with('bar')->andReturn('test'); + $this->sessionHandler->shouldReceive('set')->with(Sentry::SESSION_MASQUERADE_STACK, array( + array(Sentry::SESSION_KEY_PERSIST_CODE => 'foo_old', Sentry::SESSION_KEY_USER_ID => 'bar_old') + ))->once(); + $this->userProvider->shouldReceive('findById')->with('bar')->andReturn('test'); $this->sentry->masqueradedLogout(); $this->assertEquals('test', $this->sentry->getUser()); }