Completed
Push — master ( 4c949c...532c30 )
by Julien
11:23
created

AuthController::findOrCreateUser()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 13
rs 9.4286
cc 2
eloc 8
nc 2
nop 1
1
<?php
2
3
namespace App\Http\Controllers\Auth;
4
5
use App\Http\Controllers\Controller;
6
use App\Http\Models\Administrators;
7
use App\User;
8
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
9
use Illuminate\Foundation\Auth\ThrottlesLogins;
10
use Illuminate\Http\Request;
11
use Illuminate\Support\Facades\Auth;
12
use Illuminate\Support\Facades\Redirect;
13
use Laravel\Socialite\Facades\Socialite;
14
use Validator;
15
16
class AuthController extends Controller
17
{
18
    /**
19
     * Redirections (surcharge des valeurs par défaut de Laravel).
20
     */
21
22
    /**
23
     * @var string
24
     */
25
    protected $loginPath = '/auth/login';
26
27
    /**
28
     * @var string
29
     */
30
    protected $redirectPath = '/admin/';
31
32
    /**
33
     * @var string
34
     */
35
    protected $redirectAfterLogout = '/auth/login/';
36
37
    /**
38
     * @var string
39
     */
40
    protected $redirectTo = '/auth/login';
41
42
    /*
43
    |--------------------------------------------------------------------------
44
    | Registration & Login Controller
45
    |--------------------------------------------------------------------------
46
    |
47
    | This controller handles the registration of new users, as well as the
48
    | authentication of existing users. By default, this controller uses
49
    | a simple trait to add these behaviors. Why don't you explore it?
50
    |
51
    */
52
53
    use AuthenticatesAndRegistersUsers, ThrottlesLogins;
54
55
    /**
56
     * Create a new authentication controller instance.
57
     *
58
     * La construction de mon controlleur
59
     * agit sur toutes les methodes qui seront appelé dans ce constructeur
60
     */
61
    public function __construct()
62
    {
63
        //exit('coucou');
64
65
        // application du middleware guest
66
        $this->middleware('guest', ['except' => 'getLogout']);
67
    }
68
69
    /**
70
     * Get a validator for an incoming registration request.
71
     *
72
     * @param array $data
73
     *
74
     * @return \Illuminate\Contracts\Validation\Validator
75
     */
76
    protected function validator(array $data)
77
    {
78
        return Validator::make($data, [
79
            'name'     => 'required|max:255',
80
            'email'    => 'required|email|max:255|unique:administrators',
81
            'password' => 'required|confirmed|min:6',
82
        ]);
83
    }
84
85
    /**
86
     * Create a new user instance after a valid registration.
87
     *
88
     * @param array $data
89
     *
90
     * @return User
91
     */
92
    protected function create(array $data)
93
    {
94
        return Administrators::create([
95
            'name'     => $data['name'],
96
            'email'    => $data['email'],
97
            'password' => bcrypt($data['password']),
98
        ]);
99
    }
100
101
    /**
102
     * Get Page on login.
103
     *
104
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
105
     */
106
    public function getLogin()
107
    {
108
        return view('Auth/login', ['errors' => []]);
109
    }
110
111
    /**
112
     * Handle a login request to the application.
113
     *
114
     * @param \Illuminate\Http\Request $request
115
     *
116
     * @return \Illuminate\Http\Response
117
     */
118
    public function postLogin(Request $request)
119
    {
120
        $this->validate($request, [
121
            $this->loginUsername() => 'required', 'password' => 'required',
122
        ]);
123
124
        // If the class is using the ThrottlesLogins trait, we can automatically throttle
125
        // the login attempts for this application. We'll key this by the username and
126
        // the IP address of the client making these requests into this application.
127
        $throttles = $this->isUsingThrottlesLoginsTrait();
128
129
        if ($throttles && $this->hasTooManyLoginAttempts($request)) {
130
            return $this->sendLockoutResponse($request);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->sendLockoutResponse($request); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by App\Http\Controllers\Aut...thController::postLogin of type Illuminate\Http\Response.

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...
131
        }
132
133
        $this->getCredentials($request);
134
135
        //override AUth atempt() here...
136
        if (Auth::attempt([
137
            'email' => $request->email,
138
            'password' => $request->password,
139
            'active' => 1,
140
        ])) {
141
            return $this->handleUserWasAuthenticated($request, $throttles);
142
        }
143
144
        // If the login attempt was unsuccessful we will increment the number of attempts
145
        // to login and redirect the user back to the login form. Of course, when this
146
        // user surpasses their maximum number of attempts they will get locked out.
147
        if ($throttles) {
148
            $this->incrementLoginAttempts($request);
149
        }
150
151
        return redirect($this->loginPath())
0 ignored issues
show
Bug Best Practice introduced by
The return type of return redirect($this->l...FailedLoginMessage())); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by App\Http\Controllers\Aut...thController::postLogin of type Illuminate\Http\Response.

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...
152
            ->withInput($request->only($this->loginUsername(), 'remember'))
153
            ->withErrors([
154
                $this->loginUsername() => $this->getFailedLoginMessage(),
155
            ]);
156
    }
157
158
    /**
159
     * Redirect the user to the GitHub authentication page.
160
     *
161
     * @return Response
162
     */
163
    public function redirectToProvider()
164
    {
165
        return Socialite::driver('facebook')->redirect();
166
    }
167
168
    /**
169
     * Obtain the user information from GitHub.
170
     *
171
     * @return Response
172
     */
173
    public function handleProviderCallback()
174
    {
175
        try {
176
            $user = Socialite::driver('facebook')->user();
177
        } catch (\Exception $e) {
178
            return Redirect::to('auth/facebook');
179
        }
180
181
        $authUser = $this->findOrCreateUser($user);
182
183
        Auth::login($authUser, true);
184
185
        return Redirect::to('home');
186
    }
187
188
    /**
189
     * Return user if exists; create and return if doesn't.
190
     *
191
     * @param $githubUser
192
     *
193
     * @return User
194
     */
195
    private function findOrCreateUser($githubUser)
196
    {
197
        if ($authUser = User::where('github_id', $githubUser->id)->first()) {
198
            return $authUser;
199
        }
200
201
        return User::create([
202
            'name'      => $githubUser->name,
203
            'email'     => $githubUser->email,
204
            'github_id' => $githubUser->id,
205
            'avatar'    => $githubUser->avatar,
206
        ]);
207
    }
208
}
209