Completed
Pull Request — master (#33)
by Fèvre
02:45
created

SocialiteController::createUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
rs 9.4285
cc 1
eloc 6
nc 1
nop 1
1
<?php
2
namespace Xetaravel\Http\Controllers\Auth;
3
4
use Exception;
5
use Illuminate\Auth\Events\Registered;
6
use Illuminate\Http\RedirectResponse;
7
use Illuminate\Http\Request;
8
use Illuminate\Foundation\Auth\RedirectsUsers;
9
use Illuminate\Support\Facades\Auth;
10
use Illuminate\Support\Str;
11
use Illuminate\View\View;
12
use Laravel\Socialite\Facades\Socialite;
13
use Laravel\Socialite\Two\User as ProviderUser;
14
use Symfony\Component\HttpFoundation\RedirectResponse as RedirectResponseSF;
15
use Xetaravel\Events\RegisterEvent;
16
use Xetaravel\Http\Controllers\Controller;
17
use Xetaravel\Models\User;
18
use Xetaravel\Models\Repositories\UserRepository;
19
use Xetaravel\Models\Role;
20
use Xetaravel\Models\Validators\UserValidator;
21
22
class SocialiteController extends Controller
23
{
24
    use RedirectsUsers;
25
26
    /**
27
     * Where to redirect users after login.
28
     *
29
     * @var string
30
     */
31
    protected $redirectTo = '/';
32
33
    /**
34
     * The driver used.
35
     *
36
     * @var string
37
     */
38
    protected $driver;
39
40
    /**
41
     * Show the registration form.
42
     *
43
     * @param \Illuminate\Http\Request $request The request object.
44
     * @param string $driver The driver used.
45
     *
46
     * @return \Illuminate\View\View
47
     */
48
    public function showRegistrationForm(Request $request, string $driver): View
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $driver is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
49
    {
50
        return view('Auth.socialite');
51
    }
52
53
    /**
54
     * Register an user that has been forced to modify his email or
55
     * username due to a conflit with the database.
56
     *
57
     * @param \Illuminate\Http\Request $request The request object.
58
     * @param string $driver The driver used.
59
     *
60
     * @return \Illuminate\Http\RedirectResponse
61
     */
62
    public function register(Request $request, string $driver): RedirectResponse
63
    {
64
        $this->driver = $driver;
65
        $validator = UserValidator::createWithProvider($request->all());
66
67
        if ($validator->fails()) {
68
            return redirect()
69
                ->back()
70
                ->withErrors($validator)
71
                ->withInput($request->all());
72
        }
73
        $user = Socialite::driver($driver)->userFromToken($request->session()->get('socialite.token'));
74
75
        $user->nickname = $request->input('username');
76
        $user->email = $request->input('email');
77
78
        $user = $this->registered($user);
79
80
        $request->session()->forget('socialite');
0 ignored issues
show
Bug introduced by
The method forget() does not seem to exist on object<Symfony\Component...ssion\SessionInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
81
82
        return $this->login($request, $user);
83
    }
84
85
    /**
86
     * Redirect the user to the Provider authentication page.
87
     *
88
     * @param \Illuminate\Http\Request $request The request object.
89
     * @param string $driver The driver used.
90
     * @param string $type The type of callback. (Either `login` or `register`)
91
     *
92
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
93
     */
94
    public function redirectToProvider(Request $request, string $driver, string $type): RedirectResponseSF
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
95
    {
96
        return Socialite::driver($driver)
97
                ->redirectUrl(route('auth.driver.type.callback', ['driver' => $driver, 'type' => $type]))
98
                ->redirect();
99
    }
100
101
    /**
102
     * Obtain the user information from the Provider and process to the
103
     * registration or login regarding to the type of callback.
104
     *
105
     * @param \Illuminate\Http\Request $request The request object.
106
     * @param string $driver The driver used.
107
     * @param string $type The type of callback. (Either `login` or `register`)
108
     *
109
     * @return \Illuminate\Http\Response
0 ignored issues
show
Documentation introduced by
Should the return type not be RedirectResponse?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
110
     */
111
    public function handleProviderCallback(Request $request, string $driver, string $type): RedirectResponse
112
    {
113
        $this->driver = $driver;
114
115
        try {
116
            $user = Socialite::driver($driver)->user();
117
        } catch (Exception $e) {
118
            $redirect = 'users.auth.login';
119
120
            if ($type == 'register') {
121
                $redirect = 'users.auth.register';
122
            }
123
            $driver = Str::title($driver);
124
125
            return redirect()
126
                ->route($redirect)
127
                ->with('danger', "An error occurred while getting your information from {$driver} !");
128
        }
129
130
        if ($type == 'register') {
131
            $user = $this->handleRegister($request, $user);
132
133
            if (!$user instanceof User) {
134
                return $user;
135
            }
136
137
            return $this->login($request, $user);
138
        }
139
140
        if (!$user = User::where($driver . '_id', $user->id)->first()) {
141
            return redirect()
142
                ->route('users.auth.login')
143
                ->with('danger', "This user is not registered, register it or try another login method.");
144
        }
145
146
        return $this->login($request, $user);
147
    }
148
149
    /**
150
     * Login the user and trigger the authenticated function.
151
     *
152
     * @param \Illuminate\Http\Request $request The request object.
153
     * @param \Xetaravel\Models\User $user The user to login.
154
     *
155
     * @return \Illuminate\Http\RedirectResponse
156
     */
157
    protected function login(Request $request, User $user): RedirectResponse
158
    {
159
        Auth::login($user, true);
160
161
        $this->authenticated($request, $user);
162
163
        return redirect()->intended($this->redirectPath());
164
    }
165
166
    /**
167
     * Handle the registration.
168
     *
169
     * @param \Illuminate\Http\Request $request The request object.
170
     * @param \Laravel\Socialite\Two\User $user The user to register.
171
     *
172
     * @return \Illuminate\Http\RedirectResponse|\Xetaravel\Models\User
173
     */
174
    protected function handleRegister(Request $request, ProviderUser $user)
175
    {
176
        $driver = $this->driver;
177
178
        if (User::where($driver . '_id', $user->id)->first()) {
179
            $driver = Str::title($driver);
180
181
            return redirect()
182
                ->route('users.auth.login')
183
                ->with('danger', "This {$driver} user is already registered !");
184
        }
185
186
        $validator = UserValidator::createWithProvider([
187
            'username' => $user->nickname,
188
            'email' => $user->email
189
        ]);
190
191
        if ($validator->fails()) {
192
            $request->session()->put('socialite', [
0 ignored issues
show
Bug introduced by
The method put() does not seem to exist on object<Symfony\Component...ssion\SessionInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
193
                'driver' => $driver,
194
                'token' => $user->token
195
            ]);
196
197
            return redirect()
198
                ->route('auth.driver.register', ['driver' => $driver])
199
                ->withErrors($validator)
200
                ->withInput([
201
                    'username' => $user->nickname,
202
                    'email' => $user->email
203
                ]);
204
        }
205
206
        $user = $this->registered($user);
207
208
        return $user;
209
    }
210
211
    /**
212
     * Create the user.
213
     *
214
     * @param \Laravel\Socialite\Two\User $user The user to create.
215
     *
216
     * @return \Xetaravel\Models\User
217
     */
218
    protected function createUser(ProviderUser $user)
219
    {
220
        return UserRepository::create(
221
            [
222
                'username' => $user->nickname,
223
                'email' => $user->email
224
            ],
225
            [
226
                $this->driver . '_id' => $user->id
227
            ],
228
            true
229
        );
230
    }
231
232
    /**
233
     * The user has been authenticated.
234
     *
235
     * @param \Illuminate\Http\Request $request The request object.
236
     * @param \Xetaravel\Models\User $user The user that has been logged in.
237
     *
238
     * @return void
239
     */
240 View Code Duplication
    protected function authenticated(Request $request, $user)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
241
    {
242
        event(new RegisterEvent($user));
243
244
        $request->session()->flash(
0 ignored issues
show
Bug introduced by
The method flash() does not seem to exist on object<Symfony\Component...ssion\SessionInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
245
            'success',
246
            'Welcome back <strong>' . e($user->username) . '</strong>! You\'re successfully connected !'
247
        );
248
    }
249
250
    /**
251
     * The user has been registered.
252
     *
253
     * @param \Laravel\Socialite\Two\User $user The user that has been registered.
254
     *
255
     * @return \Xetaravel\Models\User
256
     */
257
    protected function registered(ProviderUser $user): User
258
    {
259
        event(new Registered($user = $this->createUser($user)));
260
261
        $role = Role::where('slug', 'user')->first();
262
        $user->attachRole($role);
263
264
        $user->clearMediaCollection('avatar');
265
        $user->addMedia(resource_path('assets/images/avatar.png'))
266
            ->preservingOriginal()
267
            ->setName(substr(md5($user->username), 0, 10))
268
            ->setFileName(substr(md5($user->username), 0, 10) . '.png')
269
            ->toMediaCollection('avatar');
270
271
        return $user;
272
    }
273
}
274