Initial FOSUserBundle integration

This commit is contained in:
umpirsky 2013-01-31 17:22:31 +01:00
parent c263c0d08b
commit 29bc208137
15 changed files with 740 additions and 284 deletions

View file

@ -18,15 +18,15 @@
],
"require": {
"php": ">=5.3.3",
"symfony/symfony": "2.1.*",
"symfony/symfony": ">=2.2,<2.3-dev",
"doctrine/orm": ">=2.2.3,<2.4-dev",
"doctrine/doctrine-bundle": "1.1.*",
"doctrine/doctrine-bundle": "1.2.*",
"doctrine/doctrine-fixtures-bundle": "*",
"twig/extensions": "1.0.*",
"symfony/assetic-bundle": "2.1.*",
"symfony/swiftmailer-bundle": "2.1.*",
"symfony/monolog-bundle": "2.1.*",
"sensio/distribution-bundle": "2.1.*",
"symfony/swiftmailer-bundle": "2.2.*",
"symfony/monolog-bundle": "2.2.*",
"sensio/distribution-bundle": "2.2.*",
"sylius/core-bundle": "0.1.*",
"sylius/web-bundle": "0.1.*"

613
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -16,9 +16,11 @@ use Behat\Gherkin\Node\TableNode;
use Behat\Symfony2Extension\Context\KernelAwareInterface;
use Sylius\Bundle\AddressingBundle\Model\ZoneInterface;
use Sylius\Bundle\ShippingBundle\Calculator\DefaultCalculators;
use Sylius\Bundle\CoreBundle\Entity\User;
use Symfony\Component\Form\Util\FormUtil;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Locale\Locale;
use Faker\Factory as FakerFactory;
/**
* Data writing and reading context.
@ -27,6 +29,18 @@ use Symfony\Component\Locale\Locale;
*/
class DataContext extends BehatContext implements KernelAwareInterface
{
/**
* Faker.
*
* @var Generator
*/
protected $faker;
public function __construct()
{
$this->faker = FakerFactory::create();
}
/**
* {@inheritdoc}
*/
@ -35,6 +49,36 @@ class DataContext extends BehatContext implements KernelAwareInterface
$this->kernel = $kernel;
}
/**
* @Given /^there are following users:$/
*/
public function thereAreFollowingUsers(TableNode $table)
{
$manager = $this->getEntityManager();
foreach ($table->getHash() as $data) {
$this->thereIsUser(
$data['username'],
isset($data['password']) ? $data['password'] : $this->faker->word(),
'ROLE_USER',
isset($data['enabled']) ? $data['enabled'] : true
);
}
}
public function thereIsUser($username, $password, $role, $enabled = true)
{
$user = new User();
$user->setUsername($username);
$user->setEmail($this->faker->email());
$user->addRole($role);
$user->setEnabled($enabled);
$user->setPlainPassword($password);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
}
/**
* @Given /^there are following products:$/
* @Given /^the following products exist:$/

View file

@ -11,6 +11,7 @@
namespace Context;
use Behat\Behat\Context\Step;
use Behat\Gherkin\Node\TableNode;
use Behat\MinkExtension\Context\RawMinkContext;
use Behat\Mink\Driver\Selenium2Driver;
@ -125,6 +126,24 @@ class WebUser extends RawMinkContext implements KernelAwareInterface
$this->assertStatusCodeEquals(200);
}
/**
* @Then /^I should be on login page$/
*/
public function iShouldBeOnLoginPage()
{
$this->assertSession()->addressEquals($this->generatePageUrl('fos_user_security_login'));
$this->assertStatusCodeEquals(200);
}
/**
* @Then /^I should be on registration page$/
*/
public function iShouldBeOnRegistrationPage()
{
$this->assertSession()->addressEquals($this->generatePageUrl('fos_user_registration_register'));
$this->assertStatusCodeEquals(200);
}
/**
* @Given /^I am on the page of ([^""]*) "([^""]*)"$/
* @Given /^I go to the page of ([^""]*) "([^""]*)"$/
@ -365,7 +384,7 @@ class WebUser extends RawMinkContext implements KernelAwareInterface
*/
public function iAmLoggedInAsAdministrator()
{
// No security for now.
$this->iAmLoggedInAsRole('ROLE_SYLIUS_ADMIN');
}
/**
@ -447,6 +466,17 @@ class WebUser extends RawMinkContext implements KernelAwareInterface
return $this->getContainer()->get('security.context');
}
private function iAmLoggedInAsRole($role)
{
$this->getSubcontext('data')->thereIsUser('username', 'password', $role);
$this->getSession()->visit($this->generatePageUrl('fos_user_security_login'));
$this->iClick('Login');
$this->iFillInFieldWith('Login', 'username');
$this->iFillInFieldWith('Password', 'password');
$this->iPress('login');
}
/**
* Generate page url.
* This method uses simple convention where page argument is prefixed

29
features/login.feature Normal file
View file

@ -0,0 +1,29 @@
Feature: Log in to store
In order to view my orders list
As a visitor
I need to be able to log in to the store
Background:
Given there are following users:
| username | password |
| bar | foo |
Scenario: Log in with username and password
Given I am on the homepage
And I follow "Login"
When I fill in the following:
| Login | bar |
| Password | foo |
And I press "login"
Then I should be on the homepage
And I should see "Logout"
Scenario: Log in with bad credentials
Given I am on the homepage
And I follow "Login"
When I fill in the following:
| Login | bar |
| Password | bar |
And I press "login"
Then I should be on login page
And I should see "Bad credentials"

View file

@ -0,0 +1,28 @@
Feature: User registration
In order to track my buyings
As a visitor
I need to be able to create an account in store
Scenario: Successfully creating account in store
Given I am on the homepage
When I follow "Register"
When I fill in the following:
| Email | foo@bar.com |
| Username | foo |
| Password | bar |
| Verification | bar |
And I press "register"
Then I should see "Welcome"
And I should see "Logout"
Scenario: Trying to register with non verified password
Given I am on the homepage
When I follow "Register"
When I fill in the following:
| Email | foo@bar.com |
| Username | foo |
| Password | bar |
| Verification | foo |
And I press "register"
Then I should be on registration page
And I should see "The entered passwords don't match"

31
features/users.feature Normal file
View file

@ -0,0 +1,31 @@
Feature: Users management
As a store owner
I want to be able to list registered users
In order to see user details
Background:
Given I am logged in as administrator
And there are following users:
| username | enabled |
| foo | 1 |
| bar | 0 |
| baz | 1 |
Scenario: Seeing index of all users
Given I am on the dashboard page
When I follow "Users"
Then I should be on the user index page
And I should see 4 users in the list
Scenario: Seeing index of unconfirmed users
Given I am on the dashboard page
When I follow "Users"
And I follow "unconfirmed users"
Then I should be on the user index page
And I should see 1 users in the list
Scenario: Seeing user details
Given I am on the dashboard page
When I follow "Users"
And I follow "details"
And I should see "User details"

View file

@ -0,0 +1,12 @@
{% extends 'SyliusWebBundle:Frontend:layout.html.twig' %}
{% block content %}
<div class="page-header">
<h1>Welcome <small>Your registration was successful</small></h1>
</div>
<hr />
<div class="alert alert-success">
Thank you for sign up! You are now logged in the store
</div>
{% endblock %}

View file

@ -0,0 +1,16 @@
{% extends 'SyliusWebBundle:Frontend:layout.html.twig' %}
{% block content %}
<div class="page-header">
<h1>Registration <small>Create an account in store</small></h1>
</div>
<form action="{{ path('fos_user_registration_register') }}" method="post" novalidate>
<fieldset class="well">
{{ form_widget(form) }}
</fieldset>
<div class="form-actions">
<input type="submit" class="btn btn-success btn-large span3" value="register" />
</div>
</form>
{% endblock %}

View file

@ -0,0 +1,44 @@
{% extends 'SyliusWebBundle:Frontend:layout.html.twig' %}
{% block content %}
<div class="page-header">
<h1>Login <small>Sylius sandbox administration</small></h1>
</div>
<blockquote>
<p>His name is <strong>administrator</strong> and the magic word... <strong>abrakadabra</strong>.</p>
<small>Mr. Mysterious</small>
</blockquote>
{% if error %}
<div class="alert alert-error">
{{ error }}
</div>
{% endif %}
<form action="{{ path('fos_user_security_login') }}" method="post" class="well">
<fieldset>
<div class="control-group">
<label for="username" class="control-label">Login</label>
<div class="controls">
<input type="text" id="username" name="_username" value="{{ last_username }}" />
</div>
</div>
<div class="control-group">
<label for="password" class="control-label">Password</label>
<div class="controls">
<input type="password" id="password" name="_password" />
</div>
</div>
<div class="control-group">
<div class="controls">
Remember me? <input type="checkbox" id="remember_me" name="_remember_me" value="on" />
</div>
</div>
</fieldset>
<div class="form-actions">
<input type="submit" class="btn btn-primary btn-large" name="login" value="login" />
</div>
</form>
{% endblock %}

View file

@ -49,6 +49,7 @@ class SyliusKernel extends Kernel
new Knp\Bundle\MenuBundle\KnpMenuBundle(),
new JMS\SerializerBundle\JMSSerializerBundle($this),
new FOS\RestBundle\FOSRestBundle(),
new FOS\UserBundle\FOSUserBundle(),
new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
);

View file

@ -41,11 +41,11 @@ class Requirement
/**
* Constructor that initializes the requirement.
*
* @param Boolean $fulfilled Whether the requirement is fulfilled
* @param string $testMessage The message for testing the requirement
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement
* @param Boolean $fulfilled Whether the requirement is fulfilled
* @param string $testMessage The message for testing the requirement
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement
*/
public function __construct($fulfilled, $testMessage, $helpHtml, $helpText = null, $optional = false)
{
@ -117,16 +117,16 @@ class PhpIniRequirement extends Requirement
/**
* Constructor that initializes the requirement.
*
* @param string $cfgName The configuration name used for ini_get()
* @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
* @param string $cfgName The configuration name used for ini_get()
* @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
* @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
* @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
* @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
* @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement
* @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
* @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement
*/
public function __construct($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null, $optional = false)
{
@ -193,10 +193,10 @@ class RequirementCollection implements IteratorAggregate
/**
* Adds a mandatory requirement.
*
* @param Boolean $fulfilled Whether the requirement is fulfilled
* @param string $testMessage The message for testing the requirement
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param Boolean $fulfilled Whether the requirement is fulfilled
* @param string $testMessage The message for testing the requirement
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
*/
public function addRequirement($fulfilled, $testMessage, $helpHtml, $helpText = null)
{
@ -206,10 +206,10 @@ class RequirementCollection implements IteratorAggregate
/**
* Adds an optional recommendation.
*
* @param Boolean $fulfilled Whether the recommendation is fulfilled
* @param string $testMessage The message for testing the recommendation
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param Boolean $fulfilled Whether the recommendation is fulfilled
* @param string $testMessage The message for testing the recommendation
* @param string $helpHtml The help text formatted in HTML for resolving the problem
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
*/
public function addRecommendation($fulfilled, $testMessage, $helpHtml, $helpText = null)
{
@ -219,15 +219,15 @@ class RequirementCollection implements IteratorAggregate
/**
* Adds a mandatory requirement in form of a php.ini configuration.
*
* @param string $cfgName The configuration name used for ini_get()
* @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
* @param string $cfgName The configuration name used for ini_get()
* @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
* @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
* @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
*/
public function addPhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null)
{
@ -237,15 +237,15 @@ class RequirementCollection implements IteratorAggregate
/**
* Adds an optional recommendation in form of a php.ini configuration.
*
* @param string $cfgName The configuration name used for ini_get()
* @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
* @param string $cfgName The configuration name used for ini_get()
* @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
* @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
* @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
*/
public function addPhpIniRecommendation($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null)
{
@ -430,8 +430,15 @@ class SymfonyRequirements extends RequirementCollection
);
if (version_compare($installedPhpVersion, self::REQUIRED_PHP_VERSION, '>=')) {
$timezones = array();
foreach (DateTimeZone::listAbbreviations() as $abbreviations) {
foreach ($abbreviations as $abbreviation) {
$timezones[$abbreviation['timezone_id']] = true;
}
}
$this->addRequirement(
(in_array(date_default_timezone_get(), DateTimeZone::listIdentifiers())),
isset($timezones[date_default_timezone_get()]),
sprintf('Configured default timezone "%s" must be supported by your installation of PHP', date_default_timezone_get()),
'Your default timezone is not supported by PHP. Check for typos in your <strong>php.ini</strong> file and have a look at the list of deprecated timezones at <a href="http://php.net/manual/en/timezones.others.php">http://php.net/manual/en/timezones.others.php</a>.'
);
@ -468,11 +475,19 @@ class SymfonyRequirements extends RequirementCollection
);
if (function_exists('apc_store') && ini_get('apc.enabled')) {
$this->addRequirement(
version_compare(phpversion('apc'), '3.0.17', '>='),
'APC version must be at least 3.0.17',
'Upgrade your <strong>APC</strong> extension (3.0.17+).'
);
if (version_compare($installedPhpVersion, '5.4.0', '>=')) {
$this->addRequirement(
version_compare(phpversion('apc'), '3.1.13', '>='),
'APC version must be at least 3.1.13 when using PHP 5.4',
'Upgrade your <strong>APC</strong> extension (3.1.13+).'
);
} else {
$this->addRequirement(
version_compare(phpversion('apc'), '3.0.17', '>='),
'APC version must be at least 3.0.17',
'Upgrade your <strong>APC</strong> extension (3.0.17+).'
);
}
}
$this->addPhpIniRequirement('detect_unicode', false);
@ -495,6 +510,14 @@ class SymfonyRequirements extends RequirementCollection
$this->addPhpIniRequirement(
'xdebug.scream', false, true
);
$this->addPhpIniRecommendation(
'xdebug.max_nesting_level',
create_function('$cfgValue', 'return $cfgValue > 100;'),
true,
'xdebug.max_nesting_level should be above 100 in php.ini',
'Set "<strong>xdebug.max_nesting_level</strong>" to e.g. "<strong>250</strong>" in php.ini<a href="#phpini">*</a> to stop Xdebug\'s infinite recursion protection erroneously throwing a fatal error in your project.'
);
}
$pcreVersion = defined('PCRE_VERSION') ? (float) PCRE_VERSION : null;
@ -518,7 +541,7 @@ class SymfonyRequirements extends RequirementCollection
'You should use at least PHP 5.3.4 due to PHP bug #52083 in earlier versions',
'Your project might malfunction randomly due to PHP bug #52083 ("Notice: Trying to get property of non-object"). Install PHP 5.3.4 or newer.'
);
$this->addRecommendation(
version_compare($installedPhpVersion, '5.3.8', '>='),
'When using annotations you should have at least PHP 5.3.8 due to PHP bug #55156',

View file

@ -1,6 +1,6 @@
imports:
- { resource: parameters.yml }
# - { resource: security.yml }
- { resource: security.yml }
framework:
translator: { fallback: %sylius.locale% }
@ -51,6 +51,11 @@ stof_doctrine_extensions:
sluggable: true
timestampable: true
fos_user:
db_driver: orm
firewall_name: main
user_class: Sylius\Bundle\CoreBundle\Entity\User
swiftmailer:
transport: %sylius.mailer.transport%
host: %sylius.mailer.host%
@ -88,3 +93,10 @@ sylius_shipping:
sylius_addressing:
driver: doctrine/orm
sylius_resource:
resources:
sylius_user.user:
driver: doctrine/orm
classes:
model: Sylius\Bundle\CoreBundle\Entity\User

View file

@ -1 +1,29 @@
security: ~
# This file is part of the Sylius package.
# (c) Paweł Jędrzejewski
security:
providers:
fos_userbundle:
id: fos_user.user_manager
encoders:
FOS\UserBundle\Model\UserInterface: sha512
firewalls:
main:
form_login:
provider: fos_userbundle
login_path: /login
check_path: /login
use_referer: true
remember_me:
key: eUodAjYEzDza72
name: APP_REMEMBER_ME
lifetime: 31536000
always_remember_me: true
remember_me_parameter: _remember_me
logout: true
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: "/administration.*", role: ROLE_SYLIUS_ADMIN }

View file

@ -1,2 +1,21 @@
sylius_web:
resource: @SyliusWebBundle/Resources/config/routing/main.yml
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
fos_user_profile:
resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
prefix: /profile
fos_user_register:
resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
prefix: /register
fos_user_resetting:
resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
prefix: /resetting
fos_user_change_password:
resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
prefix: /profile