User model, SaltGenerator, UserProvider, UserCreateCommand
parent
a365c070ae
commit
2f7864be0f
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
use Gist\Service\UserProvider;
|
||||
use Silex\Provider\SecurityServiceProvider;
|
||||
use Gist\Service\SaltGenerator;
|
||||
|
||||
$app['salt_generator'] = function ($app) {
|
||||
return new SaltGenerator();
|
||||
};
|
||||
|
||||
$app['user.provider'] = function ($app) {
|
||||
return new UserProvider(
|
||||
$app['security.encoder.digest'],
|
||||
$app['salt_generator']
|
||||
);
|
||||
};
|
||||
|
||||
$app->register(
|
||||
new SecurityServiceProvider(),
|
||||
[
|
||||
'security.firewalls' => [
|
||||
'default' => [
|
||||
'pattern' => '^/user.*$',
|
||||
'anonymous' => false,
|
||||
'form' => [
|
||||
'login_path' => '/login',
|
||||
'check_path' => 'login_check',
|
||||
],
|
||||
'logout' => [
|
||||
'logout_path' => '/logout'
|
||||
],
|
||||
'users' => $app->share(function() use ($app) {
|
||||
return $app['user.provider'];
|
||||
}),
|
||||
],
|
||||
],
|
||||
'security.access_rules' => [
|
||||
['^/user.*$', 'ROLE_USER'],
|
||||
]
|
||||
]
|
||||
);
|
|
@ -4,11 +4,13 @@
|
|||
use Gist\Command\CreateCommand;
|
||||
use Gist\Command\UpdateCommand;
|
||||
use Gist\Command\StatsCommand;
|
||||
use Gist\Command\UserCreateCommand;
|
||||
|
||||
$app = require __DIR__.'/bootstrap.php';
|
||||
|
||||
$app['console']->add(new CreateCommand());
|
||||
$app['console']->add(new UpdateCommand());
|
||||
$app['console']->add(new StatsCommand());
|
||||
$app['console']->add(new UserCreateCommand());
|
||||
|
||||
$app['console']->run();
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
"symfony/security-csrf": "~2.6",
|
||||
"knplabs/console-service-provider": "~1.0",
|
||||
"propel/propel": "~2.0@dev",
|
||||
"guzzlehttp/guzzle": "~6.0"
|
||||
"guzzlehttp/guzzle": "~6.0",
|
||||
"symfony/security": "^2.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace Gist\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Knp\Command\Command;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
|
||||
class UserCreateCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('user:create')
|
||||
->setDescription('Create a user')
|
||||
->setHelp("");
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$helper = $this->getHelper('question');
|
||||
$userProvider = $this->getSilexApplication()['user.provider'];
|
||||
|
||||
$username = '';
|
||||
$password = '';
|
||||
|
||||
while (trim($username) === '') {
|
||||
$question = new Question('Username: ', '');
|
||||
$username = $helper->ask($input, $output, $question);
|
||||
|
||||
if ($userProvider->userExists($username)) {
|
||||
$output->writeln('<error>This username is already used.</error>');
|
||||
$username = '';
|
||||
}
|
||||
}
|
||||
|
||||
while (trim($password) === '') {
|
||||
$question = new Question('Password: ', '');
|
||||
$password = $helper->ask($input, $output, $question);
|
||||
}
|
||||
|
||||
$userProvider->registerUser($username, $password);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Gist\Model;
|
||||
|
||||
use Gist\Model\Base\User as BaseUser;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
class User extends BaseUser implements UserInterface
|
||||
{
|
||||
public function eraseCredentials()
|
||||
{
|
||||
$this->setPassword(null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Gist\Model;
|
||||
|
||||
use Gist\Model\Base\UserQuery as BaseUserQuery;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the 'user' table.
|
||||
*
|
||||
*
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*
|
||||
*/
|
||||
class UserQuery extends BaseUserQuery
|
||||
{
|
||||
|
||||
}
|
|
@ -2,12 +2,26 @@
|
|||
<database defaultIdMethod="native" name="default" namespace="Gist\Model">
|
||||
<table name="gist">
|
||||
<column name="id" type="INTEGER" primaryKey="true" required="true" autoIncrement="true"/>
|
||||
|
||||
<column name="title" type="VARCHAR" size="255" required="false" />
|
||||
<column name="cipher" type="BOOLEAN" required="true" defaultValue="false" />
|
||||
<column name="type" type="VARCHAR" size="30" required="true" />
|
||||
<column name="file" type="VARCHAR" size="30" required="true" />
|
||||
<column name="user_id" type="INTEGER" required="false" />
|
||||
|
||||
<foreign-key foreignTable="user" onDelete="setnull" onUpdate="cascade">
|
||||
<reference local="user_id" foreign="id"/>
|
||||
</foreign-key>
|
||||
|
||||
<behavior name="timestampable"/>
|
||||
</table>
|
||||
|
||||
<table name="user">
|
||||
<column name="id" type="INTEGER" primaryKey="true" required="true" autoIncrement="true"/>
|
||||
<column name="username" type="VARCHAR" size="255" required="true" />
|
||||
<column name="password" type="VARCHAR" size="255" required="true" />
|
||||
<column name="roles" type="VARCHAR" size="255" required="true" />
|
||||
<column name="salt" type="VARCHAR" size="64" required="true" />
|
||||
|
||||
<behavior name="timestampable"/>
|
||||
</table>
|
||||
</database>
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Gist\Service;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class SaltGenerator
|
||||
* @author Simon Vieille <simon@deblan.fr>
|
||||
*/
|
||||
class SaltGenerator
|
||||
{
|
||||
public function generate($length = 64)
|
||||
{
|
||||
if (!is_numeric($length)) {
|
||||
throw new InvalidArgumentException('Paramter length must be a valid integer.');
|
||||
}
|
||||
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
return substr(base64_encode(openssl_random_pseudo_bytes($length)), 0, $length);
|
||||
}
|
||||
|
||||
if (function_exists('mcrypt_create_iv')) {
|
||||
return substr(base64_encode(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)), 0, $length);
|
||||
}
|
||||
|
||||
throw new RuntimeException('You must enable openssl or mcrypt modules.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
namespace Gist\Service;
|
||||
|
||||
use Gist\Model\UserQuery;
|
||||
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
|
||||
use Gist\Model\User;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
use Gist\Service\SaltGenerator;
|
||||
|
||||
/**
|
||||
* Class UserProvider
|
||||
* @author Simon Vieille <simon@deblan.fr>
|
||||
*/
|
||||
class UserProvider implements UserProviderInterface
|
||||
{
|
||||
protected $encoder;
|
||||
|
||||
protected $saltGenerator;
|
||||
|
||||
public function __construct(MessageDigestPasswordEncoder $encoder, SaltGenerator $saltGenerator)
|
||||
{
|
||||
$this->encoder = $encoder;
|
||||
$this->saltGenerator = $saltGenerator;
|
||||
}
|
||||
|
||||
public function setEncoder(MessageDigestPasswordEncoder $encoder)
|
||||
{
|
||||
$this->encoder = $encoder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEncoder()
|
||||
{
|
||||
return $this->encoder;
|
||||
}
|
||||
|
||||
public function setSaltGenerator(SaltGenerator $saltGenerator)
|
||||
{
|
||||
$this->saltGenerator = $saltGenerator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSaltGenerator()
|
||||
{
|
||||
return $this->saltGenerator;
|
||||
}
|
||||
|
||||
public function userExists($username)
|
||||
{
|
||||
return UserQuery::create()
|
||||
->filterByUsername($username)
|
||||
->count() > 0;
|
||||
}
|
||||
|
||||
public function registerUser($username, $password)
|
||||
{
|
||||
$user = new User();
|
||||
|
||||
$salt = $this->saltGenerator->generate(64);
|
||||
|
||||
$user
|
||||
->setUsername($username)
|
||||
->setRoles('ROLE_USER')
|
||||
->setSalt($salt);
|
||||
|
||||
$user
|
||||
->setPassword($this->encoder->encodePassword($user, $password))
|
||||
->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function updateUserPassword(User $user, $password)
|
||||
{
|
||||
$user
|
||||
->setPassword($this->encoder->encodePassword($password))
|
||||
->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function loadUserByUsername($username)
|
||||
{
|
||||
$user = UserQuery::create()->findOneByUsername($username);
|
||||
|
||||
if (null === $user) {
|
||||
throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function refreshUser(UserInterface $user)
|
||||
{
|
||||
if (!$user instanceof User) {
|
||||
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
|
||||
}
|
||||
|
||||
return $this->loadUserByUsername($user->getUsername());
|
||||
}
|
||||
|
||||
public function supportsClass($class)
|
||||
{
|
||||
return $class === 'Gist\\Model\\User';
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue