Skip to content

Commit

Permalink
Abstract provider to load users from the database
Browse files Browse the repository at this point in the history
  • Loading branch information
webinarium committed Apr 16, 2017
1 parent 247c01a commit b42d97d
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 1 deletion.
29 changes: 29 additions & 0 deletions Model/UserRepositoryInterface.php
@@ -0,0 +1,29 @@
<?php

//----------------------------------------------------------------------
//
// Copyright (C) 2017 Artem Rodygin
//
// You should have received a copy of the MIT License along with
// this file. If not, see <http://opensource.org/licenses/MIT>.
//
//----------------------------------------------------------------------

namespace Pignus\Model;

use Doctrine\Common\Persistence\ObjectRepository;

/**
* User repository interface.
*/
interface UserRepositoryInterface extends ObjectRepository
{
/**
* Finds user by username.
*
* @param string $username
*
* @return \Symfony\Component\Security\Core\User\UserInterface|null
*/
public function findOneByUsername(string $username);
}
2 changes: 1 addition & 1 deletion Model/UserTrait.php
Expand Up @@ -16,7 +16,7 @@
/**
* User trait.
*
* @ORM\MappedSuperclass
* @ORM\MappedSuperclass(repositoryClass="Pignus\Model\UserRepositoryInterface")
*/
trait UserTrait
{
Expand Down
68 changes: 68 additions & 0 deletions Provider/AbstractUserProvider.php
@@ -0,0 +1,68 @@
<?php

//----------------------------------------------------------------------
//
// Copyright (C) 2017 Artem Rodygin
//
// You should have received a copy of the MIT License along with
// this file. If not, see <http://opensource.org/licenses/MIT>.
//
//----------------------------------------------------------------------

namespace Pignus\Provider;

use Pignus\Model\UserRepositoryInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

/**
* Abstract provider to load users from the database.
*/
abstract class AbstractUserProvider implements UserProviderInterface
{
protected $repository;

/**
* Dependency Injection constructor.
*
* @param UserRepositoryInterface $repository
*/
public function __construct(UserRepositoryInterface $repository)
{
$this->repository = $repository;
}

/**
* {@inheritdoc}
*/
public function loadUserByUsername($username)
{
$user = $this->repository->findOneByUsername($username);

if ($user === null) {
throw new UsernameNotFoundException();
}

return $user;
}

/**
* {@inheritdoc}
*/
public function refreshUser(UserInterface $user)
{
if (!$this->supportsClass(get_class($user))) {
throw new UnsupportedUserException();
}

$user = $this->repository->findOneByUsername($user->getUsername());

if ($user === null) {
throw new UsernameNotFoundException();
}

return $user;
}
}
92 changes: 92 additions & 0 deletions Tests/Provider/AbstractUserProviderTest.php
@@ -0,0 +1,92 @@
<?php

//----------------------------------------------------------------------
//
// Copyright (C) 2017 Artem Rodygin
//
// You should have received a copy of the MIT License along with
// this file. If not, see <http://opensource.org/licenses/MIT>.
//
//----------------------------------------------------------------------

namespace Pignus\Tests\Provider;

use Pignus\Model\UserRepositoryInterface;
use Pignus\Tests\Model\DummyUser;
use Symfony\Component\Security\Core\User\User;

class AbstractUserProviderTest extends \PHPUnit_Framework_TestCase
{
/** @var DummyUser */
protected $user;

/** @var DummyUserProvider */
protected $provider;

protected function setUp()
{
parent::setUp();

$this->user = new DummyUser();

$reflection = new \ReflectionProperty(DummyUser::class, 'username');
$reflection->setAccessible(true);
$reflection->setValue($this->user, 'admin');

$repository = $this->createMock(UserRepositoryInterface::class);
$repository
->method('findOneByUsername')
->willReturnMap([
['admin', $this->user],
]);

/** @var UserRepositoryInterface $repository */
$this->provider = new DummyUserProvider($repository);
}

public function testLoadUserByUsername()
{
$result = $this->provider->loadUserByUsername('admin');

self::assertInstanceOf(DummyUser::class, $result);
self::assertEquals('admin', $result->getUsername());
}

/**
* @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
*/
public function testLoadUnknownUserByUsername()
{
$this->provider->loadUserByUsername('unknown');
}

public function testRefreshUser()
{
$result = $this->provider->refreshUser($this->user);

self::assertInstanceOf(DummyUser::class, $result);
self::assertEquals('admin', $result->getUsername());
}

/**
* @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
*/
public function testRefreshUnknownUser()
{
$reflection = new \ReflectionProperty(DummyUser::class, 'username');
$reflection->setAccessible(true);
$reflection->setValue($this->user, 'unknown');

$this->provider->refreshUser($this->user);
}

/**
* @expectedException \Symfony\Component\Security\Core\Exception\UnsupportedUserException
*/
public function testUnsupportedUserException()
{
$user = new User('admin', 'secret');

$this->provider->refreshUser($user);
}
}
26 changes: 26 additions & 0 deletions Tests/Provider/DummyUserProvider.php
@@ -0,0 +1,26 @@
<?php

//----------------------------------------------------------------------
//
// Copyright (C) 2017 Artem Rodygin
//
// You should have received a copy of the MIT License along with
// this file. If not, see <http://opensource.org/licenses/MIT>.
//
//----------------------------------------------------------------------

namespace Pignus\Tests\Provider;

use Pignus\Provider\AbstractUserProvider;
use Pignus\Tests\Model\DummyUser;

class DummyUserProvider extends AbstractUserProvider
{
/**
* {@inheritdoc}
*/
public function supportsClass($class)
{
return $class === DummyUser::class;
}
}
1 change: 1 addition & 0 deletions composer.json
Expand Up @@ -9,6 +9,7 @@
"php" : ">=7.0",
"symfony/http-kernel" : "^2.4|^3.0",
"symfony/security-core" : "^2.4|^3.0",
"doctrine/common" : "^2.7",
"doctrine/orm" : "^2.5",
"roave/security-advisories" : "dev-master"
},
Expand Down

0 comments on commit b42d97d

Please sign in to comment.