├── public
└── .gitkeep
├── src
├── lang
│ ├── .gitkeep
│ ├── en
│ │ └── confide.php
│ └── pt
│ │ └── confide.php
├── views
│ ├── .gitkeep
│ ├── emails
│ │ ├── passwordreset.blade.php
│ │ └── confirm.blade.php
│ ├── forgot_password.blade.php
│ ├── reset_password.blade.php
│ ├── generators
│ │ ├── routes.blade.php
│ │ ├── migration.blade.php
│ │ └── controller.blade.php
│ ├── login.blade.php
│ └── signup.blade.php
├── config
│ ├── .gitkeep
│ └── config.php
├── migrations
│ ├── .gitkeep
│ └── 2013_01_13_172956_confide_setup_users_table.php
├── Zizaco
│ └── Confide
│ │ ├── ConfideFacade.php
│ │ ├── ObjectProvider.php
│ │ ├── ConfideServiceProvider.php
│ │ ├── Confide.php
│ │ └── ConfideUser.php
└── commands
│ ├── MigrationCommand.php
│ ├── ControllerCommand.php
│ └── RoutesCommand.php
├── tests
├── .gitkeep
├── ConfideUserTest.php
└── ConfideTest.php
├── .gitignore
├── .travis.yml
├── phpunit.xml
├── composer.json
└── README.md
/public/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/lang/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/config/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/migrations/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.lock
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.3
5 | - 5.4
6 |
7 | before_script:
8 | - curl -s http://getcomposer.org/installer | php
9 | - php composer.phar install --dev
10 |
11 | script: phpunit
12 |
--------------------------------------------------------------------------------
/src/Zizaco/Confide/ConfideFacade.php:
--------------------------------------------------------------------------------
1 | {{ Lang::get('confide::confide.email.password_reset.subject') }}
2 |
3 |
{{ Lang::get('confide::confide.email.password_reset.greetings', array( 'name' => $user->username)) }},
4 |
5 | {{ Lang::get('confide::confide.email.password_reset.body') }}
6 |
7 | {{{ URL::to("user/reset_password/".$token) }}}
8 |
9 |
10 | {{ Lang::get('confide::confide.email.password_reset.farewell') }}
11 |
--------------------------------------------------------------------------------
/src/views/emails/confirm.blade.php:
--------------------------------------------------------------------------------
1 | {{ Lang::get('confide::confide.email.account_confirmation.subject') }}
2 |
3 | {{ Lang::get('confide::confide.email.account_confirmation.greetings', array( 'name' => $user->username)) }},
4 |
5 | {{ Lang::get('confide::confide.email.account_confirmation.body') }}
6 |
7 | {{{ URL::to("user/confirm/{$user->confirmation_code}") }}}
8 |
9 |
10 | {{ Lang::get('confide::confide.email.account_confirmation.farewell') }}
11 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | ./tests/
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/migrations/2013_01_13_172956_confide_setup_users_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->string('username');
19 | $table->string('email');
20 | $table->string('password');
21 | $table->string('confirmation_code');
22 | $table->boolean('confirmed')->default(false);
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::drop('users');
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/views/forgot_password.blade.php:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zizaco/confide",
3 | "description": "Confide is an authentication solution for Laravel 4",
4 | "keywords": ["laravel","illuminate","auth"],
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Zizaco Zizuini",
9 | "email": "zizaco@gmail.com"
10 | }
11 | ],
12 | "require": {
13 | "php": ">=5.3.0",
14 | "illuminate/support": "4.0.x",
15 | "laravelbook/ardent": "*"
16 | },
17 | "require-dev": {
18 | "mockery/mockery": "0.7.2",
19 | "illuminate/database": "4.0.x",
20 | "illuminate/auth": "4.0.x"
21 | },
22 | "suggest": {
23 | "zizaco/entrust":"add Role-based Permissions to Laravel 4"
24 | },
25 | "autoload": {
26 | "classmap": [
27 | "src/migrations",
28 | "src/commands"
29 | ],
30 | "psr-0": {
31 | "Zizaco\\Confide": "src/"
32 | }
33 | },
34 | "minimum-stability": "dev"
35 | }
36 |
--------------------------------------------------------------------------------
/src/views/reset_password.blade.php:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/src/views/generators/routes.blade.php:
--------------------------------------------------------------------------------
1 | {{{ "\n\n" }}}
2 | @if (! $restful)
3 |
4 | // Confide routes
5 | Route::get( '{{ lcfirst(substr($name,0,-10)) }}/create', '{{ $name }}@create');
6 | Route::post('{{ lcfirst(substr($name,0,-10)) }}', '{{ $name }}@store');
7 | Route::get( '{{ lcfirst(substr($name,0,-10)) }}/login', '{{ $name }}@login');
8 | Route::post('{{ lcfirst(substr($name,0,-10)) }}/login', '{{ $name }}@do_login');
9 | Route::get( '{{ lcfirst(substr($name,0,-10)) }}/confirm/{code}', '{{ $name }}@confirm');
10 | Route::get( '{{ lcfirst(substr($name,0,-10)) }}/forgot_password', '{{ $name }}@forgot_password');
11 | Route::post('{{ lcfirst(substr($name,0,-10)) }}/forgot_password', '{{ $name }}@do_forgot_password');
12 | Route::get( '{{ lcfirst(substr($name,0,-10)) }}/reset_password/{token}', '{{ $name }}@reset_password');
13 | Route::post('{{ lcfirst(substr($name,0,-10)) }}/reset_password', '{{ $name }}@do_reset_password');
14 | Route::get( '{{ lcfirst(substr($name,0,-10)) }}/logout', '{{ $name }}@logout');
15 | @else
16 |
17 | // Confide RESTful route
18 | Route::controller( 'user', '{{ $name }}');
19 | @endif
20 |
--------------------------------------------------------------------------------
/src/views/generators/migration.blade.php:
--------------------------------------------------------------------------------
1 | {{{ 'increments('id');
18 | $table->string('username');
19 | $table->string('email');
20 | $table->string('password');
21 | $table->string('confirmation_code');
22 | $table->boolean('confirmed')->default(false);
23 | $table->timestamps();
24 | });
25 |
26 | // Creates password reminders table
27 | Schema::create('password_reminders', function($t)
28 | {
29 | $t->string('email');
30 | $t->string('token');
31 | $t->timestamp('created_at');
32 | });
33 | }
34 |
35 | /**
36 | * Reverse the migrations.
37 | *
38 | * @return void
39 | */
40 | public function down()
41 | {
42 | Schema::drop('password_reminders');
43 | Schema::drop('{{ $table }}');
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/views/login.blade.php:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/src/Zizaco/Confide/ConfideServiceProvider.php:
--------------------------------------------------------------------------------
1 | package('zizaco/confide');
24 | }
25 |
26 | /**
27 | * Register the service provider.
28 | *
29 | * @return void
30 | */
31 | public function register()
32 | {
33 | $this->registerConfide();
34 |
35 | $this->registerCommands();
36 | }
37 |
38 | /**
39 | * Register the application bindings.
40 | *
41 | * @return void
42 | */
43 | private function registerConfide()
44 | {
45 | $this->app->bind('confide', function($app)
46 | {
47 | return new Confide($app);
48 | });
49 | }
50 |
51 | /**
52 | * Register the artisan commands.
53 | *
54 | * @return void
55 | */
56 | private function registerCommands()
57 | {
58 | $this->app['command.confide.controller'] = $this->app->share(function($app)
59 | {
60 | return new ControllerCommand($app);
61 | });
62 |
63 | $this->app['command.confide.routes'] = $this->app->share(function($app)
64 | {
65 | return new RoutesCommand($app);
66 | });
67 |
68 | $this->app['command.confide.migration'] = $this->app->share(function($app)
69 | {
70 | return new MigrationCommand($app);
71 | });
72 |
73 | $this->commands(
74 | 'command.confide.controller',
75 | 'command.confide.routes',
76 | 'command.confide.migration'
77 | );
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/views/signup.blade.php:
--------------------------------------------------------------------------------
1 |
34 |
--------------------------------------------------------------------------------
/src/config/config.php:
--------------------------------------------------------------------------------
1 | 9,
16 |
17 | /*
18 | |--------------------------------------------------------------------------
19 | | Form Views
20 | |--------------------------------------------------------------------------
21 | |
22 | | The VIEWS used to render forms with Confide methods:
23 | | makeLoginForm, makeSignupForm, makeForgotPasswordForm
24 | | and makeResetPasswordForm.
25 | |
26 | | By default, the out of the box confide views are used
27 | | but you can create your own forms and replace the view
28 | | names here. For example
29 | |
30 | | // To use app/views/user/signup.blade.php:
31 | |
32 | | 'signup_form' => 'user.signup'
33 | |
34 | |
35 | */
36 | 'login_form' => 'confide::login',
37 | 'signup_form' => 'confide::signup',
38 | 'forgot_password_form' => 'confide::forgot_password',
39 | 'reset_password_form' => 'confide::reset_password', //*
40 |
41 | // * reset_password_form must use $token variable in hidden input field
42 |
43 | /*
44 | |--------------------------------------------------------------------------
45 | | Email Views
46 | |--------------------------------------------------------------------------
47 | |
48 | | The VIEWS used to email messages for some Confide events:
49 | |
50 | | By default, the out of the box confide views are used
51 | | but you can create your own forms and replace the view
52 | | names here. For example
53 | |
54 | | // To use app/views/email/confirmation.blade.php:
55 | |
56 | | 'email_account_confirmation' => 'email.confirmation'
57 | |
58 | |
59 | */
60 |
61 | 'email_reset_password' => 'confide::emails.passwordreset', // with $user and $token.
62 | 'email_account_confirmation' => 'confide::emails.confirm', // with $user
63 |
64 | );
65 |
--------------------------------------------------------------------------------
/src/lang/en/confide.php:
--------------------------------------------------------------------------------
1 | 'Username',
6 | 'password' => 'Password',
7 | 'password_confirmation' => 'Confirm Password',
8 | 'e_mail' => 'Email',
9 | 'username_e_mail' => 'Username or Email',
10 |
11 | 'signup' => array(
12 | 'title' => 'Signup',
13 | 'desc' => 'Signup for new account',
14 | 'confirmation_required' => 'Confirmation required',
15 | 'submit' => 'Create new account',
16 | ),
17 |
18 | 'login' => array(
19 | 'title' => 'Login',
20 | 'desc' => 'Enter your credentials',
21 | 'forgot_password' => '(forgot password)',
22 | 'remember' => 'Remember me',
23 | 'submit' => 'Login',
24 | ),
25 |
26 | 'forgot' => array(
27 | 'title' => 'Forgot password',
28 | 'submit' => 'Continue',
29 | ),
30 |
31 | 'alerts' => array(
32 | 'account_created' => 'Your account has been successfully created. Please check your email for the instructions on how to confirm your account.',
33 | 'too_many_attempts' => 'Too many attempts. Try again in few minutes.',
34 | 'wrong_credentials' => 'Incorrect username, email or password.',
35 | 'not confirmed' => 'Your account may not be confirmed. Check your email for the confirmation link',
36 | 'confirmation' => 'Your account has been confirmed! You may now login.',
37 | 'wrong_confirmation' => 'Wrong confirmation code.',
38 | 'password_forgot' => 'The information regarding password reset was sent to your email.',
39 | 'wrong_password_forgot' => 'User not found.',
40 | 'password_reset' => 'Your password has been changed successfully.',
41 | 'wrong_password_reset' => 'Invalid password. Try again',
42 | ),
43 |
44 | 'email' => array(
45 | 'account_confirmation' => array(
46 | 'subject' => 'Account Confirmation',
47 | 'greetings' => 'Hello :name',
48 | 'body' => 'Please access the link bellow to confirm your account.',
49 | 'farewell' => 'Regards',
50 | ),
51 |
52 | 'password_reset' => array(
53 | 'subject' => 'Password Reset',
54 | 'greetings' => 'Hello :name',
55 | 'body' => 'Access the following link to change your password',
56 | 'farewell' => 'Regards',
57 | ),
58 | ),
59 |
60 | );
61 |
--------------------------------------------------------------------------------
/src/lang/pt/confide.php:
--------------------------------------------------------------------------------
1 | 'Nome de Usuário',
6 | 'password' => 'Senha',
7 | 'password_confirmation' => 'Confirmar senha',
8 | 'e_mail' => 'Email',
9 | 'username_e_mail' => 'Email ou Usuário',
10 |
11 | 'signup' => array(
12 | 'title' => 'Cadastrar',
13 | 'desc' => 'Cadastrar nova conta',
14 | 'confirmation_required' => 'Confirmação necessária',
15 | 'submit' => 'Criar nova conta',
16 | ),
17 |
18 | 'login' => array(
19 | 'title' => 'Entrar',
20 | 'desc' => 'Entre suas credenciais',
21 | 'forgot_password' => '(esqueci minha senha)',
22 | 'remember' => 'Continuar conectado',
23 | 'submit' => 'Entrar',
24 | ),
25 |
26 | 'forgot' => array(
27 | 'title' => 'Esqueci minha senha',
28 | 'submit' => 'Continuar',
29 | ),
30 |
31 | 'alerts' => array(
32 | 'account_created' => 'Sua conta foi criada com sucesso! Por favor verifique em seu e-mail as instruções para confirmar a sua conta.',
33 | 'wrong_credentials' => 'Nome de usuário ou senha incorretos.',
34 | 'too_many_attempts' => 'Muitas tentativas incorretas. Tente novamente mais tarde.',
35 | 'not confirmed' => 'Sua conta pode não estar confirmada. Verifique seu email e procure pelo link de confirmação',
36 | 'confirmation' => 'Sua conta foi confirmada! Você pode entrar agora.',
37 | 'wrong_confirmation' => 'Código de confirmação incorreto.',
38 | 'password_forgot' => 'As informações para a troca de senha foram enviadas ao seu e-mail.',
39 | 'wrong_password_forgot' => 'Usuário não encontrado.',
40 | 'password_reset' => 'Sua senha foi alterada com sucesso.',
41 | 'wrong_password_reset' => 'Senha inválida. Tente novamente.',
42 | ),
43 |
44 | 'email' => array(
45 | 'account_confirmation' => array(
46 | 'subject' => 'Confirmação de conta',
47 | 'greetings' => 'Olá :name',
48 | 'body' => 'Por favor, acesse o link abaixo para confirmar a sua conta',
49 | 'farewell' => 'Att',
50 | ),
51 |
52 | 'password_reset' => array(
53 | 'subject' => 'Troca de senha',
54 | 'greetings' => 'Olá :name',
55 | 'body' => 'Acesse o link a seguir para trocar a sua senha',
56 | 'farewell' => 'Att',
57 | ),
58 | ),
59 |
60 | );
61 |
--------------------------------------------------------------------------------
/src/commands/MigrationCommand.php:
--------------------------------------------------------------------------------
1 | addNamespace('confide',substr(__DIR__,0,-8).'views');
33 | }
34 |
35 | /**
36 | * Execute the console command.
37 | *
38 | * @return void
39 | */
40 | public function fire()
41 | {
42 | $table = lcfirst($this->option('table'));
43 |
44 | $this->line('');
45 | $this->info( "Table name: $table" );
46 | $message = "An migration that creates the $table table will".
47 | " be created in app/database/migrations directory";
48 |
49 | $this->comment( $message );
50 | $this->line('');
51 |
52 | if ( $this->confirm("Proceed with the migration creation? [Yes|no]") )
53 | {
54 | $this->line('');
55 |
56 | $this->info( "Creating migration..." );
57 | if( $this->createMigration( $table ) )
58 | {
59 | $this->info( "Migration successfully created!" );
60 | }
61 | else{
62 | $this->error(
63 | "Coudn't create migration.\n Check the write permissions".
64 | " within the app/database/migrations directory."
65 | );
66 | }
67 |
68 | $this->line('');
69 |
70 | }
71 | }
72 |
73 | /**
74 | * Get the console command options.
75 | *
76 | * @return array
77 | */
78 | protected function getOptions()
79 | {
80 | $app = app();
81 |
82 | return array(
83 | array('table', null, InputOption::VALUE_OPTIONAL, 'Table name.', $app['config']->get('auth.table')),
84 | );
85 | }
86 |
87 | /**
88 | * Create the migration
89 | *
90 | * @param string $name
91 | * @return bool
92 | */
93 | protected function createMigration( $table = 'users' )
94 | {
95 | $app = app();
96 | $migration_file = $this->laravel->path."/database/migrations/".date('Y_m_d_His')."_confide_setup_users_table.php";
97 | $output = $app['view']->make('confide::generators.migration')->with('table', $table)->render();
98 |
99 | if( ! file_exists( $migration_file ) )
100 | {
101 | $fs = fopen($migration_file, 'x');
102 | if ( $fs )
103 | {
104 | fwrite($fs, $output);
105 | fclose($fs);
106 | return true;
107 | }
108 | else
109 | {
110 | return false;
111 | }
112 | }
113 | else
114 | {
115 | return false;
116 | }
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/src/commands/ControllerCommand.php:
--------------------------------------------------------------------------------
1 | addNamespace('confide',substr(__DIR__,0,-8).'views');
33 | }
34 |
35 | /**
36 | * Execute the console command.
37 | *
38 | * @return void
39 | */
40 | public function fire()
41 | {
42 | $name = $this->prepareName($this->option('name'));
43 | $restful = $this->option('restful');
44 |
45 | $this->line('');
46 | $this->info( "Controller name: $name".(($restful) ? "\nRESTful: Yes" : '') );
47 | $message = "An authentication ".(($restful) ? 'RESTful ' : '')."controller template with the name $name.php".
48 | " will be created in app/controllers directory and will NOT overwrite any ".
49 | " file.";
50 |
51 | $this->comment( $message );
52 | $this->line('');
53 |
54 | if ( $this->confirm("Proceed with the controller creation? [Yes|no]") )
55 | {
56 | $this->line('');
57 |
58 | $this->info( "Creating $name..." );
59 | if( $this->createController( $name, $restful ) )
60 | {
61 | $this->info( "$name.php Successfully created!" );
62 | }
63 | else{
64 | $this->error(
65 | "Coudn't create app/controllers/$name.php.\nCheck the".
66 | " write permissions within the controllers directory".
67 | " or if $name.php already exists. (This command will".
68 | " not overwrite any file. delete the existing $name.php".
69 | " if you wish to continue)."
70 | );
71 | }
72 |
73 | $this->line('');
74 |
75 | }
76 | }
77 |
78 | /**
79 | * Get the console command options.
80 | *
81 | * @return array
82 | */
83 | protected function getOptions()
84 | {
85 | $app = app();
86 |
87 | return array(
88 | array('name', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', $app['config']->get('auth.model')),
89 | array('--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'),
90 | );
91 | }
92 |
93 | /**
94 | * Prepare the controller name
95 | *
96 | * @param string $name
97 | * @return string
98 | */
99 | protected function prepareName($name = '')
100 | {
101 | $name = ( $name != '') ? ucfirst($name) : 'User';
102 |
103 | if( substr($name,-10) == 'controller' )
104 | {
105 | $name = substr($name, 0, -10).'Controller';
106 | }
107 | else
108 | {
109 | $name .= 'Controller';
110 | }
111 |
112 | return $name;
113 | }
114 |
115 | /**
116 | * Create the controller
117 | *
118 | * @param string $name
119 | * @return bool
120 | */
121 | protected function createController( $name = '', $restful = false )
122 | {
123 | $app = app();
124 |
125 | $controller_file = $this->laravel->path."/controllers/$name.php";
126 | $output = $app['view']->make('confide::generators.controller')
127 | ->with('name', $name)
128 | ->with('restful', $restful)
129 | ->render();
130 |
131 | if( ! file_exists( $controller_file ) )
132 | {
133 | $fs = fopen($controller_file, 'x');
134 | if ( $fs )
135 | {
136 | fwrite($fs, $output);
137 | fclose($fs);
138 | return true;
139 | }
140 | else
141 | {
142 | return false;
143 | }
144 | }
145 | else
146 | {
147 | return false;
148 | }
149 | }
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/src/commands/RoutesCommand.php:
--------------------------------------------------------------------------------
1 | addNamespace('confide',substr(__DIR__,0,-8).'views');
33 | }
34 |
35 | /**
36 | * Execute the console command.
37 | *
38 | * @return void
39 | */
40 | public function fire()
41 | {
42 | $name = $this->prepareName($this->option('controller'));
43 | $restful = $this->option('restful');
44 |
45 | $this->line('');
46 | $this->info( "Routes file: app/routes.php" );
47 |
48 | if(! $restful)
49 | {
50 | $message = "The default Confide routes (to use with the Controller template)".
51 | " will be appended to your routes.php file.";
52 | }
53 | else
54 | {
55 | $message = "A single route to handle every action in a RESTful controller".
56 | " will be appended to your routes.php file. This may be used with a confide".
57 | " controller generated using [-r|--restful] option.";
58 | }
59 |
60 |
61 | $this->comment( $message );
62 | $this->line('');
63 |
64 | if ( $this->confirm("Proceed with the append? [Yes|no]") )
65 | {
66 | $this->line('');
67 |
68 | $this->info( "Appending routes..." );
69 | if( $this->appendRoutes( $name, $restful ) )
70 | {
71 | $this->info( "app/routes.php Patched successfully!" );
72 | }
73 | else{
74 | $this->error(
75 | "Coudn't append content to app/routes.php\nCheck the".
76 | " write permissions within the file."
77 | );
78 | }
79 |
80 | $this->line('');
81 |
82 | }
83 | }
84 |
85 | /**
86 | * Get the console command options.
87 | *
88 | * @return array
89 | */
90 | protected function getOptions()
91 | {
92 | $app = app();
93 |
94 | return array(
95 | array('controller', null, InputOption::VALUE_OPTIONAL, 'Name of the controller.', $app['config']->get('auth.model')),
96 | array('--restful', '-r', InputOption::VALUE_NONE, 'Generate RESTful controller.'),
97 | );
98 | }
99 |
100 | /**
101 | * Prepare the controller name
102 | *
103 | * @param string $name
104 | * @return string
105 | */
106 | protected function prepareName( $name = '' )
107 | {
108 | $name = ( $name != '') ? ucfirst($name) : 'User';
109 |
110 | if( substr($name,-10) == 'controller' )
111 | {
112 | $name = substr($name, 0, -10).'Controller';
113 | }
114 | else
115 | {
116 | $name .= 'Controller';
117 | }
118 |
119 | return $name;
120 | }
121 |
122 | /**
123 | * Create the controller
124 | *
125 | * @param string $name
126 | * @return bool
127 | */
128 | protected function appendRoutes( $name = '', $restful = false )
129 | {
130 | $app = app();
131 | $routes_file = $this->laravel->path.'/routes.php';
132 | $confide_routes = $app['view']->make('confide::generators.routes')
133 | ->with('name', $name)
134 | ->with('restful', $restful)
135 | ->render();
136 |
137 | if( file_exists( $routes_file ) )
138 | {
139 | $fs = fopen($routes_file, 'a');
140 | if ( $fs )
141 | {
142 | fwrite($fs, $confide_routes);
143 | $this->line($confide_routes);
144 | fclose($fs);
145 | return true;
146 | }
147 | else
148 | {
149 | return false;
150 | }
151 | }
152 | else
153 | {
154 | return false;
155 | }
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/tests/ConfideUserTest.php:
--------------------------------------------------------------------------------
1 | mockApp();
35 |
36 | $this->confide_user = new ConfideUser;
37 | }
38 |
39 | private function populateUser()
40 | {
41 | $this->confide_user->username = 'uname';
42 | $this->confide_user->password = '123123';
43 | $this->confide_user->email = 'mail@sample.com';
44 | $this->confide_user->confirmation_code = '456456';
45 | $this->confide_user->confirmed = true;
46 | }
47 |
48 | public function testShouldGetAuthPassword()
49 | {
50 | $this->populateUser();
51 |
52 | $this->assertEquals( $this->confide_user->password, $this->confide_user->getAuthPassword() );
53 | }
54 |
55 | public function testShouldConfirm()
56 | {
57 | $this->populateUser();
58 |
59 | $this->assertNotEquals( 0, $this->confide_user->confirm() );
60 |
61 | $this->assertEquals( 1, $this->confide_user->confirmed );
62 | }
63 |
64 | public function testShouldSendForgotPassword()
65 | {
66 | // Should send an email once
67 | ConfideUser::$app['mailer'] = m::mock( 'Mail' );
68 | ConfideUser::$app['mailer']->shouldReceive('send')
69 | ->andReturn( null )
70 | ->atLeast(1);
71 |
72 | $this->populateUser();
73 |
74 | $old_password = $this->confide_user->password;
75 |
76 | $this->assertTrue( $this->confide_user->forgotPassword() );
77 | }
78 |
79 | public function testShouldChangePassword()
80 | {
81 | $credentials = array( 'email'=>'mail@sample.com', 'password'=>'987987' );
82 |
83 | $this->populateUser();
84 |
85 | $old_password = $this->confide_user->password;
86 |
87 | $this->assertTrue( $this->confide_user->resetPassword( $credentials ) );
88 |
89 | $new_password = $this->confide_user->password;
90 |
91 | // Should have generated a new password code
92 | $this->assertNotEquals( $old_password, $new_password );
93 | }
94 |
95 | public function testShouldGenerateConfirmationCodeOnSave()
96 | {
97 | // Should send an email once
98 | ConfideUser::$app['mailer'] = m::mock( 'Mail' );
99 | ConfideUser::$app['mailer']->shouldReceive('send')
100 | ->andReturn( null )
101 | ->once();
102 |
103 | $this->populateUser();
104 | $this->confide_user->confirmation_code = '';
105 | $this->confide_user->confirmed = false;
106 |
107 | $old_cc = $this->confide_user->confirmation_code;
108 |
109 | $this->assertTrue( $this->confide_user->save() );
110 |
111 | $new_cc = $this->confide_user->confirmation_code;
112 |
113 | // Should have generated a new confirmation code
114 | $this->assertNotEquals( $old_cc, $new_cc );
115 | }
116 |
117 | public function testShouldNotGenerateConfirmationCodeIfExists()
118 | {
119 | $this->populateUser();
120 |
121 | // Considering the model was already saved
122 | $this->confide_user->id = 1;
123 |
124 | $old_cc = $this->confide_user->confirmation_code;
125 |
126 | $this->assertTrue( $this->confide_user->save() );
127 |
128 | $new_cc = $this->confide_user->confirmation_code;
129 |
130 | // Should not change confirmation code
131 | $this->assertEquals( $old_cc, $new_cc );
132 | }
133 |
134 | private function mockApp()
135 | {
136 | // Mocks the application components
137 | $app = array();
138 |
139 | $app['config'] = m::mock( 'Config' );
140 | $app['config']->shouldReceive( 'get' )
141 | ->with( 'auth.table' )
142 | ->andReturn( 'users' );
143 |
144 | $app['config']->shouldReceive( 'getEnvironment' )
145 | ->andReturn( 'production' );
146 |
147 | $app['config']->shouldReceive( 'get' )
148 | ->with( 'app.key' )
149 | ->andReturn( '123' );
150 |
151 | $app['config']->shouldReceive( 'get' )
152 | ->with( 'confide::throttle_limit' )
153 | ->andReturn( 9 );
154 |
155 | $app['config']->shouldReceive( 'get' )
156 | ->andReturn( 'confide::login' );
157 |
158 | $app['mailer'] = m::mock( 'Mail' );
159 | $app['mailer']->shouldReceive('send')
160 | ->andReturn( null );
161 |
162 | $app['hash'] = m::mock( 'Hash' );
163 | $app['hash']->shouldReceive('make')
164 | ->andReturn( 'aRandomHash' );
165 |
166 | $app['db'] = m::mock( 'DatabaseManager' );
167 | $app['db']->shouldReceive('connection')
168 | ->andReturn( $app['db'] );
169 |
170 | $app['db']->shouldReceive('table')
171 | ->andReturn( $app['db'] );
172 |
173 | $app['db']->shouldReceive('insert')
174 | ->andReturn( $app['db'] );
175 |
176 | $app['db']->shouldReceive('where')
177 | ->andReturn( $app['db'] );
178 |
179 | $app['db']->shouldReceive('update')
180 | ->andReturn( true );
181 |
182 | return $app;
183 | }
184 |
185 | }
186 |
--------------------------------------------------------------------------------
/src/Zizaco/Confide/Confide.php:
--------------------------------------------------------------------------------
1 | app = app();
31 | $this->objectRepository = new ObjectProvider;
32 | }
33 |
34 | /**
35 | * Returns the Laravel application
36 | *
37 | * @return Illuminate\Foundation\Application
38 | */
39 | public function app()
40 | {
41 | return $this->app;
42 | }
43 |
44 | /**
45 | * Returns the model set in auth config
46 | *
47 | * @return string
48 | */
49 | public function model()
50 | {
51 | $model = $this->app['config']->get('auth.model');
52 |
53 | return $this->objectRepository->getObject( $model );
54 |
55 | }
56 |
57 | /**
58 | * Get the currently authenticated user or null.
59 | *
60 | * @return Zizaco\Confide\ConfideUser|null
61 | */
62 | public function user()
63 | {
64 | return $this->app['auth']->user();
65 | }
66 |
67 | /**
68 | * Set the user confirmation to true.
69 | *
70 | * @param string $code
71 | * @return bool
72 | */
73 | public function confirm( $code )
74 | {
75 | $user = Confide::model()->where('confirmation_code', '=', $code)->get()->first();
76 | if( $user )
77 | {
78 | return $user->confirm();
79 | }
80 | else
81 | {
82 | return false;
83 | }
84 | }
85 |
86 | /**
87 | * Attempt to log a user into the application with
88 | * password and username or email.
89 | *
90 | * @param array $arguments
91 | * @param bool $confirmed_only
92 | * @return void
93 | */
94 | public function logAttempt( $credentials, $confirmed_only = false )
95 | {
96 |
97 | if(! $this->reachedThrottleLimit( $credentials ) )
98 | {
99 | $user = $this->model()
100 | ->where('email','=',$credentials['email'])
101 | ->orWhere('username','=',$credentials['email'])
102 | ->first();
103 |
104 | if( ! is_null($user) and ($user->confirmed or !$confirmed_only ) and $this->app['hash']->check($credentials['password'], $user->password) )
105 | {
106 | $remember = isset($credentials['remember']) ? $credentials['remember'] : false;
107 |
108 | $this->app['auth']->login( $user, $remember );
109 | return true;
110 | }
111 | }
112 |
113 | $this->throttleCount( $credentials );
114 |
115 | return false;
116 | }
117 |
118 | /**
119 | * Checks if the credentials has been throttled by too
120 | * much failed login attempts
121 | *
122 | * @param array $credentials
123 | * @return mixed Value.
124 | */
125 | public function isThrottled( $credentials )
126 | {
127 | // Check how many failed tries have been done
128 | $attempt_key = $this->attemptCacheKey( $credentials );
129 | $attempts = $this->app['cache']->get($attempt_key, 0);
130 |
131 | if( $attempts >= $this->app['config']->get('confide::throttle_limit') )
132 | {
133 | return true;
134 | }
135 | else
136 | {
137 | return false;
138 | }
139 | }
140 |
141 | /**
142 | * Send email with information about password reset
143 | *
144 | * @param string $email
145 | * @return bool
146 | */
147 | public function forgotPassword( $email )
148 | {
149 | $user = Confide::model()->where('email', '=', $email)->get()->first();
150 | if( $user )
151 | {
152 | $user->forgotPassword();
153 | return true;
154 | }
155 | else
156 | {
157 | return false;
158 | }
159 | }
160 |
161 | /**
162 | * Change user password
163 | *
164 | * @return string
165 | */
166 | public function resetPassword( $params )
167 | {
168 | $token = array_get($params, 'token', '');
169 |
170 | $email = $this->app['db']->connection()->table('password_reminders')
171 | ->select('email')->where('token','=',$token)
172 | ->first();
173 |
174 | if ($email)
175 | $email = $email->email;
176 |
177 | $user = Confide::model()->where('email', '=', $email)->get()->first();
178 | if( $user )
179 | {
180 | return $user->resetPassword( $params );
181 | }
182 | else
183 | {
184 | return false;
185 | }
186 | }
187 |
188 | /**
189 | * Log the user out of the application.
190 | *
191 | * @return void
192 | */
193 | public function logout()
194 | {
195 | $this->app['auth']->logout();
196 | }
197 |
198 | /**
199 | * Display the default login view
200 | *
201 | * @return Illuminate\View\View
202 | */
203 | public function makeLoginForm()
204 | {
205 | return $this->app['view']->make($this->app['config']->get('confide::login_form'));
206 | }
207 |
208 | /**
209 | * Display the default signup view
210 | *
211 | * @return Illuminate\View\View
212 | */
213 | public function makeSignupForm()
214 | {
215 | return $this->app['view']->make( $this->app['config']->get('confide::signup_form') );
216 | }
217 |
218 | /**
219 | * Display the forget password view
220 | *
221 | * @return Illuminate\View\View
222 | */
223 | public function makeForgotPasswordForm()
224 | {
225 | return $this->app['view']->make( $this->app['config']->get('confide::forgot_password_form') );
226 | }
227 |
228 | /**
229 | * Display the forget password view
230 | *
231 | * @return Illuminate\View\View
232 | */
233 | public function makeResetPasswordForm( $token )
234 | {
235 | return $this->app['view']->make( $this->app['config']->get('confide::reset_password_form') , array('token'=>$token));
236 | }
237 |
238 | /**
239 | * Returns the name of the cache key that will be used
240 | * to store the failed attempts
241 | *
242 | * @param array $credentials.
243 | * @return string.
244 | */
245 | protected function attemptCacheKey( $credentials )
246 | {
247 | return 'confide_flogin_attempt_'
248 | .$this->app['request']->server('REMOTE_ADDR')
249 | .$this->app['request']->server('HTTP_X_FORWARDED_FOR')
250 | .$credentials['email'];
251 | }
252 |
253 | /**
254 | * Checks if the current IP / email has reached the throttle
255 | * limit
256 | *
257 | * @param array $credentials
258 | * @return bool Value.
259 | */
260 | protected function reachedThrottleLimit( $credentials )
261 | {
262 | $attempt_key = $this->attemptCacheKey( $credentials );
263 | $attempts = $this->app['cache']->get($attempt_key, 0);
264 |
265 | return $attempts >= $this->app['config']->get('confide::throttle_limit');
266 | }
267 |
268 | /**
269 | * Increment IP / email throttle count
270 | *
271 | * @param array $credentials
272 | * @return void
273 | */
274 | protected function throttleCount( $credentials )
275 | {
276 | $attempt_key = $this->attemptCacheKey( $credentials );
277 | $attempts = $this->app['cache']->get($attempt_key, 0);
278 |
279 | $this->app['cache']->put($attempt_key, $attempts+1, 2); // used throttling login attempts
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/src/Zizaco/Confide/ConfideUser.php:
--------------------------------------------------------------------------------
1 | 'required|alpha_dash|between:4,16',
51 | 'email' => 'required|email',
52 | 'password' => 'required|between:4,11|confirmed',
53 | );
54 |
55 | /**
56 | * Create a new ConfideUser instance.
57 | */
58 | public function __construct()
59 | {
60 | parent::__construct();
61 |
62 | if ( ! static::$app )
63 | static::$app = app();
64 |
65 | $this->table = static::$app['config']->get('auth.table');
66 | }
67 |
68 | /**
69 | * Get the unique identifier for the user.
70 | *
71 | * @return mixed
72 | */
73 | public function getAuthIdentifier()
74 | {
75 | return $this->getKey();
76 | }
77 |
78 | /**
79 | * Get the password for the user.
80 | *
81 | * @return string
82 | */
83 | public function getAuthPassword()
84 | {
85 | return $this->password;
86 | }
87 |
88 | /**
89 | * Confirm the user (usually means that the user)
90 | * email is valid.
91 | *
92 | * @return bool
93 | */
94 | public function confirm()
95 | {
96 | $this->confirmed = 1;
97 |
98 | // Executes directly using query builder
99 | return static::$app['db']->table($this->table)
100 | ->where($this->getKeyName(), $this->getKey())
101 | ->update(array('confirmed'=>1));
102 | }
103 |
104 | /**
105 | * Send email with information about password reset
106 | *
107 | * @return string
108 | */
109 | public function forgotPassword()
110 | {
111 | $token = substr(md5(microtime().static::$app['config']->get('app.key')),-16);
112 |
113 | static::$app['db']->connection()->table('password_reminders')->insert(array(
114 | 'email'=> $this->email,
115 | 'token'=> $token,
116 | 'created_at'=> new \DateTime
117 | ));
118 |
119 | $view = static::$app['config']->get('confide::email_reset_password');
120 |
121 | $this->sendEmail( 'confide::confide.email.password_reset.subject', $view, array('user'=>$this, 'token'=>$token) );
122 |
123 | return true;
124 | }
125 |
126 | /**
127 | * Change user password
128 | *
129 | * @return string
130 | */
131 | public function resetPassword( $params )
132 | {
133 | $this->password = array_get($params, 'password', '');
134 | $this->password_confirmation = array_get($params, 'password_confirmation', '');
135 |
136 | if ( $this->save() )
137 | {
138 | return true;
139 | }
140 | else{
141 | return false;
142 | }
143 | }
144 |
145 | /**
146 | * Overwrite the Ardent save method. Saves model into
147 | * database
148 | *
149 | * @param array $rules:array
150 | * @param array $customMessages
151 | * @param closure $beforeSave
152 | * @param callable $afterSave
153 | * @return bool
154 | */
155 | public function save( $rules = array(), $customMessages = array(), Closure $beforeSave = null, Closure $afterSave = null )
156 | {
157 | return $this->real_save( $rules, $customMessages, $beforeSave, $afterSave );
158 | }
159 |
160 | /**
161 | * Ardent method overloading:
162 | * Before save the user. Generate a confirmation
163 | * code if is a new user.
164 | *
165 | * @param bool $forced Indicates whether the user is being saved forcefully
166 | * @return bool
167 | */
168 | public function beforeSave( $forced = false )
169 | {
170 | if ( empty($this->id) )
171 | {
172 | $this->confirmation_code = md5(microtime().static::$app['config']->get('app.key'));
173 | }
174 |
175 | /*
176 | * Remove password_confirmation field before save to
177 | * database.
178 | */
179 | if ( isset($this->password_confirmation) )
180 | {
181 | unset( $this->password_confirmation );
182 | }
183 |
184 | return true;
185 | }
186 |
187 | /**
188 | * Ardent method overloading:
189 | * After save, delivers the confirmation link email.
190 | * code if is a new user.
191 | *
192 | * @param bool $forced Indicates whether the user is being saved forcefully
193 | * @return bool
194 | */
195 | public function afterSave( $success, $forced = false )
196 | {
197 | if ( $success and ! $this->confirmed )
198 | {
199 | $view = static::$app['config']->get('confide::email_account_confirmation');
200 |
201 | $this->sendEmail( 'confide::confide.email.account_confirmation.subject', $view, array('user' => $this) );
202 | }
203 |
204 | return true;
205 | }
206 |
207 | /**
208 | * Runs the real eloquent save method or returns
209 | * true if it's under testing. Because Eloquent
210 | * and Ardent save methods are not Confide's
211 | * responsibility.
212 | *
213 | * @return bool
214 | */
215 | protected function real_save( $rules = array(), $customMessages = array(), Closure $beforeSave = null, Closure $afterSave = null )
216 | {
217 | if ( defined('CONFIDE_TEST') )
218 | {
219 | $this->beforeSave();
220 | $this->afterSave( true );
221 | return true;
222 | }
223 | else{
224 |
225 | /*
226 | * This will make sure that a non modified password
227 | * will not trigger validation error.
228 | */
229 | if( empty($rules) && $this->password == $this->getOriginal('password') )
230 | {
231 | $rules = static::$rules;
232 | $rules['password'] = 'required';
233 | }
234 |
235 | return parent::save( $rules, $customMessages, $beforeSave, $afterSave );
236 | }
237 | }
238 |
239 | /**
240 | * Add the namespace 'confide::' to view hints.
241 | * this makes possible to send emails using package views from
242 | * the command line.
243 | *
244 | * @return void
245 | */
246 | protected static function fixViewHint()
247 | {
248 | if (isset(static::$app['view.finder']))
249 | static::$app['view.finder']->addNamespace('confide', __DIR__.'/../../views');
250 | }
251 |
252 | /**
253 | * Send email using the lang sentence as subject and the viewname
254 | *
255 | * @param mixed $subject_translation
256 | * @param mixed $view_name
257 | * @return voi.
258 | */
259 | protected function sendEmail( $subject_translation, $view_name, $params = array() )
260 | {
261 | if ( static::$app['config']->getEnvironment() == 'testing' )
262 | return;
263 |
264 | static::fixViewHint();
265 |
266 | $user = $this;
267 |
268 | static::$app['mailer']->send($view_name, $params, function($m) use ($subject_translation, $user)
269 | {
270 | $m->to( $user->email )
271 | ->subject( ConfideUser::$app['translator']->get($subject_translation) );
272 | });
273 | }
274 | }
275 |
--------------------------------------------------------------------------------
/src/views/generators/controller.blade.php:
--------------------------------------------------------------------------------
1 | {{{ 'username = Input::get( 'username' );
33 | ${{ lcfirst(Config::get('auth.model')) }}->email = Input::get( 'email' );
34 | ${{ lcfirst(Config::get('auth.model')) }}->password = Input::get( 'password' );
35 |
36 | // The password confirmation will be removed from model
37 | // before saving. This field will be used in Ardent's
38 | // auto validation.
39 | ${{ lcfirst(Config::get('auth.model')) }}->password_confirmation = Input::get( 'password_confirmation' );
40 |
41 | // Save if valid. Password field will be hashed before save
42 | ${{ lcfirst(Config::get('auth.model')) }}->save();
43 |
44 | if ( ${{ lcfirst(Config::get('auth.model')) }}->id )
45 | {
46 | // Redirect with success message, You may replace "Lang::get(..." for your custom message.
47 | @if (! $restful)
48 | return Redirect::action('{{ $name }}@login')
49 | @else
50 | return Redirect::to('user/login')
51 | @endif
52 | ->with( 'notice', Lang::get('confide::confide.alerts.account_created') );
53 | }
54 | else
55 | {
56 | // Get validation errors (see Ardent package)
57 | $error = ${{ lcfirst(Config::get('auth.model')) }}->getErrors()->all();
58 |
59 | @if (! $restful)
60 | return Redirect::action('{{ $name }}@create')
61 | @else
62 | return Redirect::to('user/create')
63 | @endif
64 | ->withInput(Input::except('password'))
65 | ->with( 'error', $error );
66 | }
67 | }
68 |
69 | /**
70 | * Displays the login form
71 | *
72 | */
73 | public function {{ (! $restful) ? 'login' : 'getLogin' }}()
74 | {
75 | if( Confide::user() )
76 | {
77 | // If user is logged, redirect to internal
78 | // page, change it to '/admin', '/dashboard' or something
79 | return Redirect::to('/');
80 | }
81 | else
82 | {
83 | return Confide::makeLoginForm();
84 | }
85 | }
86 |
87 | /**
88 | * Attempt to do login
89 | *
90 | */
91 | public function {{ (! $restful) ? 'do_login' : 'postLogin' }}()
92 | {
93 | $input = array(
94 | 'email' => Input::get( 'email' ), // May be the username too
95 | 'password' => Input::get( 'password' ),
96 | 'remamber' => Input::get( 'remember' ),
97 | );
98 |
99 | // If you wish to only allow login from confirmed users, call logAttempt
100 | // with the second parameter as true.
101 | // logAttempt will check if the 'email' perhaps is the username.
102 | if ( Confide::logAttempt( $input ) )
103 | {
104 | // If the session 'loginRedirect' is set, then redirect
105 | // to that route. Otherwise redirect to '/'
106 | $r = Session::get('loginRedirect');
107 | if (!empty($r))
108 | {
109 | Session::forget('loginRedirect');
110 | return Redirect::to($r);
111 | }
112 |
113 | return Redirect::to('/'); // change it to '/admin', '/dashboard' or something
114 | }
115 | else
116 | {
117 | // Check if there was too many login attempts
118 | if( Confide::isThrottled( $input ) )
119 | {
120 | $err_msg = Lang::get('confide::confide.alerts.too_many_attempts');
121 | }
122 | else
123 | {
124 | $err_msg = Lang::get('confide::confide.alerts.wrong_credentials');
125 | }
126 |
127 | @if (! $restful)
128 | return Redirect::action('{{ $name }}@login')
129 | @else
130 | return Redirect::to('user/login')
131 | @endif
132 | ->withInput(Input::except('password'))
133 | ->with( 'error', $err_msg );
134 | }
135 | }
136 |
137 | /**
138 | * Attempt to confirm account with code
139 | *
140 | * @param string $code
141 | */
142 | public function {{ (! $restful) ? 'confirm' : 'getConfirm' }}( $code )
143 | {
144 | if ( Confide::confirm( $code ) )
145 | {
146 | $notice_msg = Lang::get('confide::confide.alerts.confirmation');
147 | @if (! $restful)
148 | return Redirect::action('{{ $name }}@login')
149 | @else
150 | return Redirect::to('user/login')
151 | @endif
152 | ->with( 'notice', $notice_msg );
153 | }
154 | else
155 | {
156 | $error_msg = Lang::get('confide::confide.alerts.wrong_confirmation');
157 | @if (! $restful)
158 | return Redirect::action('{{ $name }}@login')
159 | @else
160 | return Redirect::to('user/login')
161 | @endif
162 | ->with( 'error', $error_msg );
163 | }
164 | }
165 |
166 | /**
167 | * Displays the forgot password form
168 | *
169 | */
170 | public function {{ (! $restful) ? 'forgot_password' : 'getForgot' }}()
171 | {
172 | return Confide::makeForgotPasswordForm();
173 | }
174 |
175 | /**
176 | * Attempt to send change password link to the given email
177 | *
178 | */
179 | public function {{ (! $restful) ? 'do_forgot_password' : 'postForgot' }}()
180 | {
181 | if( Confide::forgotPassword( Input::get( 'email' ) ) )
182 | {
183 | $notice_msg = Lang::get('confide::confide.alerts.password_forgot');
184 | @if (! $restful)
185 | return Redirect::action('{{ $name }}@login')
186 | @else
187 | return Redirect::to('user/login')
188 | @endif
189 | ->with( 'notice', $notice_msg );
190 | }
191 | else
192 | {
193 | $error_msg = Lang::get('confide::confide.alerts.wrong_password_forgot');
194 | @if (! $restful)
195 | return Redirect::action('{{ $name }}@forgot_password')
196 | @else
197 | return Redirect::to('user/forgot')
198 | @endif
199 | ->withInput()
200 | ->with( 'error', $error_msg );
201 | }
202 | }
203 |
204 | /**
205 | * Shows the change password form with the given token
206 | *
207 | */
208 | public function {{ (! $restful) ? 'reset_password' : 'getReset' }}( $token )
209 | {
210 | return Confide::makeResetPasswordForm( $token );
211 | }
212 |
213 | /**
214 | * Attempt change password of the user
215 | *
216 | */
217 | public function {{ (! $restful) ? 'do_reset_password' : 'postReset' }}()
218 | {
219 | $input = array(
220 | 'token'=>Input::get( 'token' ),
221 | 'password'=>Input::get( 'password' ),
222 | 'password_confirmation'=>Input::get( 'password_confirmation' ),
223 | );
224 |
225 | // By passing an array with the token, password and confirmation
226 | if( Confide::resetPassword( $input ) )
227 | {
228 | $notice_msg = Lang::get('confide::confide.alerts.password_reset');
229 | @if (! $restful)
230 | return Redirect::action('{{ $name }}@login')
231 | @else
232 | return Redirect::to('user/login')
233 | @endif
234 | ->with( 'notice', $notice_msg );
235 | }
236 | else
237 | {
238 | $error_msg = Lang::get('confide::confide.alerts.wrong_password_reset');
239 | @if (! $restful)
240 | return Redirect::action('{{ $name }}@reset_password', array('token'=>$input['token']))
241 | @else
242 | return Redirect::to('user/reset')
243 | @endif
244 | ->withInput()
245 | ->with( 'error', $error_msg );
246 | }
247 | }
248 |
249 | /**
250 | * Log the user out of the application.
251 | *
252 | */
253 | public function {{ (! $restful) ? 'logout' : 'getLogout' }}()
254 | {
255 | Confide::logout();
256 |
257 | return Redirect::to('/');
258 | }
259 |
260 | }
261 |
--------------------------------------------------------------------------------
/tests/ConfideTest.php:
--------------------------------------------------------------------------------
1 | mockApp();
23 | $this->confide = new Confide();
24 |
25 | // Set the app attribute with mock
26 | $this->confide->app = $app;
27 | }
28 |
29 | public function testGetModel()
30 | {
31 | // Make shure it grabbed the model from config
32 | $config = m::mock('Illuminate\Config\Repository');
33 | $config->shouldReceive('get')
34 | ->with('auth.model')
35 | ->andReturn( 'User' )
36 | ->once();
37 | $this->confide->app['config'] = $config;
38 |
39 | // Mocks an user
40 | $confide_user = $this->mockConfideUser();
41 |
42 | // Make shure the object provider returns the
43 | // user object when called
44 | $this->objProviderShouldReturn( 'User', $confide_user );
45 |
46 | $user = $this->confide->model();
47 |
48 | $this->assertNotNull( $user );
49 | }
50 |
51 | public function testShouldGetUser()
52 | {
53 | $confide_user = $this->mockConfideUser();
54 |
55 | // Laravel auth component should return user
56 | $auth = m::mock('Illuminate\Auth\Guard');
57 | $auth->shouldReceive('user')
58 | ->andReturn( $confide_user )
59 | ->once();
60 | $this->confide->app['auth'] = $auth;
61 |
62 | $this->assertEquals( $confide_user, $this->confide->user() );
63 | }
64 |
65 | public function testShouldConfirm()
66 | {
67 | $confide_user = $this->mockConfideUser();
68 | $confide_user->shouldReceive('confirm')
69 | ->andReturn( true )
70 | ->once();
71 |
72 | $this->objProviderShouldReturn( 'User', $confide_user );
73 |
74 | $this->assertTrue( $this->confide->confirm( '123123' ) );
75 | }
76 |
77 | public function testShouldLogAttempt()
78 | {
79 | $confide_user = $this->mockConfideUser();
80 |
81 | // Considering a valid hash check from hash component
82 | $hash = m::mock('Illuminate\Hashing\HasherInterface');
83 | $hash->shouldReceive('check')
84 | ->andReturn( true )
85 | ->times(2); // 2 successfull logins
86 | $this->confide->app['hash'] = $hash;
87 |
88 | $this->objProviderShouldReturn( 'User', $confide_user );
89 |
90 | $this->assertTrue(
91 | $this->confide->logAttempt( array( 'email'=>'username', 'password'=>'123123' ) )
92 | );
93 |
94 | // Should not login with unconfirmed user.
95 | $this->assertFalse(
96 | $this->confide->logAttempt( array( 'email'=>'username', 'password'=>'123123' ), true )
97 | );
98 |
99 | $confide_user->confirmed = 1;
100 |
101 | // Should login because now the user is confirmed
102 | $this->assertTrue(
103 | $this->confide->logAttempt( array( 'email'=>'username', 'password'=>'123123' ), true )
104 | );
105 | }
106 |
107 | public function testShouldThrottleLogAttempt()
108 | {
109 | $tries = 15;
110 |
111 | $confide_user = $this->mockConfideUser();
112 | $confide_user->shouldReceive('get','first')
113 | ->andReturn( null );
114 |
115 | $this->objProviderShouldReturn( 'User', $confide_user );
116 |
117 | $this->confide->app['hash']->shouldReceive('check')
118 | ->andReturn( false );
119 |
120 | for ($i=0; $i < $tries; $i++) {
121 |
122 | // Simulates cache values
123 | $this->useCacheForThrottling($i);
124 |
125 | // Make shure the login is not happening anyway
126 | $this->assertFalse(
127 | $this->confide->logAttempt( array('email'=>'wrong', 'password'=>'wrong') )
128 | );
129 | }
130 |
131 | // Check if the credentials has been throttled
132 | $this->assertTrue(
133 | $this->confide->isThrottled( array('email'=>'wrong', 'password'=>'wrong') )
134 | );
135 | }
136 |
137 | public function testShouldResetPassword()
138 | {
139 | $confide_user = $this->mockConfideUser();
140 | $confide_user->shouldReceive('resetPassword')
141 | ->andReturn( true )
142 | ->once();
143 |
144 | $this->objProviderShouldReturn( 'User', $confide_user );
145 |
146 | $this->assertTrue( $this->confide->resetPassword( 'mail@sample.com' ) );
147 | }
148 |
149 | public function testShouldLogout()
150 | {
151 | // Make shure auth logout method is called
152 | $auth = m::mock('Illuminate\Auth\Guard');
153 | $auth->shouldReceive('logout')
154 | ->once();
155 |
156 | $this->confide->app['auth'] = $auth;
157 | $this->assertEquals( null, $this->confide->logout() );
158 | }
159 |
160 | public function testShouldMakeForms()
161 | {
162 | // Make shure view make method is called 3 times
163 | $view = m::mock('Illuminate\View\Environment\View');
164 | $view->shouldReceive('make')
165 | ->andReturn( 'Content' )
166 | ->times( 3 );
167 |
168 | $this->confide->app['view'] = $view;
169 |
170 | $this->assertNotEquals( null, $this->confide->MakeLoginForm() );
171 | $this->assertNotEquals( null, $this->confide->makeSignupForm() );
172 | $this->assertNotEquals( null, $this->confide->makeForgotPasswordForm() );
173 | }
174 |
175 | private function mockConfideUser()
176 | {
177 | $confide_user = m::mock( 'Illuminate\Auth\UserInterface' );
178 | $confide_user->username = 'uname';
179 | $confide_user->password = '123123';
180 | $confide_user->confirmed = 0;
181 | $confide_user->shouldReceive('where','get', 'orWhere','first', 'all')
182 | ->andReturn( $confide_user );
183 |
184 | return $confide_user;
185 | }
186 |
187 | private function mockApp()
188 | {
189 | // Mocks the application components that
190 | // are not Confide's responsibility
191 | $app = array();
192 |
193 | $app['config'] = m::mock( 'Config' );
194 | $app['config']->shouldReceive( 'get' )
195 | ->with( 'auth.table' )
196 | ->andReturn( 'users' );
197 |
198 | $app['config']->shouldReceive( 'get' )
199 | ->with( 'auth.model' )
200 | ->andReturn( 'User' );
201 |
202 | $app['config']->shouldReceive( 'get' )
203 | ->with( 'app.key' )
204 | ->andReturn( '123' );
205 |
206 | $app['config']->shouldReceive( 'get' )
207 | ->with( 'confide::throttle_limit' )
208 | ->andReturn( 9 );
209 |
210 | $app['config']->shouldReceive( 'get' )
211 | ->andReturn( 'confide::login' );
212 |
213 | $app['mail'] = m::mock( 'Mail' );
214 | $app['mail']->shouldReceive('send')
215 | ->andReturn( null );
216 |
217 | $app['hash'] = m::mock( 'Hash' );
218 | $app['hash']->shouldReceive('make')
219 | ->andReturn( 'aRandomHash' );
220 |
221 | $app['cache'] = m::mock( 'Cache' );
222 | $app['cache']->shouldReceive('get')
223 | ->andReturn( 0 );
224 | $app['cache']->shouldReceive('put');
225 |
226 | $app['auth'] = m::mock( 'Auth' );
227 | $app['auth']->shouldReceive('login')
228 | ->andReturn( true );
229 |
230 | $app['request'] = m::mock( 'Request' );
231 | $app['request']->shouldReceive('server')
232 | ->andReturn( null );
233 |
234 | $app['db'] = m::mock( 'DatabaseManager' );
235 | $app['db']->shouldReceive('connection')
236 | ->andReturn( $app['db'] );
237 | $app['db']->shouldReceive('table')
238 | ->andReturn( $app['db'] );
239 | $app['db']->shouldReceive('select')
240 | ->andReturn( $app['db'] );
241 | $app['db']->shouldReceive('where')
242 | ->andReturn( $app['db'] );
243 | $app['db']->shouldReceive('first')
244 | ->andReturn( $app['db'] );
245 | $app['db']->email = 'test@example.com';
246 |
247 | return $app;
248 | }
249 |
250 | private function useCacheForThrottling( $value )
251 | {
252 | $cache = m::mock('Illuminate\Cache\Store');
253 | $cache->shouldReceive('put')
254 | ->with( "confide_flogin_attempt_wrong", $value+1, 2 )
255 | ->once();
256 | $cache->shouldReceive('get')
257 | ->andReturn( $value );
258 | $this->confide->app['cache'] = $cache;
259 | }
260 |
261 | /**
262 | * the ObjectProvider getObject method should
263 | * be called with $class to return $object.
264 | *
265 | * @param string $class
266 | * @param mixed $obj
267 | * @return void
268 | */
269 | private function objProviderShouldReturn( $class, $obj )
270 | {
271 | $obj_provider = m::mock('ObjectProvider');
272 | $obj_provider->shouldReceive('getObject')
273 | ->with($class)
274 | ->andReturn( $obj );
275 |
276 | $this->confide->objectRepository = $obj_provider;
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Confide (Laravel4 Package)
2 |
3 | 
4 |
5 | [](https://travis-ci.org/Zizaco/confide)
6 | [](http://stillmaintained.com/Zizaco/confide)
7 |
8 | Confide is a authentication solution for **Laravel4** made to eliminate repetitive tasks involving the management of users: Account creation, login, logout, confirmation by e-mail, password reset, etc.
9 |
10 | Confide aims to be simple to use, quick to configure and flexible.
11 |
12 | ## Features
13 |
14 | **Current:**
15 | - Account confirmation (through confirmation link).
16 | - Password reset (sending email with a change password link).
17 | - Easily render forms for login, signup and password reset.
18 | - Generate customizable routes for login, signup, password reset, confirmation, etc.
19 | - Generate a customizable controller that handles the basic user account actions.
20 | - Contains a set of methods to help basic user features.
21 | - Integrated with the Laravel Auth component/configs.
22 | - Field/model validation (Powered by [Ardent](http://laravelbook.github.com/ardent "Ardent")).
23 | - Login throttling.
24 | - Redirecting to previous route after authentication.
25 |
26 | If you are looking for user roles and permissions see [Entrust](https://github.com/Zizaco/entrust)
27 |
28 | **Planned:**
29 | - Captcha in user signup and password reset.
30 | - General improvements.
31 |
32 | ## Quick start
33 |
34 | ### Required setup
35 |
36 | In the `require` key of `composer.json` file add the following
37 |
38 | "zizaco/confide": "dev-master"
39 |
40 | Run the Composer update comand
41 |
42 | $ composer update
43 |
44 | In your `config/app.php` add `'Zizaco\Confide\ConfideServiceProvider'` to the end of the `$providers` array
45 |
46 | 'providers' => array(
47 |
48 | 'Illuminate\Foundation\Providers\ArtisanServiceProvider',
49 | 'Illuminate\Auth\AuthServiceProvider',
50 | ...
51 | 'Zizaco\Confide\ConfideServiceProvider',
52 |
53 | ),
54 |
55 | At the end of `config/app.php` add `'Confide' => 'Zizaco\Confide\ConfideFacade'` to the `$aliases` array
56 |
57 | 'aliases' => array(
58 |
59 | 'App' => 'Illuminate\Support\Facades\App',
60 | 'Artisan' => 'Illuminate\Support\Facades\Artisan',
61 | ...
62 | 'Confide' => 'Zizaco\Confide\ConfideFacade',
63 |
64 | ),
65 |
66 | ### Configuration
67 |
68 | Set the properly values to the `config/auth.php`. This values will be used by confide to generate the database migration and to generate controllers and routes.
69 |
70 | Set the `address` and `name` from the `from` array in `config/mail.php`. Those will be used to send account confirmation and password reset emails to the users.
71 |
72 | ### User model
73 |
74 | Now generate the Confide migration and the reminder password table migration:
75 |
76 | $ php artisan confide:migration
77 |
78 | It will generate the `_confide_setup_users_table.php` migration. You may now run it with the artisan migrate command:
79 |
80 | $ php artisan migrate
81 |
82 | It will setup a table containing `username`, `email`, `password`, `confirmation_code` and `confirmed` fields, which are the default fields needed for Confide use. Feel free to add more fields to the database.
83 |
84 | Change your User model in `app/models/User.php` to:
85 |
86 | render() }}`.
126 | 2. Generate a controller with the template contained in Confide throught the artisan command `$ php artisan confide:controller`. If a controller with the same name exists it will **NOT** be overwritten.
127 | 3. Generate routes matching the controller template throught the artisan command `$ php artisan confide:routes`. Your `routes.php` will **NOT** be overwritten.
128 |
129 | ### Advanced
130 |
131 | #### Using custom table / model name
132 |
133 | You can change the model name that will be authenticated in the `config/auth.php` file.
134 | Confide uses the values present in that configuration file.
135 |
136 | To change the controller name when dumping the default controller template you can use the --name option.
137 |
138 | $ php artisan confide:controller --name Employee
139 |
140 | Will result in `EmployeeController`
141 |
142 | Then, when dumping the routes, you should use the --controller option to match the existing controller.
143 |
144 | $ php artisan confide:routes --controller Employee
145 |
146 | #### Using custom form or emails
147 |
148 | First, publish the config files:
149 |
150 | $ php artisan config:publish zizaco/confide
151 |
152 | Then edit the view names in `app/config/packages/zizaco/confide/config.php`.
153 |
154 | #### Validate model fields
155 |
156 | To change the validation rules of the User model you can take a look at [Ardent](http://laravelbook.github.com/ardent/#validation "Ardent Validation Rulez"). For example:
157 |
158 | 'required|alpha_dash|between:6,12',
169 | 'email' => 'required|email',
170 | 'password' => 'required|between:4,11|confirmed',
171 | );
172 |
173 | }
174 |
175 | Feel free to add more fields to your table and to the validation array. Then you should build you own signup form with the aditional fields.
176 |
177 | #### RESTful controller
178 |
179 | If you want to generate a [RESTful controller](https://github.com/laravel/docs/blob/master/controllers.md#restful-controllers) you can use the aditional `--restful` or `-r` option.
180 |
181 | $ php artisan confide:controller --restful
182 |
183 | Will result in a [RESTful controller](https://github.com/laravel/docs/blob/master/controllers.md#restful-controllers)
184 |
185 | Then, when dumping the routes, you should use the --restful option to match the existing controller.
186 |
187 | $ php artisan confide:routes --restful
188 |
189 | #### User roles and permissions
190 |
191 | In order not to bloat Confide with not related features, the role and permission was developed as another package: [Entrust](https://github.com/Zizaco/entrust). This package couples very well with Confide.
192 |
193 | See [Entrust](https://github.com/Zizaco/entrust)
194 |
195 | #### Redirecting to previous route after login
196 |
197 | When defining your filter you should set the `'loginRedirect'` session variable. For example:
198 |
199 | // filters.php
200 |
201 | Route::filter('auth', function()
202 | {
203 | if ( Auth::guest() ) // If the user is not logged in
204 | {
205 | // Set the loginRedirect session variable
206 | Session::put( 'loginRedirect', Request::url() );
207 |
208 | // Redirect back to user login
209 | return Redirect::to( 'user/login' );
210 | }
211 | });
212 |
213 | // Only authenticated users will be able to access routes that begins with
214 | // 'admin'. Ex: 'admin/posts', 'admin/categories'.
215 | Route::when('admin*', 'auth');
216 |
217 | or, if you are using [Entrust](https://github.com/Zizaco/entrust) ;)
218 |
219 | // filters.php
220 |
221 | Entrust::routeNeedsRole( 'admin*', 'Admin', function(){
222 | Session::put( 'loginRedirect', Request::url() );
223 | return Redirect::to( 'user/login' );
224 | } );
225 |
226 | ## Troubleshooting
227 |
228 | __[Exception] SQLSTATE[HY000]: General error: 1364 Field 'confirmation_code' doesn't have a default value...__
229 |
230 | If you overwrite the `beforeSave()` method in your model, make sure to call `parent::beforeSave()`:
231 |
232 | public function beforeSave( $forced = false ){
233 |
234 | parent::beforeSave( $forced) // Don't forget this
235 |
236 | // Your stuff
237 | }
238 |
239 | __Confirmation link is not sent when user signup__
240 |
241 | Same as above. If you overwrite the `afterSave()` method in your model, make sure to call `parent::afterSave()`:
242 |
243 | __Users are able to login without confirming account__
244 |
245 | If you want only confirmed users to login, in your `UserController`, instead of simply calling `logAttempt( $input )`, call `logAttempt( $input, true )`. The second parameter stands for _"confirmed_only"_.
246 |
247 |
248 | ## License
249 |
250 | Confide is free software distributed under the terms of the MIT license
251 |
252 | ## Aditional information
253 |
254 | Any questions, feel free to contact me or ask [here](http://forums.laravel.io/viewtopic.php?id=4658)
255 |
256 | Any issues, please [report here](https://github.com/Zizaco/confide/issues)
257 |
--------------------------------------------------------------------------------