Completed
Push — master ( 15a5bf...eb9630 )
by Joao
08:35
created

AuthController   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 435
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 4
Bugs 0 Features 2
Metric Value
wmc 49
c 4
b 0
f 2
lcom 1
cbo 9
dl 0
loc 435
rs 8.5454

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getSignin() 0 9 2
A getSignup() 0 9 2
A getLostPassword() 0 9 2
A getForgotPasswordConfirm() 0 12 2
A getLogout() 0 8 1
B getActivate() 0 32 4
B postSignin() 0 53 7
F postSignup() 0 135 21
B postForgotPassword() 0 42 4
B postForgotPasswordConfirm() 0 38 3

How to fix   Complexity   

Complex Class

Complex classes like AuthController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AuthController, and based on these observations, apply Extract Interface, too.

1
<?php namespace jlourenco\base\Controllers;
2
3
use App\Http\Controllers\Controller;
4
use Illuminate\Support\Facades\Request;
5
use Sentinel;
6
use View;
7
use Validator;
8
use Input;
9
use Session;
10
use Redirect;
11
use Lang;
12
use URL;
13
use Activation;
14
use Base;
15
use \Cartalyst\Sentinel\Checkpoints\NotActivatedException;
16
use \Cartalyst\Sentinel\Checkpoints\ThrottlingException;
17
use Reminder;
18
use Mail;
19
use Illuminate\Support\MessageBag;
20
21
class AuthController extends controller
22
{
23
    use \jlourenco\support\Traits\CaptchaTrait;
24
25
    /**
26
     * Message bag.
27
     *
28
     * @var Illuminate\Support\MessageBag
29
     */
30
    protected $messageBag = null;
31
32
    /**
33
     * Initializer.
34
     *
35
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
36
     */
37
    public function __construct()
38
    {
39
        $this->messageBag = new MessageBag;
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Illuminate\Support\MessageBag() of type object<Illuminate\Support\MessageBag> is incompatible with the declared type object<jlourenco\base\Co...ate\Support\MessageBag> of property $messageBag.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
40
    }
41
42
    /**
43
     * Account sign in.
44
     *
45
     * @return View
46
     */
47
    public function getSignin()
48
    {
49
        // Is the user logged in?
50
        if (Sentinel::check())
51
            return Redirect::route('home');
52
53
        // Show the page
54
        return View('auth.login');
55
    }
56
57
    /**
58
     * Account sign up.
59
     *
60
     * @return View
61
     */
62
    public function getSignup()
63
    {
64
        // Is the user logged in?
65
        if (Sentinel::check())
66
            return Redirect::route('home');
67
68
        // Show the page
69
        return View('auth.register');
70
    }
71
72
    /**
73
     * Account sign up.
74
     *
75
     * @return View
76
     */
77
    public function getLostPassword()
78
    {
79
        // Is the user logged in?
80
        if (Sentinel::check())
81
            return Redirect::route('home');
82
83
        // Show the page
84
        return View('auth.forgot-password');
85
    }
86
87
    /**
88
     * Forgot Password Confirmation page.
89
     *
90
     * @param number $userId
91
     * @param  string $passwordResetCode
92
     * @return View
93
     */
94
    public function getForgotPasswordConfirm($userId, $passwordResetCode)
95
    {
96
        // Find the user using the password reset code
97
        if(!$user = Sentinel::findById($userId))
98
        {
99
            // Redirect to the forgot password page
100
            return Redirect::route('forgot-password')->with('error', Lang::get('base.auth.forgot_password_confirm.error'));
101
        }
102
103
        // Show the page
104
        return View('auth.forgot-password-confirm', compact('userId', 'passwordResetCode'));
105
    }
106
107
    /**
108
     * Logout page.
109
     *
110
     * @return Redirect
111
     */
112
    public function getLogout()
113
    {
114
        // Log the user out
115
        Sentinel::logout();
116
117
        // Redirect to the users page
118
        return Redirect::to('/')->with('success', Lang::get('base.auth.logged_out'));
119
    }
120
121
    /**
122
     * User account activation page.
123
     *
124
     * @param number $userId
125
     * @param string $activationCode
126
     * @return
127
     */
128
    public function getActivate($userId, $activationCode)
129
    {
130
        // Is user logged in?
131
        if (Sentinel::check()) {
132
            return Redirect::route('home');
133
        }
134
135
        // Find the user using the password reset code
136
        if(!$user = Sentinel::findById($userId))
137
        {
138
            // Redirect to the forgot password page
139
            return Redirect::route('login')->with('error', Lang::get('base.auth.activate.error'));
140
        }
141
        // $activation = Activation::exists($user);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
142
143
        if (Activation::complete($user, $activationCode))
144
        {
145
            $user->status = 1;
146
            $user->save();
147
            
148
            // Activation was successful
149
            // Redirect to the login page
150
            return Redirect::route('login')->with('success', Lang::get('base.auth.activate.success'));
151
        }
152
        else
153
        {
154
            // Activation not found or not completed.
155
            $error = Lang::get('base.auth.activate.error');
156
            return Redirect::route('login')->with('error', $error);
157
        }
158
159
    }
160
161
    /**
162
     * Account sign in form processing.
163
     *
164
     * @return Redirect
165
     */
166
    public function postSignin()
167
    {
168
        $isEmail = preg_match('/@/', Input::get('email'));
169
170
        // Declare the rules for the form validation
171
        $rules = array(
172
            'email' => 'required|email',
173
            'password' => 'required|between:3,32',
174
        );
175
176
        if (!$isEmail)
177
            $rules['email'] = 'required';
178
179
        // Create a new validator instance from our validation rules
180
        $validator = Validator::make(Input::all(), $rules);
181
182
        // If validation fails, we'll exit the operation now.
183
        if ($validator->fails()) {
184
            // Ooops.. something went wrong
185
            return back()->withInput()->withErrors($validator);
186
        }
187
        try {
188
            foreach(Sentinel::createModel()->getLoginNames() as $loginName)
189
            {
190
                $data = array(
191
                    $loginName => Input::only('email')["email"],
192
                    "password" => Input::only('password')["password"]
193
                );
194
195
                // Try to log the user in
196
                if(Sentinel::authenticate($data, Input::get('remember-me', false)))
197
                {
198
                    $user = Sentinel::check();
199
                    $user->update(['ip' => Request::ip()]);
200
                    Base::Log($user->username . ' (' . $user->first_name . ' ' . $user->last_name . ') logged in with IP ' . Request::ip() );
201
                    
202
                    // Redirect to the dashboard page
203
                    return Redirect::route("home")->with('success', Lang::get('base.auth.signin.success'));
204
                }
205
            }
206
207
            $this->messageBag->add('email', Lang::get('base.auth.account.not_found'));
208
        } catch (NotActivatedException $e) {
209
            $this->messageBag->add('email', Lang::get('base.auth.account.not_activated'));
210
        } catch (ThrottlingException $e) {
211
            $delay = $e->getDelay();
212
            $this->messageBag->add('email', Lang::get('base.auth.account.suspended', compact('delay' )));
213
        }
214
        Base::Log('Login attempt registred for ' . Input::only('email')["email"] . ' from IP ' . Request::ip() );
215
216
        // Ooops.. something went wrong
217
        return back()->withInput()->withErrors($this->messageBag);
218
    }
219
220
    /**
221
     * Account sign up form processing.
222
     *
223
     * @return Redirect
224
     */
225
    public function postSignup()
226
    {
227
        /************TEMP VARIABLE************/
228
        /*
229
         * 0 - Disabled
230
         * 1 - Enabled and no activation
231
         * 2 - User activation
232
         * 3 - Admin activation
233
         */
234
235
        $signupStatus = \Base::getSetting('USER_REGISTRATION');
236
        /************TEMP VARIABLE************/
237
238
        $signupEnabled = $signupStatus != 0;
239
        $userActivation = $signupStatus == 2;
240
        $adminActivation = $signupStatus == 3;
241
242
        if (!$signupEnabled)
243
            return Redirect::to(URL::previous())->withInput()->with('error', Lang::get('base.auth.account.registration_disabled'));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Redirect::to(\UR...gistration_disabled')); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by jlourenco\base\Controlle...hController::postSignup of type Illuminate\Routing\Redirector.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
244
245
        $rules = array();
246
247
        // Declare the rules for the form validation
248
        foreach(Sentinel::createModel()->getRegisterFields() as $fieldid => $field)
249
            $rules[$fieldid] = $field['validator'];
250
251
        $rules['g-recaptcha-response'] = 'required';
252
253
        // Create a new validator instance from our validation rules
254
        $validator = Validator::make(Input::all(), $rules);
255
256
        $err = false;
257
258
        // If validation fails, we'll exit the operation now.
259
        if ($validator->fails() || ($err = $this->captchaCheck()) == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
260
            if ($err)
261
                return Redirect::to(URL::previous())->withInput()->withErrors(['g-recaptcha-response' => Lang::get('base.captcha.error')]);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Redirect::to(\UR...base.captcha.error'))); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by jlourenco\base\Controlle...hController::postSignup of type Illuminate\Routing\Redirector.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
262
263
            // Ooops.. something went wrong
264
            return Redirect::to(URL::previous())->withInput()->withErrors($validator);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Redirect::to(\UR...withErrors($validator); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by jlourenco\base\Controlle...hController::postSignup of type Illuminate\Routing\Redirector.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
265
        }
266
267
        try {
268
            $data = array();
269
270
            // Set the data to the user from the User class
271
            foreach(Sentinel::createModel()->getRegisterFields() as $fieldid => $field)
272
                $data[$fieldid] = Input::get($fieldid);
273
274
            // Set the standard data to the user
275
            $data['ip'] = Request::getClientIP();
276
            $data['status'] = 0;
277
            $data['staff'] = 0;
278
            if ($data['birthday'] != null)
279
                $data['birthday'] = \Carbon\Carbon::createFromFormat('d/m/Y', $data['birthday']);
280
281
            // Find the user if it exists and needs to be created
282
            $user = Sentinel::getUserRepository()->findByCredentials(['email' => Input::get('email')]);
283
284
            if ($user != null)
285
            {
286
                // Update the temporary user to the new one
287
                if (Sentinel::validForUpdate($data, ['email' => Input::get('email')])) {
288
                    $testing = Sentinel::createModel()->getRegisterFields();
289
                    $user = Sentinel::findById($user->id);
290
291
                    foreach($data as $fieldid => $field)
292
                        if (!isset($testing[$fieldid]) || $testing[$fieldid]['save'] == true)
293
                            $user[$fieldid] = $field;
294
295
                    $user['password'] = bcrypt($user['password']);
296
                    Sentinel::update($user, ['email' => Input::get('email')]);
297
                }
298
                else
299
                    return Redirect::to(URL::previous())->withInput()->with('error', Lang::get('base.auth.account.registration_failed'));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Redirect::to(\UR...registration_failed')); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by jlourenco\base\Controlle...hController::postSignup of type Illuminate\Routing\Redirector.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
300
            }
301
            // Register the user
302
            else
303
                $user = Sentinel::register($data, false);
304
305
            // If the user needs to activate the account send him an email
306
            if ($userActivation)
307
            {
308
                $activation = Activation::create($user);
309
310
                // Data to be used on the email view
311
                $data = array(
312
                    'user'          => $user,
313
                    'activationUrl' => URL::route('activate', [$user->id, $activation->code]),
314
                );
315
316
                // Send the activation code through email
317
                Mail::queue('emails.auth.register-activate', $data, function ($m) use ($user) {
318
                    $m->to($user->email, $user->first_name . ' ' . $user->last_name);
319
                    $m->subject(Lang::get('base.mails.welcome') . ' ' . $user->first_name);
320
                });
321
            }
322
323
            // If the administrator needs to activate the account send the user a warning saying that
324
            if ($adminActivation)
325
            {
326
                Mail::queue('emails.auth.register-admin-activate', ['user' => $user], function ($m) use ($user) {
327
                    $m->to($user->email, $user->first_name . ' ' . $user->last_name);
328
                    $m->subject(Lang::get('base.mails.welcome') . ' ' . $user->first_name);
329
                });
330
            }
331
332
            // Log the user in
333
            if (!$adminActivation && !$userActivation)
334
            {
335
                $activation = Activation::create($user);
336
337
                if (Activation::complete($user, $activation->code)) {
338
                    Sentinel::login($user, false);
339
340
                    Mail::queue('emails.auth.activated', ['user' => $user], function ($m) use ($user) {
341
                        $m->to($user->email, $user->first_name . ' ' . $user->last_name);
342
                        $m->subject(Lang::get('base.mails.welcome') . ' ' . $user->first_name);
343
                    });
344
                }
345
            }
346
347
            Base::Log('New account registred for ' . $user->username . ' (' . $user->first_name . ' ' . $user->last_name . ') from IP ' . Request::ip() );
348
349
            // Redirect to the home page with success menu
350
            return Redirect::to("login")->with('success', Lang::get('base.auth.signup.success') . $adminActivation ? Lang::get('base.auth.signup.admin') : $userActivation ? Lang::get('base.auth.signup.self') : Lang::get('base.auth.signup.ready'));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Redirect::to('lo...e.auth.signup.ready')); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by jlourenco\base\Controlle...hController::postSignup of type Illuminate\Routing\Redirector.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
351
        } catch (UserExistsException $e) {
0 ignored issues
show
Bug introduced by
The class jlourenco\base\Controllers\UserExistsException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
352
            $this->messageBag->add('email', Lang::get('base.auth.account.already_exists'));
353
        }
354
355
        Base::Log('New account registration attempt from IP ' . Request::ip() );
356
357
        // Ooops.. something went wrong
358
        return Redirect::back()->withInput()->withErrors($this->messageBag);
359
    }
360
361
    /**
362
     * Forgot password form processing page.
363
     *
364
     * @return Redirect
365
     */
366
    public function postForgotPassword()
367
    {
368
        // Declare the rules for the validator
369
        $rules = array(
370
            'email' => 'required|email',
371
        );
372
373
        // Create a new validator instance from our dynamic rules
374
        $validator = Validator::make(Input::all(), $rules);
375
376
        // If validation fails, we'll exit the operation now.
377
        if ($validator->fails()) {
378
            // Ooops.. something went wrong
379
            return Redirect::to(URL::previous())->withInput()->withErrors($validator);
380
        }
381
382
        // Get the user password recovery code
383
        $user = Sentinel::findByCredentials(['email' => Input::get('email')]);
384
385
        if($user)
386
        {
387
            //get reminder for user
388
            $reminder = Reminder::exists($user) ?: Reminder::create($user);
389
390
            // Data to be used on the email view
391
            $data = array(
392
                'user'              => $user,
393
                'forgotPasswordUrl' => URL::route('forgot-password-confirm',[$user->id, $reminder->code]),
394
            );
395
396
            Base::Log('Forgot password request for ' . $user->username . ' (' . $user->first_name . ' ' . $user->last_name . ') from IP ' . Request::ip() );
397
398
            // Send the activation code through email
399
            Mail::queue('emails.auth.forgot-password', $data, function ($m) use ($user) {
400
                $m->to($user->email, $user->first_name . ' ' . $user->last_name);
401
                $m->subject(Lang::get('base.mails.recovery'));
402
            });
403
        }
404
405
        //  Redirect to the forgot password
406
        return Redirect::to(URL::previous())->with('success', Lang::get('base.auth.forgot_password.success'));
407
    }
408
409
    /**
410
     * Forgot Password Confirmation form processing page.
411
     *
412
     * @param number $userId
413
     * @param  string   $passwordResetCode
414
     * @return Redirect
415
     */
416
    public function postForgotPasswordConfirm($userId, $passwordResetCode)
417
    {
418
        // Declare the rules for the form validation
419
        $rules = array(
420
            'password'         => 'required|between:3,32',
421
            'password_confirm' => 'required|same:password'
422
        );
423
424
        // Create a new validator instance from our dynamic rules
425
        $validator = Validator::make(Input::all(), $rules);
426
427
        // If validation fails, we'll exit the operation now.
428
        if ($validator->fails()) {
429
            // Ooops.. something went wrong
430
            return Redirect::route('forgot-password-confirm', compact(['userId','passwordResetCode']))->withInput()->withErrors($validator);
431
        }
432
433
        // Find the user using the password reset code
434
        $user = Sentinel::findById($userId);
435
        if(!$reminder = Reminder::complete($user, $passwordResetCode, Input::get('password')))
436
        {
437
            Base::Log('Forgot password confirm failed for ' . $user->username . ' (' . $user->first_name . ' ' . $user->last_name . ') from IP ' . Request::ip() );
438
439
            // Ooops.. something went wrong
440
            return Redirect::route('login')->with('error', Lang::get('base.auth.forgot_password_confirm.error'));
441
        } else {
442
            // Send the activation code through email
443
            Mail::queue('emails.auth.password-changed', [ 'user' => $user], function ($m) use ($user) {
444
                $m->to($user->email, $user->first_name . ' ' . $user->last_name);
445
                $m->subject(Lang::get('base.mails.password_changed'));
446
            });
447
        }
448
449
        Base::Log('Forgot password confirmed for ' . $user->username . ' (' . $user->first_name . ' ' . $user->last_name . ') from IP ' . Request::ip() );
450
451
        // Password successfully reseted
452
        return Redirect::route('login')->with('success', Lang::get('base.auth.forgot_password_confirm.success'));
453
    }
454
455
}
456