LoginService::createToken()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 3
cp 0
crap 2
rs 10
1
<?php
2
3
namespace App\Services;
4
5
use App\Interfaces\LoginServiceInterface;
6
use App\Models\User;
7
use Illuminate\Support\Arr;
8
use Laravel\Passport\Client;
9
use Laravel\Passport\ClientRepository;
10
use Laravel\Socialite\Contracts\User as UserContract;
11
use Laravel\Socialite\Facades\Socialite;
12
use Symfony\Component\HttpFoundation\RedirectResponse;
13
14
class LoginService implements LoginServiceInterface
15
{
16
    /**
17
     * Laravel Passport Client Repository.
18
     *
19
     * @var ClientRepository
20
     */
21
    private ClientRepository $clientRepository;
22
23
    /**
24
     * LoginService constructor.
25
     *
26
     * @param  ClientRepository  $repository
27
     */
28
    public function __construct(ClientRepository $repository)
29
    {
30
        $this->clientRepository = $repository;
31
    }
32
33
    /**
34
     * Redirect to OAuth authorization service URL.
35
     *
36
     * @param  string  $provider
37
     * @return RedirectResponse
38
     */
39
    public function redirect(string $provider): RedirectResponse
40
    {
41
        return Socialite::driver($provider)
42
            // Define custom scopes if needed under "services.{provider}"
43
            ->scopes(config("services.{$provider}.scopes") ?? '*')
0 ignored issues
show
Bug introduced by
The method scopes() does not exist on Laravel\Socialite\Contracts\Provider. It seems like you code against a sub-type of Laravel\Socialite\Contracts\Provider such as Laravel\Socialite\Two\AbstractProvider. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

43
            ->/** @scrutinizer ignore-call */ scopes(config("services.{$provider}.scopes") ?? '*')
Loading history...
44
            ->redirect();
45
    }
46
47
    /**
48
     * Handle callback.
49
     *
50
     * @param  string  $provider
51
     * @param  array  $clientInfo
52
     * @return User
53
     */
54
    public function callback(string $provider, array $clientInfo): User
55
    {
56
        $profile = Socialite::driver($provider)->user();
57
58
        return $this->user($provider, $profile);
59
    }
60
61
    /**
62
     * Handle callback.
63
     *
64
     * @param  User  $user
65
     * @return string
66
     */
67
    public function createToken(User $user): string
68
    {
69
        $tokenName = config('app.name').' Token - '.now();
70
71
        return $user->createToken($tokenName)->accessToken;
72
    }
73
74
    /**
75
     * Create a new user or update existing one.
76
     *
77
     * @param  string  $provider
78
     * @param  UserContract  $userContract
79
     * @return User
80
     */
81
    public function user(string $provider, UserContract $userContract): User
82
    {
83
        return User::updateOrCreate([
84
            'provider_name'  => $provider,                       // GitHub, LinkedIn, Google, Apple
85
            'provider_id'    => $userContract->getId(),          // unsignedBigInteger, uuid
86
        ], [
87
            'name'           => $userContract->getName() ?? $userContract->getNickname(),
88
            /**
89
             * E-mails, tokens and profile will be synced.
90
             * E-mail is for e-mail notifications.
91
             * Tokens for retrieve data from authorization
92
             * server such as GitHub, Twitter or Google.
93
             */
94
            'email'          => $userContract->getEmail(),       // OAuth provider e-mail address
95
            'notify_via'     => ['broadcast'],                   // Default notification preference
96
            'access_token'   => $userContract->token,            // TOKEN
0 ignored issues
show
Bug introduced by
Accessing token on the interface Laravel\Socialite\Contracts\User suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
97
            'refresh_token'  => $userContract->refreshToken,     // TOKEN - some providers have it
0 ignored issues
show
Bug introduced by
Accessing refreshToken on the interface Laravel\Socialite\Contracts\User suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
98
            'profile'        => $userContract->user,             // JSON profile data
0 ignored issues
show
Bug introduced by
Accessing user on the interface Laravel\Socialite\Contracts\User suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
99
        ]);
100
    }
101
102
    /**
103
     * Get or create client for user.
104
     *
105
     * @param  User  $user
106
     * @param  array  $clientInfo
107
     * @return Client
108
     */
109
    public function client(User $user, array $clientInfo): Client
110
    {
111
        $find = $this->clientRepository->forUser($user->id);
112
113
        return $find->first() ?? $this->clientRepository->create(
114
                $user->id,
115
                "{$user->provider_name}-{$user->provider_id}",
0 ignored issues
show
Bug Best Practice introduced by
The property provider_name does not exist on App\Models\User. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property provider_id does not exist on App\Models\User. Since you implemented __get, consider adding a @property annotation.
Loading history...
116
                Arr::get($clientInfo, 'redirect_uri'),
117
                $user->provider_name,
0 ignored issues
show
Bug introduced by
It seems like $user->provider_name can also be of type Illuminate\Database\Eloq...uent\Relations\Relation and Illuminate\Database\Eloquent\Relations\Relation; however, parameter $provider of Laravel\Passport\ClientRepository::create() does only seem to accept null|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

117
                /** @scrutinizer ignore-type */ $user->provider_name,
Loading history...
118
                false,
119
                false,
120
                false
121
            );
122
    }
123
}
124