Browse Source

Added triggering of Auth.afterIdentify and Auth.logout events.

Auth.afterIdentify is triggered after a user has been identified.
BaseAuthenticate::logout() has been removed, instead authenticate classes should
add listener for Auth.logout event if needed.
ADmad 11 years ago
parent
commit
601cdcc14c

+ 22 - 14
src/Auth/BaseAuthenticate.php

@@ -16,6 +16,7 @@ namespace Cake\Auth;
 use Cake\Auth\PasswordHasherFactory;
 use Cake\Controller\ComponentRegistry;
 use Cake\Core\InstanceConfigTrait;
+use Cake\Event\EventListenerInterface;
 use Cake\Network\Request;
 use Cake\Network\Response;
 use Cake\ORM\TableRegistry;
@@ -24,7 +25,7 @@ use Cake\ORM\TableRegistry;
  * Base Authentication class with common methods and properties.
  *
  */
-abstract class BaseAuthenticate {
+abstract class BaseAuthenticate implements EventListenerInterface {
 
 	use InstanceConfigTrait;
 
@@ -175,19 +176,6 @@ abstract class BaseAuthenticate {
 	abstract public function authenticate(Request $request, Response $response);
 
 /**
- * Allows you to hook into AuthComponent::logout(),
- * and implement specialized logout behavior.
- *
- * All attached authentication objects will have this method
- * called when a user logs out.
- *
- * @param array $user The user about to be logged out.
- * @return void
- */
-	public function logout(array $user) {
-	}
-
-/**
  * Get a user based on information in the request. Primarily used by stateless authentication
  * systems like basic and digest auth.
  *
@@ -213,4 +201,24 @@ abstract class BaseAuthenticate {
 	public function unauthenticated(Request $request, Response $response) {
 	}
 
+/**
+ * Returns a list of all events that this authenticate class will listen to.
+ *
+ * An autheticate class can listen to following events fired by AuthComponent:
+ *
+ * - `Auth.afterIdentify` - Fired after a user has been identified using one of
+ *   configured authenticate class. The callback function should have signature
+ *   like `afteIndentify(Event $event, array $user)` when `$user` is the
+ *   identified user record.
+ *
+ * - `Auth.logout` - Fired when AuthComponent::logout() is called. The callback
+ *   function should have signature like `logout(Event $event, array $user)`
+ *   where `$user` is the user about to be logged out.
+ *
+ * @return array List of events this class listens to. Defaults to `[]`.
+ */
+	public function implementedEvents() {
+		return [];
+	}
+
 }

+ 7 - 3
src/Controller/Component/AuthComponent.php

@@ -19,6 +19,7 @@ use Cake\Controller\Controller;
 use Cake\Core\App;
 use Cake\Core\Exception\Exception;
 use Cake\Event\Event;
+use Cake\Event\EventManagerTrait;
 use Cake\Network\Exception\ForbiddenException;
 use Cake\Network\Request;
 use Cake\Network\Response;
@@ -34,6 +35,8 @@ use Cake\Utility\Hash;
  */
 class AuthComponent extends Component {
 
+	use EventManagerTrait;
+
 /**
  * Constant for 'all'
  *
@@ -236,6 +239,7 @@ class AuthComponent extends Component {
  */
 	public function initialize(array $config) {
 		$controller = $this->_registry->getController();
+		$this->eventManager($controller->eventManager());
 		$this->request = $controller->request;
 		$this->response = $controller->response;
 		$this->session = $controller->request->session();
@@ -599,9 +603,7 @@ class AuthComponent extends Component {
 			$this->constructAuthenticate();
 		}
 		$user = (array)$this->user();
-		foreach ($this->_authenticateObjects as $auth) {
-			$auth->logout($user);
-		}
+		$this->dispatchEvent('Auth.logout', [$user]);
 		$this->session->delete($this->sessionKey);
 		$this->session->delete('Auth.redirect');
 		$this->session->renew();
@@ -716,6 +718,7 @@ class AuthComponent extends Component {
 			$result = $auth->authenticate($this->request, $this->response);
 			if (!empty($result) && is_array($result)) {
 				$this->_authenticationProvider = $auth;
+				$event = $this->dispatchEvent('Auth.afterIdentify', [$result]);
 				return $result;
 			}
 		}
@@ -755,6 +758,7 @@ class AuthComponent extends Component {
 			}
 			$config = array_merge($global, (array)$config);
 			$this->_authenticateObjects[$alias] = new $className($this->_registry, $config);
+			$this->eventManager()->attach($this->_authenticateObjects[$alias]);
 		}
 		return $this->_authenticateObjects;
 	}

+ 10 - 11
tests/TestCase/Controller/Component/AuthComponentTest.php

@@ -1014,22 +1014,21 @@ class AuthComponentTest extends TestCase {
 	}
 
 /**
- * Logout should trigger a logout method on authentication objects.
+ * Test that Auth.afterIdentify and Auth.logout events are triggered
  *
  * @return void
  */
-	public function testLogoutTrigger() {
-		$LogoutTriggerMockAuthenticate = $this->getMock(
-			'Cake\Controller\Component\Auth\BaseAuthenticate',
-			array('authenticate', 'logout'), array(), '', false
-		);
-
-		$this->Auth->config('authenticate', ['LogoutTriggerMock']);
-		$this->Auth->setAuthenticateObject(0, $LogoutTriggerMockAuthenticate);
-		$LogoutTriggerMockAuthenticate->expects($this->once())
-			->method('logout');
+	public function testEventTriggering() {
+		$this->Auth->config('authenticate', [
+			'Test' => ['className' => 'TestApp\Auth\TestAuthenticate']
+		]);
 
+		$this->Auth->identify();
 		$this->Auth->logout();
+		$authObject = $this->Auth->authenticationProvider();
+
+		$expected = ['afterIdentify', 'logout'];
+		$this->assertEquals($expected, $authObject->callStack);
 	}
 
 /**

+ 48 - 0
tests/test_app/TestApp/Auth/TestAuthenticate.php

@@ -0,0 +1,48 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.0.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace TestApp\Auth;
+
+use Cake\Auth\BaseAuthenticate;
+use Cake\Event\Event;
+use Cake\Network\Request;
+use Cake\Network\Response;
+
+/**
+ * TestAuthenticate class
+ *
+ */
+class TestAuthenticate extends BaseAuthenticate {
+
+	public $callStack = [];
+
+	public function implementedEvents() {
+		return [
+			'Auth.afterIdentify' => 'afterIdentify',
+			'Auth.logout' => 'logout'
+		];
+	}
+
+	public function authenticate(Request $request, Response $response) {
+		return ['id' => 1, 'username' => 'admad'];
+	}
+
+	public function afterIdentify(Event $event, array $user) {
+		$this->callStack[] = __FUNCTION__;
+	}
+
+	public function logout(Event $event, array $user) {
+		$this->callStack[] = __FUNCTION__;
+	}
+
+}