25 | * @license http://opensource.org/licenses/MIT MIT
26 | * @version Release: 2.0
27 | * @link https://github.com/codeconsortium/CCDNUserSecurityBundle
28 | *
29 | */
30 | class SessionModel extends BaseModel implements ModelInterface
31 | {
32 | /**
33 | *
34 | * @access public
35 | * @param string $ipAddress
36 | * @param string $timeLimit
37 | * @return \Doctrine\Common\Collections\ArrayCollection
38 | */
39 | public function findAllByIpAddressAndLoginAttemptDate($ipAddress, $timeLimit)
40 | {
41 | return $this->getRepository()->findAllByIpAddressAndLoginAttemptDate($ipAddress, $timeLimit);
42 | }
43 |
44 | /**
45 | *
46 | * @access public
47 | * @param string $ipAddress
48 | * @param string $username
49 | * @return \CCDNUser\SecurityBundle\Model\FrontModel\SessionModel
50 | */
51 | public function newRecord($ipAddress, $username)
52 | {
53 | return $this->getManager()->newRecord($ipAddress, $username);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [NO LONGER SUPPORTED] CCDNUser SecurityBundle README.
2 | ===============================
3 |
4 | [](https://insight.sensiolabs.com/projects/bc552d3d-50ea-4287-8398-ed165db32f78) [](https://travis-ci.org/codeconsortium/CCDNUserSecurityBundle) [](https://scrutinizer-ci.com/g/codeconsortium/CCDNUserSecurityBundle/) [](https://scrutinizer-ci.com/g/codeconsortium/CCDNUserSecurityBundle/) [](https://packagist.org/packages/codeconsortium/ccdn-user-security-bundle) [](https://packagist.org/packages/codeconsortium/ccdn-user-security-bundle) [](https://waffle.io/codeconsortium/ccdnusersecuritybundle)
5 |
6 | ## Notes:
7 |
8 | This is no longer supported or worked on. If you wish to continue using this and wish to take over let me know.
9 |
10 | This bundle is for the symfony framework and requires Symfony ~2.4 and PHP >=5.3.2
11 |
12 | This project uses Doctrine >=2.1 and so does not require any specific database.
13 |
14 | This file is part of the CCDNUser bundles(s)
15 |
16 | © CCDN © [CodeConsortium](http://www.codeconsortium.com/)
17 |
18 | Available on:
19 | * [Github](http://www.github.com/codeconsortium/CCDNUserSecurityBundle)
20 | * [Packagist](https://packagist.org/packages/codeconsortium/ccdn-user-security-bundle)
21 |
22 | For the full copyright and license information, please view the [LICENSE](http://github.com/codeconsortium/CCDNUserSecurityBundle/blob/master/Resources/meta/LICENSE) file that was distributed with this source code.
23 |
24 | [](https://insight.sensiolabs.com/projects/bc552d3d-50ea-4287-8398-ed165db32f78)
25 | [](http://knpbundles.com/codeconsortium/CCDNUserSecurityBundle)
26 |
27 | ## Description:
28 |
29 | Use this bundle to mitigate brute force dictionary attacks on your sites. Excessive failed logins will force users to recover their account, additional attempts
30 | to circumvent that will block the user from specified webpages by returning an HTTP 500 response on all specified routes.
31 |
32 | ### You can use this bundle with any User Bundle you like.
33 |
34 | > This bundle does *NOT* provide user registration/login/logout etc features. This bundle is for brute force dictionary attack mitigation only. Use this bundle in conjunction with your preferred user bundle.
35 |
36 | ## Features.
37 |
38 | SecurityBundle Provides the following features:
39 |
40 | 1. Prevent brute force attacks being carried out by limiting number of login attempts:
41 | 1. When first limit is reached, redirect to an account recovery page.
42 | 2. When secondary limit is reached, return an HTTP 500 status to block login pages etc.
43 | 3. All limits are configurable.
44 | 4. Routes to block are configurable.
45 | 5. Route for account recovery page is configurable.
46 | 6. Decoupled from UserBundle specifics. You can use this with any user bundle you like.
47 | 6. Redirect user to last page they were on upon successful login.
48 | 7. Redirect user to last page they were on upon successful logout.
49 |
50 | ## Documentation.
51 |
52 | Documentation can be found in the `Resources/doc/index.md` file in this bundle:
53 |
54 | [Read the Documentation](http://github.com/codeconsortium/CCDNUserSecurityBundle/blob/master/Resources/doc/index.md).
55 |
56 | ## Installation.
57 |
58 | All the installation instructions are located in [documentation](http://github.com/codeconsortium/CCDNUserSecurityBundle/blob/master/Resources/doc/install.md).
59 |
60 | ## License.
61 |
62 | This software is licensed under the MIT license. See the complete license file in the bundle:
63 |
64 | Resources/meta/LICENSE
65 |
66 | [Read the License](http://github.com/codeconsortium/CCDNUserSecurityBundle/blob/master/Resources/meta/LICENSE).
67 |
68 | ## About.
69 |
70 | [CCDNUser SecurityBundle](http://github.com/codeconsortium/CCDNUserSecurityBundle) is free software from [Code Consortium](http://www.codeconsortium.com).
71 | See also the list of [contributors](http://github.com/codeconsortium/CCDNUserSecurityBundle/contributors).
72 |
73 | ## Reporting an issue or feature request.
74 |
75 | Issues and feature requests are tracked in the [Github issue tracker](http://github.com/codeconsortium/CCDNUserSecurityBundle/issues).
76 |
77 | Discussions and debates on the project can be further discussed at [Code Consortium](http://www.codeconsortium.com).
78 |
--------------------------------------------------------------------------------
/Resources/config/doctrine/Session.orm.yml:
--------------------------------------------------------------------------------
1 | CCDNUser\SecurityBundle\Entity\Session:
2 | type: entity
3 | table: cc_security_session
4 | id:
5 | id:
6 | type: integer
7 | generator: { strategy: AUTO }
8 | fields:
9 | ipAddress:
10 | type: string
11 | column: ip_address
12 | length: 50
13 | loginAttemptDate:
14 | type: datetime
15 | column: login_attempt_date
16 | loginAttemptUsername:
17 | type: text
18 | column: login_attempt_username
19 |
--------------------------------------------------------------------------------
/Resources/config/routing.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeconsortium/CCDNUserSecurityBundle/c99576c53611fe91220708474a58538eead0ce1d/Resources/config/routing.yml
--------------------------------------------------------------------------------
/Resources/config/services.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 |
3 | # Service Parameters defined in app/config
4 |
5 | services:
6 |
--------------------------------------------------------------------------------
/Resources/config/services/components.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 |
3 | # Service Parameters defined in app/config
4 |
5 | services:
6 |
7 | #
8 | # Login/Logout Success/Failure Handlers.
9 | #
10 | ccdn_user_security.component.authentication.handler.login_failure_handler:
11 | class: %ccdn_user_security.component.authentication.handler.login_failure_handler.class%
12 | parent: security.authentication.failure_handler
13 | calls:
14 | - [setLoginFailureTracker, ['@ccdn_user_security.component.authentication.tracker.login_failure_tracker']]
15 |
16 | ccdn_user_security.component.authentication.tracker.login_failure_tracker:
17 | class: %ccdn_user_security.component.authentication.tracker.login_failure_tracker.class%
18 | arguments:
19 | - @ccdn_user_security.model.session
20 |
21 | #
22 | # Access Decision Manager
23 | #
24 | ccdn_user_security.component.authorisation.security_manager:
25 | class: %ccdn_user_security.component.authorisation.security_manager.class%
26 | arguments:
27 | - @request_stack
28 | - @ccdn_user_security.component.authentication.tracker.login_failure_tracker
29 | - %ccdn_user_security.login_shield.route_login%
30 | - %ccdn_user_security.login_shield.force_account_recovery%
31 | - %ccdn_user_security.login_shield.block_pages%
32 |
33 | #
34 | # Authorisation Voter
35 | #
36 | ccdn_user_security.component.authorisation.voter.client_login_voter:
37 | class: %ccdn_user_security.component.authorisation.voter.client_login_voter.class%
38 | arguments:
39 | - @ccdn_user_security.component.authorisation.security_manager
40 | tags:
41 | - { name: security.voter }
42 |
43 | #
44 | # Blocking login Listener.
45 | #
46 | ccdn_user_security.component.listener.blocking_login_listener:
47 | class: %ccdn_user_security.component.listener.blocking_login_listener.class%
48 | arguments:
49 | - @ccdn_user_security.component.authorisation.security_manager
50 | - @ccdn_user_security.component.access_denied_exception_factory
51 | tags:
52 | - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 9 }
53 | ccdn_user_security.component.access_denied_exception_factory:
54 | class: %ccdn_user_security.component.access_denied_exception_factory.class%
55 |
56 | #
57 | # Defer login Listener.
58 | #
59 | ccdn_user_security.component.listener.defer_login_listener:
60 | class: %ccdn_user_security.component.listener.defer_login_listener.class%
61 | arguments:
62 | - @router
63 | - @ccdn_user_security.component.authorisation.security_manager
64 | - %ccdn_user_security.login_shield.force_account_recovery%
65 | tags:
66 | - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
67 |
68 | #
69 | # For legacy compatibility, we alias deprecated listeners
70 | #
71 | ccdn_user_security.component.authentication.handler.login_success_handler:
72 | parent: security.authentication.success_handler
73 |
74 | ccdn_user_security.component.authentication.handler.logout_success_handler:
75 | parent: security.logout.success_handler
76 |
--------------------------------------------------------------------------------
/Resources/config/services/model-gateway.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 |
3 | # Service Parameters defined in app/config
4 |
5 | services:
6 |
7 | #
8 | # Gateways.
9 | #
10 | ccdn_user_security.gateway.session:
11 | class: %ccdn_user_security.gateway.session.class%
12 | arguments:
13 | - @doctrine.orm.entity_manager
14 | - %ccdn_user_security.entity.session.class%
15 |
--------------------------------------------------------------------------------
/Resources/config/services/model-manager.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 |
3 | # Service Parameters defined in app/config
4 |
5 | services:
6 |
7 | #
8 | # Managers.
9 | #
10 | ccdn_user_security.manager.session:
11 | class: %ccdn_user_security.manager.session.class%
12 | arguments:
13 | - @event_dispatcher
14 | - @ccdn_user_security.gateway.session
15 |
--------------------------------------------------------------------------------
/Resources/config/services/model-repository.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 |
3 | # Service Parameters defined in app/config
4 |
5 | services:
6 |
7 | #
8 | # Repositories.
9 | #
10 | ccdn_user_security.repository.session:
11 | class: %ccdn_user_security.repository.session.class%
12 | arguments:
13 | - @ccdn_user_security.gateway.session
14 |
--------------------------------------------------------------------------------
/Resources/config/services/model.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 |
3 | # Service Parameters defined in app/config
4 |
5 | services:
6 |
7 | #
8 | # Models.
9 | #
10 | ccdn_user_security.model.session:
11 | class: %ccdn_user_security.model.session.class%
12 | arguments:
13 | - @event_dispatcher
14 | - @ccdn_user_security.repository.session
15 | - @ccdn_user_security.manager.session
16 |
--------------------------------------------------------------------------------
/Resources/doc/configuration_reference.md:
--------------------------------------------------------------------------------
1 | CCDNUser SecurityBundle Configuration Reference.
2 | ================================================
3 |
4 | All available configuration options are listed below with their default values.
5 |
6 | ``` yml
7 | #
8 | # for CCDNUser SecurityBundle
9 | #
10 | ccdn_user_security:
11 | entity:
12 | user:
13 | class: Acme\YourUserBundle\Entity\User # Required
14 | login_shield:
15 | route_login:
16 | name: fos_user_security_login
17 | params: []
18 | force_account_recovery: # Specify all routes to block after attempt limit is reached, and account recovery route to force browser redirect.
19 | enabled: true
20 | after_attempts: 2
21 | duration_in_minutes: 1
22 | route_recover_account:
23 | name: fos_user_resetting_request
24 | params: []
25 | routes:
26 | - fos_user_security_login
27 | - fos_user_security_check
28 | - fos_user_security_logout
29 | block_pages: # Specify all routes to block after attempt limit is reached.
30 | enabled: true
31 | after_attempts: 4
32 | duration_in_minutes: 2
33 | routes:
34 | - fos_user_security_login
35 | - fos_user_security_check
36 | - fos_user_security_logout
37 | - fos_user_registration_register
38 | - fos_user_registration_check_email
39 | - fos_user_registration_confirm
40 | - fos_user_registration_confirmed
41 | - fos_user_resetting_request
42 | - fos_user_resetting_send_email
43 | ```
44 |
45 | Please note that for either 'force_account_recovery' or 'block_pages' to function, you need to specify the 'route_login' config, also you must specify the route for the account recovery page.
46 |
47 | Once you have enabled either 'force_account_recovery' or 'block_pages', you must specify the routes that you want blocked once the number of attempts has been reached.
48 |
49 | In order that the forced account recovery process works, the limit must be set lower than the block_pages process, otherwise page blocking will supersede this and prevent it from working.
50 |
51 | Replace Acme\YourUserBundle\Entity\User with the user class of your chosen user bundle.
52 |
53 | - [Return back to the docs index](index.md).
54 |
--------------------------------------------------------------------------------
/Resources/doc/index.md:
--------------------------------------------------------------------------------
1 | CCDNUser SecurityBundle Documentation.
2 | ======================================
3 |
4 | ### Translations
5 |
6 | If you wish to use default texts provided in this bundle, you have to make sure you have translator enabled in your config.
7 |
8 | ``` yaml
9 | # app/config/config.yml
10 |
11 | framework:
12 | translator: ~
13 | ```
14 |
15 | For more information about translations, check [Symfony documentation](http://symfony.com/doc/current/book/translation.html).
16 |
17 | ## Installation Documentation:
18 |
19 | - [Installing CCDNUser SecurityBundle for Symfony](install.md).
20 | - [Configuration Reference](configuration_reference.md).
21 |
--------------------------------------------------------------------------------
/Resources/doc/install.md:
--------------------------------------------------------------------------------
1 | Installing CCDNUser SecurityBundle.
2 | ===================================
3 |
4 | ## Dependencies:
5 |
6 | > Note you will need a User Bundle so that you can map the UserInterface to your own User entity. You can use whatever User Bundle you prefer. FOSUserBundle is highly rated.
7 |
8 | ## Installation:
9 |
10 | Installation takes only 5 steps:
11 |
12 | 1. Download and install dependencies via Composer.
13 | 2. Register bundles with AppKernel.php.
14 | 3. Update your app/config/config.yml.
15 | 4. enable handlers
16 | 5. Update your database schema.
17 |
18 | ### Step 1: Download and install dependencies via Composer.
19 |
20 | Append the following to end of your applications composer.json file (found in the root of your Symfony2 installation):
21 |
22 | ``` js
23 | // composer.json
24 | {
25 | // ...
26 | "require": {
27 | // ...
28 | "codeconsortium/ccdn-user-security-bundle": "dev-master"
29 | }
30 | }
31 | ```
32 |
33 | NOTE: Please replace ``dev-master`` in the snippet above with the latest stable branch, for example ``2.0.*``.
34 |
35 | Then, you can install the new dependencies by running Composer's ``update``
36 | command from the directory where your ``composer.json`` file is located:
37 |
38 | ``` bash
39 | $ php composer.phar update
40 | ```
41 |
42 | ### Step 2: Register bundles with AppKernel.php.
43 |
44 | Now, Composer will automatically download all required files, and install them
45 | for you. All that is left to do is to update your ``AppKernel.php`` file, and
46 | register the new bundle:
47 |
48 | ``` php
49 | // app/AppKernel.php
50 | public function registerBundles()
51 | {
52 | $bundles = array(
53 | new CCDNUser\SecurityBundle\CCDNUserSecurityBundle(),
54 | // ...
55 | );
56 | }
57 | ```
58 |
59 | ### Step 3: Update your app/config/config.yml.
60 |
61 | In your app/config/config.yml add:
62 |
63 | ``` yml
64 | #
65 | # for CCDNUser SecurityBundle
66 | #
67 | ccdn_user_security:
68 | entity:
69 | user:
70 | class: Acme\YourUserBundle\Entity\User # Required
71 | login_shield:
72 | route_login:
73 | name: fos_user_security_login
74 | params: []
75 | force_account_recovery: # Specify all routes to block after attempt limit is reached, and account recovery route to force browser redirect.
76 | enabled: true
77 | after_attempts: 2
78 | duration_in_minutes: 1
79 | route_recover_account:
80 | name: fos_user_resetting_request
81 | params: []
82 | routes:
83 | - fos_user_security_login
84 | - fos_user_security_check
85 | - fos_user_security_logout
86 | block_pages: # Specify all routes to block after attempt limit is reached.
87 | enabled: true
88 | after_attempts: 4
89 | duration_in_minutes: 2
90 | routes:
91 | - fos_user_security_login
92 | - fos_user_security_check
93 | - fos_user_security_logout
94 | - fos_user_registration_register
95 | - fos_user_registration_check_email
96 | - fos_user_registration_confirm
97 | - fos_user_registration_confirmed
98 | - fos_user_resetting_request
99 | - fos_user_resetting_send_email
100 | ```
101 |
102 | > Routes added are for FOSUserBundle and are added as an example only, choose the correct routes for the user bundle of your choice. If however you are using FOSUserBundle then the routes shown above should work for you.
103 |
104 | Replace Acme\YourUserBundle\Entity\User with the user class of your chosen user bundle.
105 |
106 | Add or remove routes as you see fit to the ignore list or list of routes to block when denied.
107 |
108 | Use the ignore list for routes you do not want to track for the redirect path after a successful login.
109 |
110 | >Please note that for either 'force_account_recovery' or 'block_pages' to function, you need to specify the 'route_login' config, also you must specify the route for the account recovery page.
111 | >Once you have enabled either 'force_account_recovery' or 'block_pages', you must specify the routes that you want blocked once the number of attempts has been reached.
112 | >In order that the forced account recovery process works, the limit must be set lower than the block_pages process, otherwise page blocking will supersede this and prevent it from working and the route must be provided for the account recovery page.
113 |
114 | ### Step 4: enable handlers
115 |
116 | You have to enable your login-/logout-handlers via app/config/security.yml:
117 |
118 | ```
119 | security:
120 | firewalls:
121 | main:
122 | form_login:
123 | provider: fos_userbundle
124 | login_path: /login
125 | use_forward: false
126 | check_path: /login_check
127 | failure_handler: ccdn_user_security.component.authentication.handler.login_failure_handler
128 | logout:
129 | path: /logout
130 | ```
131 |
132 |
133 | ### Step 5: Update your database schema.
134 |
135 | Make sure to add the SecurityBundle to doctrines mapping configuration:
136 |
137 | ```
138 | # app/config/config.yml
139 | # Doctrine Configuration
140 | doctrine:
141 | orm:
142 | default_entity_manager: default
143 | auto_generate_proxy_classes: "%kernel.debug%"
144 | entity_managers:
145 | default:
146 | mappings:
147 | CCDNUserSecurityBundle:
148 | mapping: true
149 | type: yml
150 | dir: "Resources/config/doctrine"
151 | alias: ~
152 | prefix: CCDNUser\SecurityBundle\Entity
153 | is_bundle: true
154 | ```
155 |
156 | From your projects root Symfony directory on the command line run:
157 |
158 | ``` bash
159 | $ php app/console doctrine:schema:update --dump-sql
160 | ```
161 |
162 | Take the SQL that is output and update your database manually.
163 |
164 | **Warning:**
165 |
166 | > Please take care when updating your database, check the output SQL before applying it.
167 |
168 | ## Next Steps.
169 |
170 | Installation should now be complete!
171 |
172 | If you need further help/support, have suggestions or want to contribute please join the community at [Code Consortium](http://www.codeconsortium.com)
173 |
174 | - [Return back to the docs index](index.md).
175 | - [Configuration Reference](configuration_reference.md).
176 |
--------------------------------------------------------------------------------
/Resources/meta/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2011-2012 CodeConsortium
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | of the Software, and to permit persons to whom the Software is furnished to do
8 | so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
--------------------------------------------------------------------------------
/Resources/views/home.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hi on this test home page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Resources/views/login.html.twig:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/Tests/Functional/app/AppKernel.php:
--------------------------------------------------------------------------------
1 | load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
34 | }
35 |
36 | /**
37 | * @return string
38 | */
39 | public function getCacheDir()
40 | {
41 | return sys_get_temp_dir().'/CCDNUserSecurityBundle/cache/' . $this->getEnvironment();
42 | }
43 |
44 | /**
45 | * @return string
46 | */
47 | public function getLogDir()
48 | {
49 | return sys_get_temp_dir().'/CCDNUserSecurityBundle/logs';
50 | }
51 |
52 | /**
53 | *
54 | * @link http://kriswallsmith.net/post/27979797907/get-fast-an-easy-symfony2-phpunit-optimization
55 | * (does not work)
56 | */
57 | // protected function initializeContainer()
58 | // {
59 | // static $first = true;
60 | //
61 | // if ('test' !== $this->getEnvironment()) {
62 | // parent::initializeContainer();
63 | // return;
64 | // }
65 | //
66 | // $debug = $this->debug;
67 | //
68 | // if (!$first) {
69 | // // disable debug mode on all but the first initialization
70 | // $this->debug = false;
71 | // }
72 | //
73 | // // will not work with --process-isolation
74 | // $first = false;
75 | //
76 | // try {
77 | // parent::initializeContainer();
78 | // } catch (\Exception $e) {
79 | // $this->debug = $debug;
80 | // throw $e;
81 | // }
82 | //
83 | // $this->debug = $debug;
84 | // }
85 | }
--------------------------------------------------------------------------------
/Tests/Functional/app/config/ccdn/user-security.yml:
--------------------------------------------------------------------------------
1 | ccdn_user_security:
2 | entity:
3 | user:
4 | class: CCDNUser\SecurityBundle\Tests\Functional\src\Entity\User
5 | route_referer:
6 | enabled: false
7 | route_ignore_list:
8 | - fos_user_security_login
9 | - fos_user_security_check
10 | - fos_user_security_logout
11 | - fos_user_registration_register
12 | - fos_user_registration_check_email
13 | - fos_user_registration_confirm
14 | - fos_user_registration_confirmed
15 | - fos_user_resetting_request
16 | - fos_user_resetting_send_email
17 | - fos_user_resetting_check_email
18 | - fos_user_resetting_reset
19 | - fos_user_change_password
20 | login_shield:
21 | route_login:
22 | name: fos_user_security_login
23 | params: []
24 | force_account_recovery: # Specify all routes to block after attempt limit is reached, and account recovery route to force browser redirect.
25 | enabled: true
26 | after_attempts: 2
27 | duration_in_minutes: 1
28 | route_recover_account:
29 | name: fos_user_resetting_request
30 | params: []
31 | routes:
32 | - fos_user_security_login
33 | - fos_user_security_check
34 | - fos_user_security_logout
35 | block_pages: # Specify all routes to block after attempt limit is reached.
36 | enabled: true
37 | after_attempts: 4
38 | duration_in_minutes: 2
39 | routes:
40 | - fos_user_security_login
41 | - fos_user_security_check
42 | - fos_user_security_logout
43 | - fos_user_registration_register
44 | - fos_user_registration_check_email
45 | - fos_user_registration_confirm
46 | - fos_user_registration_confirmed
47 | - fos_user_resetting_request
48 | - fos_user_resetting_send_email
49 |
--------------------------------------------------------------------------------
/Tests/Functional/app/config/config.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: parameters.yml }
3 | - { resource: ccdn/user-security.yml }
4 |
5 | framework:
6 | test: ~
7 | #esi: ~
8 | translator: { fallback: "%locale%" }
9 | translator: ~
10 | secret: "secret"
11 | router:
12 | resource: "%kernel.root_dir%/config/routing.yml"
13 | strict_requirements: "%kernel.debug%"
14 | form: true
15 | csrf_protection: true
16 | validation: { enable_annotations: true }
17 | templating:
18 | engines: ['twig']
19 | #assets_version: SomeVersionScheme
20 | default_locale: "%locale%"
21 | trusted_proxies: ~
22 | session:
23 | storage_id: session.storage.mock_file
24 | fragments: ~
25 | http_method_override: true
26 | profiler: { only_exceptions: false }
27 |
28 | monolog:
29 | handlers:
30 | main:
31 | type: test
32 | # main:
33 | # type: stream
34 | # path: "%kernel.logs_dir%/%kernel.environment%.log"
35 | # level: debug
36 | # firephp:
37 | # type: firephp
38 | # level: info
39 |
40 | # Twig Configuration
41 | twig:
42 | debug: "%kernel.debug%"
43 | strict_variables: "%kernel.debug%"
44 | form:
45 | resources: ~
46 |
47 | # Doctrine Configuration
48 | doctrine:
49 | dbal:
50 | driver: "%database_driver%"
51 | host: "%database_host%"
52 | port: "%database_port%"
53 | dbname: "%database_name%"
54 | user: "%database_user%"
55 | password: "%database_password%"
56 | charset: UTF8
57 | orm:
58 | default_entity_manager: default
59 | auto_generate_proxy_classes: "%kernel.debug%"
60 | #auto_mapping: true
61 | resolve_target_entities:
62 | # For testing purposes only
63 | 'Symfony\Component\Security\Core\User\UserInterface': 'CCDNUser\SecurityBundle\Tests\Functional\src\Entity\User'
64 | entity_managers:
65 | default:
66 | mappings:
67 | CCDNUserSecurityBundle:
68 | mapping: true
69 | type: yml
70 | dir: "Resources/config/doctrine"
71 | alias: ~
72 | prefix: CCDNUser\SecurityBundle\Entity
73 | is_bundle: true
74 | CCDNUserSecurityBundleUserEntity:
75 | mapping: true
76 | type: yml
77 | dir: "Tests/Functional/src/Resources/config/doctrine"
78 | alias: ~
79 | prefix: CCDNUser\SecurityBundle\Tests\Functional\src\Entity
80 | is_bundle: false
81 |
82 | security:
83 | role_hierarchy:
84 | ROLE_USER: ROLE_USER
85 | ROLE_MODERATOR: [ROLE_USER]
86 | ROLE_ADMIN: [ROLE_USER, ROLE_MODERATOR]
87 | ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_MODERATOR, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
88 | encoders:
89 | FOS\UserBundle\Model\UserInterface: sha512
90 | providers:
91 | fos_userbundle:
92 | id: fos_user.user_provider.username_email
93 | # in_memory:
94 | # memory:
95 | # users:
96 | # user: { password: root, roles: [ 'ROLE_USER' ] }
97 | # moderator: { password: root, roles: [ 'ROLE_MODERATOR' ] }
98 | # admin: { password: root, roles: [ 'ROLE_ADMIN' ] }
99 | firewalls:
100 | main:
101 | switch_user: true
102 | pattern: ^/
103 | form_login:
104 | provider: fos_userbundle
105 | login_path: /login
106 | use_forward: false
107 | check_path: /login_check
108 | success_handler: ccdn_user_security.component.authentication.handler.login_success_handler
109 | failure_handler: ccdn_user_security.component.authentication.handler.login_failure_handler
110 | failure_path: null
111 | csrf_provider: form.csrf_provider
112 | #success_handler:
113 | logout:
114 | path: /logout
115 | target: /
116 | success_handler: ccdn_user_security.component.authentication.handler.logout_success_handler
117 | anonymous: true
118 | http_basic:
119 | #switch_user: true
120 | #pattern: ^/
121 | #logout:
122 | #anonymous: true
123 | dev:
124 | pattern: ^/(_(Securityr|wdt)|css|images|js)/
125 | security: false
126 | remember_me:
127 | key: secret
128 | lifetime: 604800
129 | access_control:
130 | #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
131 | # You must uncomment the two following rules to restrict access to paths
132 | # starting with the /_internal prefix to only localhost
133 | #- { path: ^/_internal/secure, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
134 | #- { path: ^/_internal/secure, roles: ROLE_NO_ACCESS }
135 |
136 | fos_user:
137 | db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
138 | firewall_name: main
139 | user_class: CCDNUser\SecurityBundle\Tests\Functional\src\Entity\User
140 |
141 |
--------------------------------------------------------------------------------
/Tests/Functional/app/config/config_dev.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: config.yml }
3 |
--------------------------------------------------------------------------------
/Tests/Functional/app/config/config_prod.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: config.yml }
3 |
--------------------------------------------------------------------------------
/Tests/Functional/app/config/config_test.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: config.yml }
3 |
--------------------------------------------------------------------------------
/Tests/Functional/app/config/routing.yml:
--------------------------------------------------------------------------------
1 |
2 | fos_user_security:
3 | resource: "@FOSUserBundle/Resources/config/routing/security.xml"
4 |
5 | fos_user_profile:
6 | resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
7 | prefix: /profile
8 |
9 | fos_user_register:
10 | resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
11 | prefix: /register
12 |
13 | fos_user_resetting:
14 | resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
15 | prefix: /resetting
16 |
17 | fos_user_change_password:
18 | resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
19 | prefix: /profile
20 |
21 | ccdn_user_security_circumvent_login:
22 | pattern: /circumvent_login
23 | defaults: { _controller: CCDNUserSecurityBundle:TestLogin:circumvent }
24 |
25 | home:
26 | path: /
27 | defaults:
28 | _controller: FrameworkBundle:Template:template
29 | template: 'CCDNUserSecurityBundle::home.html.twig'
30 |
--------------------------------------------------------------------------------
/Tests/Functional/app/config/routing_dev.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: routing.yml }
3 |
--------------------------------------------------------------------------------
/Tests/Functional/app/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');
18 | $debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod';
19 |
20 | $kernel = new AppKernel($env, $debug);
21 | $application = new Application($kernel);
22 | $application->run($input);
23 |
--------------------------------------------------------------------------------
/Tests/Functional/bootstrap.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * Available on github
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | use Doctrine\Common\Annotations\AnnotationRegistry;
15 |
16 | if (!file_exists($file = __DIR__.'/../../vendor/autoload.php')) {
17 | throw new \RuntimeException('Install the dependencies to run the test suite.');
18 | }
19 |
20 | $loader = require $file;
21 | AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
22 |
--------------------------------------------------------------------------------
/Tests/Functional/src/Entity/User.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * Available on github
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace CCDNUser\SecurityBundle\Tests\Manager;
15 |
16 | use CCDNUser\SecurityBundle\Tests\TestBase;
17 |
18 | /**
19 | *
20 | * @category CCDNUser
21 | * @package SecurityBundle
22 | *
23 | * @author Reece Fowell
24 | * @license http://opensource.org/licenses/MIT MIT
25 | * @version Release: 1.0
26 | * @link https://github.com/codeconsortium/CCDNUserSecurityBundle
27 | *
28 | */
29 | class SessionManagerTest extends TestBase
30 | {
31 | public function testNewRecord()
32 | {
33 | $this->addFixturesForUsers();
34 | $ipAddress = '127.0.0.1';
35 | $this->getSessionModel()->newRecord($ipAddress, 'tom');
36 | $timeLimit = new \DateTime('-' . 1 . ' minutes');
37 | $sessions = $this->getSessionModel()->findAllByIpAddressAndLoginAttemptDate($ipAddress, $timeLimit);
38 |
39 | $this->assertCount(1, $sessions);
40 | $this->assertInstanceOf('CCDNUser\SecurityBundle\Entity\Session', $sessions[0]);
41 | }
42 | }
--------------------------------------------------------------------------------
/Tests/Repository/SessionRepositoryTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * Available on github
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace CCDNUser\SecurityBundle\Tests\Repository;
15 |
16 | use CCDNUser\SecurityBundle\Tests\TestBase;
17 |
18 | /**
19 | *
20 | * @category CCDNUser
21 | * @package SecurityBundle
22 | *
23 | * @author Reece Fowell
24 | * @license http://opensource.org/licenses/MIT MIT
25 | * @version Release: 1.0
26 | * @link https://github.com/codeconsortium/CCDNUserSecurityBundle
27 | *
28 | */
29 | class SessionRepositoryTest extends TestBase
30 | {
31 | public function testFindAllByIpAddressAndLoginAttemptDate()
32 | {
33 | $this->addFixturesForUsers();
34 | $ipAddress = '127.0.0.1';
35 | $this->getSessionModel()->newRecord($ipAddress, 'tom');
36 | $this->getSessionModel()->newRecord($ipAddress, 'tom');
37 | $this->getSessionModel()->newRecord($ipAddress, 'tom');
38 | $this->getSessionModel()->newRecord($ipAddress, 'tom');
39 |
40 | $timeLimit = new \DateTime('-' . 1 . ' minutes');
41 | $sessions = $this->getSessionModel()->findAllByIpAddressAndLoginAttemptDate($ipAddress, $timeLimit);
42 |
43 | $this->assertCount(4, $sessions);
44 | }
45 | }
--------------------------------------------------------------------------------
/Tests/TestBase.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * Available on github
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace CCDNUser\SecurityBundle\Tests;
15 |
16 | use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
17 | use Doctrine\Common\DataFixtures\Purger\ORMPurger;
18 | use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
19 |
20 | use CCDNUser\SecurityBundle\Tests\Functional\src\Entity\User;
21 | use CCDNUser\SecurityBundle\Entity\Security;
22 |
23 | class TestBase extends WebTestCase
24 | {
25 | /**
26 | *
27 | * @var \Doctrine\ORM\EntityManager
28 | */
29 | protected $em;
30 |
31 | /**
32 | *
33 | * @var $container
34 | */
35 | private $container;
36 |
37 | /**
38 | *
39 | * @access public
40 | */
41 | public function setUp()
42 | {
43 | $kernel = static::createKernel();
44 |
45 | $kernel->boot();
46 |
47 | $this->container = $kernel->getContainer();
48 |
49 | $this->em = $this->container->get('doctrine.orm.entity_manager');
50 |
51 | $this->purge();
52 | }
53 |
54 | /*
55 | *
56 | * Close doctrine connections to avoid having a 'too many connections'
57 | * message when running many tests
58 | */
59 | public function tearDown(){
60 | if($this->container !== null){
61 | $this->container->get('doctrine')->getConnection()->close();
62 | }
63 |
64 | parent::tearDown();
65 | }
66 |
67 | protected function purge()
68 | {
69 | $purger = new ORMPurger($this->em);
70 | $executor = new ORMExecutor($this->em, $purger);
71 | $executor->purge();
72 | }
73 |
74 | protected function addNewUser($username, $email, $password)
75 | {
76 | $user = new User();
77 |
78 | $user->setUsername($username);
79 | $user->setEmail($email);
80 | $user->setPlainPassword($password);
81 |
82 | $this->em->persist($user);
83 |
84 | return $user;
85 | }
86 |
87 | protected function addFixturesForUsers()
88 | {
89 | $userNames = array('admin', 'tom', 'dick', 'harry');
90 | $users = array();
91 |
92 | foreach ($userNames as $username) {
93 | $users[$username] = $this->addNewUser($username, $username . '@foobar.com', 'password');
94 | }
95 |
96 | $this->em->flush();
97 |
98 | return $users;
99 | }
100 |
101 | /**
102 | *
103 | * @var \CCDNUser\SecurityBundle\Model\FrontModel\SessionModel $sessionModel
104 | */
105 | private $sessionModel;
106 |
107 | /**
108 | *
109 | * @access protected
110 | * @return \CCDNUser\SecurityBundle\Model\FrontModel\SessionModel
111 | */
112 | protected function getSessionModel()
113 | {
114 | if (null == $this->sessionModel) {
115 | $this->sessionModel = $this->container->get('ccdn_user_security.model.session');
116 | }
117 |
118 | return $this->sessionModel;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/behat.yml:
--------------------------------------------------------------------------------
1 | default:
2 | formatter:
3 | name: progress
4 | parameters:
5 | decorated: true
6 | verbose: false
7 | time: true
8 | language: en
9 | output_path: null
10 | multiline_arguments: true
11 | paths:
12 | features: features
13 | bootstrap: %behat.paths.features%/Context
14 | context:
15 | class: CCDNUser\SecurityBundle\features\bootstrap\FeatureContext
16 | extensions:
17 | Behat\Symfony2Extension\Extension:
18 | mink_driver: true
19 | context:
20 | path_suffix: features
21 | class_suffix: features\bootstrap
22 | kernel:
23 | env: test
24 | debug: true
25 | path: Tests/Functional/app/AppKernel.php
26 | bootstrap: Tests/Functional/bootstrap.php
27 | Behat\MinkExtension\Extension:
28 | default_session: 'symfony2'
29 | goutte: ~
30 | selenium2: ~
31 | # base_url: http://ccdn.local/
32 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "codeconsortium/ccdn-user-security-bundle",
3 | "description": "CCDN User Security Bundle",
4 | "keywords": ["ccdn", "codeconsortium", "user", "security", "brute force", "dictionary attack", "login"],
5 | "homepage": "http://github.com/codeconsortium/CCDNUserSecurityBundle",
6 | "type": "symfony-bundle",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "Reece Fowell",
11 | "email": "reece@codeconsortium.com",
12 | "homepage": "http://www.reecefowell.com"
13 | }
14 | ],
15 | "minimum-stability": "dev",
16 | "require": {
17 | "php": ">=5.3.3",
18 | "symfony/symfony": "~2.5",
19 | "doctrine/orm": "~2.2,>=2.2.3",
20 | "doctrine/doctrine-bundle": "~1.2"
21 | },
22 | "require-dev": {
23 | "symfony/swiftmailer-bundle": "~2.3",
24 | "symfony/monolog-bundle": "~2.4",
25 | "doctrine/doctrine-fixtures-bundle": "dev-master",
26 | "behat/behat": "2.5.*@stable",
27 | "behat/mink": "v1.5.0",
28 | "behat/mink-goutte-driver": "*",
29 | "behat/mink-browserkit-driver": "*",
30 | "behat/mink-selenium2-driver": "*",
31 | "behat/mink-extension": "*",
32 | "behat/symfony2-extension": "*",
33 | "phpunit/phpunit": "3.7.*",
34 | "raulfraile/ladybug-bundle": "dev-master",
35 | "friendsofsymfony/user-bundle": "~2.0@dev"
36 | },
37 | "autoload": {
38 | "psr-0": { "CCDNUser\\SecurityBundle": "" }
39 | },
40 | "target-dir": "CCDNUser/SecurityBundle"
41 | }
42 |
--------------------------------------------------------------------------------
/features/bootstrap/DataContext.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * Available on github
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace CCDNUser\SecurityBundle\features\bootstrap;
15 |
16 | use Behat\Behat\Context\BehatContext;
17 | use Behat\Gherkin\Node\TableNode;
18 | use Behat\Symfony2Extension\Context\KernelAwareInterface;
19 | use Symfony\Component\HttpKernel\KernelInterface;
20 |
21 | use CCDNUser\SecurityBundle\Tests\Functional\src\Entity\User;
22 | use CCDNUser\SecurityBundle\Entity\Profile;
23 |
24 | /**
25 | *
26 | * Features context.
27 | *
28 | * @category CCDNUser
29 | * @package SecurityBundle
30 | *
31 | * @author Reece Fowell
32 | * @license http://opensource.org/licenses/MIT MIT
33 | * @version Release: 2.0
34 | * @link https://github.com/codeconsortium/CCDNUserSecurityBundle
35 | *
36 | */
37 | class DataContext extends BehatContext implements KernelAwareInterface
38 | {
39 | /**
40 | *
41 | * Kernel.
42 | *
43 | * @var KernelInterface
44 | */
45 | protected $kernel;
46 |
47 | /**
48 | *
49 | * {@inheritdoc}
50 | */
51 | public function setKernel(KernelInterface $kernel)
52 | {
53 | $this->kernel = $kernel;
54 | }
55 |
56 | /**
57 | *
58 | * Get entity manager.
59 | *
60 | * @return EntityManager
61 | */
62 | public function getEntityManager()
63 | {
64 | return $this->getContainer()->get('doctrine')->getManager();
65 | }
66 |
67 | /**
68 | *
69 | * Returns Container instance.
70 | *
71 | * @return ContainerInterface
72 | */
73 | protected function getContainer()
74 | {
75 | return $this->kernel->getContainer();
76 | }
77 |
78 | /**
79 | *
80 | * Get service by id.
81 | *
82 | * @param string $id
83 | *
84 | * @return object
85 | */
86 | protected function getService($id)
87 | {
88 | return $this->getContainer()->get($id);
89 | }
90 |
91 | protected $users = array();
92 |
93 | /**
94 | *
95 | * @Given /^there are following users defined:$/
96 | */
97 | public function thereAreFollowingUsersDefined(TableNode $table)
98 | {
99 | foreach ($table->getHash() as $data) {
100 | $username = isset($data['name']) ? $data['name'] : sha1(uniqid(mt_rand(), true));
101 |
102 | $this->users[$username] = $this->thereIsUser(
103 | $username,
104 | isset($data['email']) ? $data['email'] : sha1(uniqid(mt_rand(), true)),
105 | isset($data['password']) ? $data['password'] : 'password',
106 | isset($data['role']) ? $data['role'] : 'ROLE_USER',
107 | isset($data['enabled']) ? $data['enabled'] : true
108 | );
109 | }
110 |
111 | $this->getEntityManager()->flush();
112 | }
113 |
114 | public function thereIsUser($username, $email, $password, $role = 'ROLE_USER', $enabled = true)
115 | {
116 | $user = new User();
117 |
118 | $user->setUsername($username);
119 | $user->setEmail($email);
120 | $user->setEnabled($enabled);
121 | $user->setPlainPassword($password);
122 |
123 | if (null !== $role) {
124 | $user->addRole($role);
125 | }
126 |
127 | $this->getEntityManager()->persist($user);
128 |
129 | return $user;
130 | }
131 |
132 | protected $profiles = array();
133 |
134 | /**
135 | *
136 | * @Given /^there are following profiles defined:$/
137 | */
138 | public function thereAreFollowingProfilesDefined(TableNode $table)
139 | {
140 | foreach ($table->getHash() as $data) {
141 | $username = isset($data['user']) ? $data['user'] : sha1(uniqid(mt_rand(), true));
142 |
143 | if (isset($this->users[$username])) {
144 | $this->profiles[$username] = $this->thereIsProfile(
145 | $this->users[$username],
146 | isset($data['country']) ? $data['country'] : null,
147 | isset($data['city']) ? $data['city'] : null,
148 | isset($data['real_name']) ? $data['real_name'] : null,
149 | isset($data['birthday']) ? new \Datetime($data['birthday']) : null,
150 | isset($data['company']) ? $data['company'] : null,
151 | isset($data['position']) ? $data['position'] : null,
152 | isset($data['bio']) ? $data['bio'] : null,
153 | isset($data['signature']) ? $data['signature'] : null,
154 | isset($data['msn']) ? $data['msn'] : null,
155 | isset($data['aim']) ? $data['aim'] : null,
156 | isset($data['yahoo']) ? $data['yahoo'] : null,
157 | isset($data['icq']) ? $data['icq'] : true
158 | );
159 | }
160 | }
161 |
162 | $this->getEntityManager()->flush();
163 | }
164 |
165 | public function thereIsProfile(User $user, $country, $city, $realName, \Datetime $birthday, $company, $position, $bio, $signature, $msn, $aim, $yahoo, $icq)
166 | {
167 | $profile = new Profile();
168 |
169 | $profile->setUser($user);
170 | $profile->setLocationCountry($country);
171 | $profile->setLocationCity($city);
172 | $profile->setRealName($realName);
173 | $profile->setBirthDate($birthday);
174 | $profile->setCompany($company);
175 | $profile->setPosition($position);
176 | $profile->setBio($bio);
177 | $profile->setSignature($signature);
178 | $profile->setMsn($msn);
179 | $profile->setMsnPublic(true);
180 | $profile->setAim($aim);
181 | $profile->setAimPublic(true);
182 | $profile->setYahoo($yahoo);
183 | $profile->setYahooPublic(true);
184 | $profile->setIcq($icq);
185 | $profile->setIcqPublic(true);
186 |
187 | $this->getEntityManager()->persist($profile);
188 |
189 | return $user;
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/features/bootstrap/FeatureContext.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * Available on github
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace CCDNUser\SecurityBundle\features\bootstrap;
15 |
16 | use Behat\MinkExtension\Context\RawMinkContext;
17 | use Behat\Symfony2Extension\Context\KernelAwareInterface;
18 | use Doctrine\Common\DataFixtures\Purger\ORMPurger;
19 | use Symfony\Component\HttpKernel\KernelInterface;
20 | use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
21 | use CCDNUser\SecurityBundle\features\bootstrap\WebUser;
22 |
23 | /**
24 | *
25 | * Features context.
26 | *
27 | * @category CCDNUser
28 | * @package SecurityBundle
29 | *
30 | * @author Reece Fowell
31 | * @license http://opensource.org/licenses/MIT MIT
32 | * @version Release: 2.0
33 | * @link https://github.com/codeconsortium/CCDNUserSecurityBundle
34 | *
35 | */
36 | class FeatureContext extends RawMinkContext implements KernelAwareInterface
37 | {
38 | /**
39 | *
40 | * Kernel.
41 | *
42 | * @var KernelInterface
43 | */
44 | private $kernel;
45 |
46 | /**
47 | *
48 | * Parameters.
49 | *
50 | * @var array
51 | */
52 | private $parameters;
53 |
54 | /**
55 | *
56 | * Initializes context.
57 | * Every scenario gets it's own context object.
58 | *
59 | * @param array $parameters context parameters (set them up through behat.yml)
60 | */
61 | public function __construct(array $parameters)
62 | {
63 | // Initialize your context here
64 | $this->parameters = $parameters;
65 |
66 | // Web user context.
67 | $this->useContext('web-user', new WebUser());
68 | }
69 |
70 | /**
71 | *
72 | * {@inheritdoc}
73 | */
74 | public function setKernel(KernelInterface $kernel)
75 | {
76 | $this->kernel = $kernel;
77 | }
78 |
79 | /**
80 | *
81 | * @BeforeScenario
82 | */
83 | public function purgeDatabase()
84 | {
85 | $entityManager = $this->kernel->getContainer()->get('doctrine.orm.entity_manager');
86 |
87 | $purger = new ORMPurger($entityManager);
88 | $purger->purge();
89 | }
90 |
91 | /**
92 | *
93 | * @Given /^I am logged in as "([^"]*)"$/
94 | */
95 | public function iAmLoggedInAs($user)
96 | {
97 | $session = $this->getMainContext()->getSession();
98 | $session->setBasicAuth($user . '@foo.com', 'root');
99 | }
100 |
101 | /**
102 | * @Given /^I logout$/
103 | */
104 | public function iLogout()
105 | {
106 | $this->kernel->getContainer()->get('security.context')->getToken()->eraseCredentials();
107 | }
108 |
109 | /**
110 | * @Given /^I should be logged in$/
111 | */
112 | public function iShouldBeLoggedIn()
113 | {
114 | WebTestCase::assertTrue($this->kernel->getContainer()->get('security.context')->getToken()->getUser() instanceof \Symfony\Component\Security\Core\User\UserInterface);
115 | }
116 |
117 | /**
118 | * @Given /^I should not be logged in$/
119 | */
120 | public function iShouldNotBeLoggedIn()
121 | {
122 | WebTestCase::assertFalse($this->kernel->getContainer()->get('security.context')->getToken()->getUser() instanceof \Symfony\Component\Security\Core\User\UserInterface);
123 | }
124 |
125 | /**
126 | * @Given /^I circumvent login with "([^"]*)" and "([^"]*)"$/
127 | */
128 | public function iCircumventLoginWithAnd($username, $password)
129 | {
130 | $this->getMainContext()->getSession()->visit('/circumvent_login');
131 | $this->getMainContext()->getSession()->getPage()->fillField('_username', $username);
132 | $this->getMainContext()->getSession()->getPage()->fillField('_password', $password);
133 | $this->getMainContext()->getSession()->getPage()->pressButton('Login');
134 | }
135 |
136 | /**
137 | * @Given /^I should be blocked$/
138 | */
139 | public function iShouldBeBlocked()
140 | {
141 | WebTestCase::assertSame(500, $this->getMainContext()->getSession()->getStatusCode());
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/features/bootstrap/WebUser.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * Available on github
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace CCDNUser\SecurityBundle\features\bootstrap;
15 |
16 | use Behat\MinkExtension\Context\MinkContext;
17 | use Behat\Symfony2Extension\Context\KernelAwareInterface;
18 | use Symfony\Component\HttpKernel\KernelInterface;
19 | use CCDNUser\SecurityBundle\features\bootstrap\DataContext;
20 |
21 | /**
22 | *
23 | * Web user context.
24 | *
25 | * @category CCDNUser
26 | * @package SecurityBundle
27 | *
28 | * @author Reece Fowell
29 | * @license http://opensource.org/licenses/MIT MIT
30 | * @version Release: 2.0
31 | * @link https://github.com/codeconsortium/CCDNUserSecurityBundle
32 | *
33 | */
34 | class WebUser extends MinkContext implements KernelAwareInterface
35 | {
36 | /**
37 | *
38 | * Kernel.
39 | *
40 | * @var KernelInterface
41 | */
42 | protected $kernel;
43 |
44 | /**
45 | *
46 | * Constructor.
47 | */
48 | public function __construct()
49 | {
50 | // Bundle data creation context.
51 | $this->useContext('data', new DataContext());
52 | }
53 |
54 | /**
55 | *
56 | * {@inheritdoc}
57 | */
58 | public function setKernel(KernelInterface $kernel)
59 | {
60 | $this->kernel = $kernel;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/features/user_login.feature:
--------------------------------------------------------------------------------
1 | Feature: Check Blocking Functionalities
2 | In order to determine forced account recovery and page blocking as an User.
3 |
4 | Background:
5 | And there are following users defined:
6 | | name | email | password | enabled | role |
7 | | user1 | user1@foo.com | root | 1 | ROLE_USER |
8 | | user2 | user2@foo.com | root | 1 | ROLE_USER |
9 | | user3 | user3@foo.com | root | 1 | ROLE_USER |
10 |
11 | Scenario: I login successfully
12 | Given I am on "/login"
13 | And I fill in "username" with "user1@foo.com"
14 | And I fill in "password" with "root"
15 | And I press "_submit"
16 | And I should be logged in
17 | And I logout
18 |
19 | Scenario: I fail to login and am forced to recover my account
20 | Given I am on "/login"
21 | And I fill in "username" with "user1@foo.com"
22 | And I fill in "password" with "wrongpass"
23 | And I press "_submit"
24 | And I should not be logged in
25 | And I fill in "username" with "user1@foo.com"
26 | And I fill in "password" with "wrongpass"
27 | And I press "_submit"
28 | And I should not be logged in
29 | And I should be on "/resetting/request"
30 |
31 | Scenario: I fail to login too many times and am blocked from the account pages
32 | Given I am on "/login"
33 | And I circumvent login with "user1@foo.com" and "wrongpass"
34 | And I should not be logged in
35 | And I circumvent login with "user1@foo.com" and "wrongpass"
36 | And I should not be logged in
37 | And I circumvent login with "user1@foo.com" and "wrongpass"
38 | And I should not be logged in
39 | And I circumvent login with "user1@foo.com" and "wrongpass"
40 | Then I should be blocked
41 | And I go to "/login"
42 | Then I should be blocked
43 | And I circumvent login with "user1@foo.com" and "root"
44 | Then I should be blocked
45 | And I go to "/"
46 | Then I should not be logged in
47 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
17 |
18 | ./Tests/Repository
19 | ./Tests/Manager
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | ./Tests
30 |
31 | ./Resources
32 | ./vendor
33 |
34 |
35 |
36 | cache
37 | config
38 | data
39 | log
40 | vendor
41 | lib/vendor
42 | plugins
43 | web
44 | Resources
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/script_behat.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | rm -rRf ./Tests/Functional/app/cache/*
4 | rm -rRf ./Tests/Functional/app/logs/*
5 |
6 | rm -f ./Tests/Functional/app/config/parameters.yml
7 | echo 'parameters:
8 | database_driver: pdo_mysql
9 | database_host: 127.0.0.1
10 | database_port: null
11 | database_name: ccdn_test
12 | database_user: ccdnroot
13 | database_password: root
14 | locale: en
15 |
16 | ' > ./Tests/Functional/app/config/parameters.yml
17 |
18 | composer install --dev --prefer-dist
19 |
20 | php ./Tests/Functional/app/console --env=test doctrine:database:drop --force
21 | php ./Tests/Functional/app/console --env=test doctrine:database:create
22 | php ./Tests/Functional/app/console --env=test doctrine:schema:create
23 | php ./Tests/Functional/app/console --env=test doctrine:schema:update --force
24 |
25 | ./vendor/behat/behat/bin/behat "@CCDNUserSecurityBundle" --config ./behat.yml
26 |
--------------------------------------------------------------------------------
/script_phpunit.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | rm -rRf ./Tests/Functional/app/cache/*
4 | rm -rRf ./Tests/Functional/app/logs/*
5 |
6 | rm -f ./Tests/Functional/app/config/parameters.yml
7 | echo 'parameters:
8 | database_driver: pdo_mysql
9 | database_host: 127.0.0.1
10 | database_port: null
11 | database_name: ccdn_test
12 | database_user: ccdnroot
13 | database_password: root
14 | locale: en
15 |
16 | ' > ./Tests/Functional/app/config/parameters.yml
17 |
18 | composer install --dev
19 |
20 | php ./Tests/Functional/app/console --env=test doctrine:database:drop --force
21 | php ./Tests/Functional/app/console --env=test doctrine:database:create
22 | php ./Tests/Functional/app/console --env=test doctrine:schema:create
23 | php ./Tests/Functional/app/console --env=test doctrine:schema:update --force
24 |
25 | ./vendor/phpunit/phpunit/phpunit.php -c ./ --testdox
26 |
--------------------------------------------------------------------------------