Symfony/BDD example 04: login/logout

1 January 2015

This is the fourth example in Symfony/BDD series. It demonstrates how to use FOSUserBundle.

1. Background

I assume that you have already read:

In this example I want to restrict access to the application.

The access is to be granted only to one user:

username:  admin
password:  loremipsum

2. Introductory step

2.1. Start the project

Create a new directory and clone my Symfony Standard repository:

# Host OS
$ mkdir symfony-bdd-example-04-login-logout
$ cd symfony-bdd-example-04-login-logout
$ git clone git@github.com:by-examples/symfony-standard.git .

2.2. Create a starting point for the project

Create a new orphan branch that starts at the tag Symfony Standard v2.6.1:

# Host OS
$ git checkout --orphan 2.6.1/symfony-bdd-example-04-login-logout v2.6.1

Commit your change:

# Host OS
$ git add -A
$ git commit -m "Symfony Standard 2.6.1"

2.3. Customize the project

Introduce the following changes in your project:

# Host OS
$ git cherry-pick origin/2.6.1/Gitignore
$ git cherry-pick origin/2.6.1/Cleanup
$ git cherry-pick origin/2.6.1/Vagrant
$ git cherry-pick origin/2.6.1/Speedup
$ git cherry-pick origin/2.6.1/Behat
$ git cherry-pick origin/2.6.1/BehatInitialization
$ git cherry-pick origin/2.6.1/Db
$ git cherry-pick origin/2.6.1/FOSUserBundle

2.4. Install the dependencies

Boot the VM with:

# Host OS
$ vagrant up
$ vagrant ssh

and run:

# Guest OS
$ composer install -o

When this is done, commit you changes with:

# Host OS
$ git add -A
$ git commit -m "Updated dependencies"

3. Run Behat - project is GREEN

Now, try to run:

# Guest OS
$ bin/behat

You will get the output similar to:

No scenarios
No steps
0m0.03s (9.00Mb)

The project is GREEN.

GREEN

5. Tests - the project is RED

Create the file features/login.feature with the following contents:

Feature: I would like to log in to the system

  Scenario: Log in as admin
    Given I am on homepage
     Then I should not see "Logged in as admin"
     When I follow "Login"
      And I fill in "username" with "admin"
      And I fill in "password" with "loremipsum"
      And I press "Login"
     Then I should see "Logged in as admin"
     Then I should not see "Login"
     When I follow "Logout"
     Then I should not see "Logged in as admin"
     Then I should see "Login"

  Scenario: Unsuccessful login
    Given I am on homepage
     When I follow "Login"
     When I fill in "username" with "wrong username"
      And I fill in "password" with "wrong password"
      And I press "Login"
     Then I should see "Bad credentials"

  Scenario: Profile unavailable
    Given I go to "/profile"
     Then the response status code should be 404

  Scenario: Resetting unavailable
    Given I go to "/resetting"
     Then the response status code should be 404

Run Behat:

# Guest OS
$ bin/behat

The project is RED.

RED

Commit the test:

# Host OS
$ git add -A
$ git commit -m "[BDD:RED] tests for login/logout"

6. Restrict access to the application

Restrict access to the whole application in app/config/security.yml file:

...

access_control:
    - { path: ^/_wdt, roles: 'IS_AUTHENTICATED_ANONYMOUSLY' }
    #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    #- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
    #- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
    #- { path: ^/admin/, role: ROLE_ADMIN }
    - { path: ^/, role: ROLE_SUPER_ADMIN }

...

Commit your changes with:

# Host OS
$ git add -A
$ git commit -m "[SECURITY] restricted access to /"

7. The Database

Create the database:

# Guest OS
$ php app/console doctrine:schema:update --force

8. The admin’s account

Crete the admin account:

# Guest OS
$ php app/console fos:user:create admin admin@example.net loremipsum --super-admin

or:

# Guest OS
$ php app/console fos:user:create
$ php app/console fos:user:promote --super admin

Now you can visit your website:

http://127.0.0.1:8880/app_dev.php/

and log in as:

user:     admin
password: loremipsum

9. The main template

Add the following content to your app/Resources/views/base.html.twig view:

...
<body>
    <ul>
        {% if is_granted('ROLE_USER') %}
            <li>Logged in as {{ app.user.username }}</li>
            <li>
                <a href="{{ path('fos_user_security_logout') }}">
                    {{ 'layout.logout'|trans({}, 'FOSUserBundle') }}
                </a>
            </li>
        {% else %}
            <li>
                <a href="{{ path('fos_user_security_login') }}">
                    {{ 'layout.login'|trans({}, 'FOSUserBundle') }}
                </a>
            </li>
        {% endif %}
    </ul>

    {% block body %}{% endblock %}
    ...

10. Run the tests

Clear the cache:

# Guest OS
$ php app/console cache:clear --env=prod

and run the tests:

# Guest OS
$ bin/behat

The project is GREEN.

GREEN

Commit your changes with:

# Host OS
$ git add -A
$ git commit -m "[BDD:GREEN] code for test: login/logout"

11. Visit app with your browser

Run web browser and visit:

http://localhost:8880/
http://localhost:8880/app_dev.php/

12. Remove unnecessary commits

Remove unnecessary commits from your repository:

$ git remote rm origin
$ git branch -D 2.7
$ git tag | xargs git tag -d
$ git reflog expire --all --expire=now
$ git prune
$ git gc

Now your repository contains only the commits that you have authored working on this example.

13. The Example

You will find the source code of the example on GitHub.

For the instruction how to run the example refer to README.md file.

Fork me on GitHub