geforked van deblan/gist
1
0
Vork 0

User model, SaltGenerator, UserProvider, UserCreateCommand

This commit is contained in:
Simon Vieille 2015-11-21 14:27:53 +01:00
bovenliggende a365c070ae
commit 2f7864be0f
9 gewijzigde bestanden met toevoegingen van 280 en 2 verwijderingen

Bestand weergeven

@ -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'],
]
]
);

Bestand weergeven

@ -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();

Bestand weergeven

@ -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": {

Bestand weergeven

@ -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);
}
}

14
src/Gist/Model/User.php Normal file
Bestand weergeven

@ -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);
}
}

Bestand weergeven

@ -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
{
}

Bestand weergeven

@ -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>

Bestand weergeven

@ -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.');
}
}

Bestand weergeven

@ -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';
}
}