event driven authentication adapter

parent e9175d01
......@@ -49,25 +49,25 @@ $container['logger'] = function ($c) {
$container['events'] = function ($c) {
return new \Zend\EventManager\EventManager(
new \Zend\EventManager\SharedEventManager()
new \Zend\EventManager\SharedEventManager(),
['events']
);
};
$container['Service\\Authentication\\Adapter'] = function ($c) use ($app) {
return new \Zend\Authentication\Adapter\Callback(function () use ($c) {
return $c->events->triggerUntil(
function (\Zend\Authentication\Result $result) {
return $result->isValid();
},
'authenticate', $app, func_get_args()
)->last();
});
// Authentication service
$container['Service\\Authentication\\Adapter'] = function ($c) {
return new \GrEduLabs\Authentication\Adapter\Events($c->get('events'));
};
$container['Service\\Authentication\\Storage'] = function ($c) {
return new \GrEduLabs\Authentication\Storage\PhpSession($_SESSION);
};
$container['Service\\Authentication'] = function ($c) {
$service = new \Zend\Authentication\AuthenticationService(
new \GrEduLabs\Authentication\Storage\PhpSession($_SESSION),
$c->get('Service\\Authentication\\Storage'),
$c->get('Service\\Authentication\\Adapter')
);
......
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\Authentication\Adapter;
use Exception;
use Zend\Authentication\Adapter\AbstractAdapter;
use Zend\Authentication\Result;
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\EventsCapableInterface;
class Events extends AbstractAdapter implements EventsCapableInterface
{
const EVENT_AUTH = 'authenticate';
/**
* @var EventManagerInterface
*/
protected $events;
/**
* Construct adapter
*
* @param EventManagerInterface $events
*/
public function __construct(EventManagerInterface $events = null)
{
if (null !== $events) {
$this->setEventManager($events);
}
}
/**
* Retrieve the event manager
*
* Lazy-loads an EventManager instance if none registered.
*
* @return EventManagerInterface
*/
public function getEventManager()
{
if (null === $this->events) {
$this->setEventManager(new EventManager());
}
return $this->events;
}
protected function setEventManager(EventManagerInterface $events)
{
$events->setIdentifiers([__CLASS__, get_class($this)]);
$this->events = $events;
}
public function authenticate()
{
try {
$identity = $this->getEventManager()->triggerUntil(function ($identity) {
return !!$identity;
}, self::EVENT_AUTH, $this, [
'identity' => $this->getIdentity(),
'credential' => $this->getCredential(),
])->last();
} catch (Exception $e) {
return new Result(Result::FAILURE_UNCATEGORIZED, null, [$e->getMessage()]);
}
if (!$identity) {
return new Result(Result::FAILURE, null, ['Authentication failure']);
}
return new Result(Result::SUCCESS, $identity, ['Authentication success']);
}
}
......@@ -36,27 +36,45 @@ class DependenciesTest extends \PHPUnit_Framework_TestCase
@session_destroy();
}
public function testViewInContainer()
public function testView()
{
$view = self::$container->get('view');
$this->assertInstanceOf('\Slim\Views\Twig', $view);
}
public function testFlashInContainer()
public function testFlash()
{
$flash = self::$container->get('flash');
$this->assertInstanceOf('\Slim\Flash\Messages', $flash);
}
public function testLoggerInContainer()
public function testLogger()
{
$logger = self::$container->get('logger');
$this->assertInstanceOf('\Monolog\Logger', $logger);
}
public function testEventsInContainer()
public function testEvents()
{
$events = self::$container->get('events');
$this->assertInstanceOf('\Zend\EventManager\EventManagerInterface', $events);
}
public function testAuthAdapter()
{
$adapter = self::$container->get('Service\\Authentication\\Adapter');
$this->assertInstanceOf('\Zend\Authentication\Adapter\AdapterInterface', $adapter);
}
public function testAuthStorage()
{
$storage = self::$container->get('Service\\Authentication\\Storage');
$this->assertInstanceOf('\Zend\Authentication\Storage\StorageInterface', $storage);
}
public function testAuthService()
{
$service = self::$container->get('Service\\Authentication');
$this->assertInstanceOf('\Zend\Authentication\AuthenticationServiceInterface', $service);
}
}
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabsTest\Authentication\Adapter;
use GrEduLabs\Authentication\Adapter\Events;
use Zend\Authentication\Result;
use Zend\EventManager\EventManager;
class EventsTest extends \PHPUnit_Framework_TestCase
{
private $adapter;
protected function setUp()
{
$this->adapter = new Events();
}
public function testConstructorSetsEventManager()
{
$events = new EventManager();
$adapter = new Events($events);
$this->assertAttributeSame($events, 'events', $adapter);
}
public function testGetEventManagerReturnsDefaultEventManager()
{
$adapter = new Events();
$events = $adapter->getEventManager();
$this->assertInstanceOf('\Zend\EventManager\EventManagerInterface', $events);
}
public function testIdentifiersSet()
{
$events = new EventManager();
$this->assertEmpty($events->getIdentifiers());
$adapter = new Events($events);
$this->assertNotEmpty($events->getIdentifiers());
}
public function testAuthenticateTriggerEvent()
{
$triggered = false;
$events = $this->adapter->getEventManager();
$events->attach(Events::EVENT_AUTH, function ($event) use (&$triggered) {
$triggered = true;
});
$result = $this->adapter->authenticate();
$this->assertTrue($triggered);
$this->assertInstanceOf('Zend\Authentication\Result', $result);
}
public function testAuthenticateReturnsFirstTruthyListener()
{
$events = $this->adapter->getEventManager();
$events->attach(Events::EVENT_AUTH, function ($event) {
return 'test';
}, 10);
$events->attach(Events::EVENT_AUTH, function ($event) {
return 'ok';
}, 15);
$events->attach(Events::EVENT_AUTH, function ($event) {
return false;
}, 20);
$events->attach(Events::EVENT_AUTH, function ($event) {
return;
}, 5);
$result = $this->adapter->authenticate();
$this->assertTrue($result->isValid());
$this->assertSame('ok', $result->getIdentity());
}
public function authenticateResults()
{
return [
[false, [false, null, Result::FAILURE]],
['identity', [true, 'identity', Result::SUCCESS]],
];
}
/**
* @dataProvider authenticateResults
*/
public function testAuthenticateFailedResult($listenerReturn, $expectedResult)
{
$events = $this->adapter->getEventManager();
$events->attach(Events::EVENT_AUTH, function () use ($listenerReturn) {
return $listenerReturn;
});
$result = $this->adapter->authenticate();
$this->assertSame($expectedResult[0], $result->isValid());
$this->assertSame($expectedResult[1], $result->getIdentity());
$this->assertSame($expectedResult[2], $result->getCode());
}
public function testAuthenticatePassIdentityAndCrendentialToListener()
{
$identity = null;
$credential = null;
$events = $this->adapter->getEventManager();
$events->attach(Events::EVENT_AUTH, function ($event) use (&$identity, &$credential) {
$identity = $event->getParam('identity');
$credential = $event->getParam('credential');
});
$this->adapter->setIdentity('username');
$this->adapter->setCredential('password');
$this->adapter->authenticate();
$this->assertSame('username', $identity);
$this->assertSame('password', $credential);
}
public function testAuthenticateIfListenerThrowsException()
{
$events = $this->adapter->getEventManager();
$events->attach(Events::EVENT_AUTH, function () {
throw new \Exception('test');
});
$result = $this->adapter->authenticate();
$this->assertFalse($result->isValid());
$this->assertSame(Result::FAILURE_UNCATEGORIZED, $result->getCode());
$this->assertSame(['test'], $result->getMessages());
$this->assertNull($result->getIdentity());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment