Test Failed
Push — issue#666 ( f5ce0d...ce3976 )
by Guilherme
28:08
created

ClientCredentials::getClient()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 3

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 3
eloc 14
nc 4
nop 1
dl 0
loc 25
ccs 13
cts 13
cp 1
crap 3
rs 8.8571
c 1
b 1
f 0
1
<?php
2
/**
3
 * This file is part of the login-cidadao project or it's bundles.
4
 *
5
 * (c) Guilherme Donato <guilhermednt on github>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace LoginCidadao\OpenIDBundle\Storage;
12
13
use Doctrine\ORM\EntityManagerInterface;
14
use LoginCidadao\OAuthBundle\Entity\ClientRepository;
15
use LoginCidadao\OAuthBundle\Model\ClientInterface;
16
use LoginCidadao\RemoteClaimsBundle\Entity\RemoteClaim;
17
use LoginCidadao\RemoteClaimsBundle\Entity\RemoteClaimRepository;
18
use LoginCidadao\RemoteClaimsBundle\Model\RemoteClaimInterface;
19
use OAuth2\ServerBundle\Storage\ClientCredentials as BaseClass;
20
21
class ClientCredentials extends BaseClass
22
{
23
    private $em;
24
25 9
    public function __construct(EntityManagerInterface $EntityManager)
0 ignored issues
show
Coding Style introduced by
$EntityManager does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
Coding Style Naming introduced by
The parameter $EntityManager is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
26
    {
27 9
        $this->em = $EntityManager;
0 ignored issues
show
Coding Style introduced by
$EntityManager does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
28 9
    }
29
30
    /**
31
     * Make sure that the client credentials is valid.
32
     *
33
     * @param $client_id
34
     * Client identifier to be check with.
35
     * @param $client_secret
36
     * (optional) If a secret is required, check that they've given the right one.
37
     *
38
     * @return TRUE if the client credentials are valid, and MUST return FALSE if it isn't.
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean?

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...
39
     * @endcode
40
     *
41
     * @see http://tools.ietf.org/html/rfc6749#section-3.1
42
     *
43
     * @ingroup oauth2_section_3
44
     */
45 3
    public function checkClientCredentials($client_id, $client_secret = null)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $client_id is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $client_secret is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
46
    {
47 3
        $client = $this->getClient($client_id);
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
48
49
        // If client exists check secret
50 3
        if ($client) {
51 2
            return $client->getClientSecret() === $client_secret;
0 ignored issues
show
Coding Style introduced by
$client_secret does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
52
        }
53
54 1
        return false;
55
    }
56
57
    /**
58
     * Get client details corresponding client_id.
59
     *
60
     * OAuth says we should store request URIs for each registered client.
61
     * Implement this function to grab the stored URI for a given client id.
62
     *
63
     * @param $client_id
64
     * Client identifier to be check with.
65
     *
66
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be false|array<string,string|array>?

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...
67
     *               Client details. The only mandatory key in the array is "redirect_uri".
68
     *               This function MUST return FALSE if the given client does not exist or is
69
     *               invalid. "redirect_uri" can be space-delimited to allow for multiple valid uris.
70
     * @code
71
     *               return array(
72
     *               "redirect_uri" => REDIRECT_URI,      // REQUIRED redirect_uri registered for the client
73
     *               "client_id"    => CLIENT_ID,         // OPTIONAL the client id
74
     *               "grant_types"  => GRANT_TYPES,       // OPTIONAL an array of restricted grant types
75
     *               );
76
     * @endcode
77
     *
78
     * @ingroup oauth2_section_4
79
     */
80 2
    public function getClientDetails($client_id)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $client_id is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
81
    {
82 2
        $client = $this->getClient($client_id);
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
83
84 2
        if (!$client) {
85 1
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface OAuth2\Storage\ClientInterface::getClientDetails of type array.

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...
86
        }
87
88
        return [
89 1
            'redirect_uri' => implode(' ', $client->getRedirectUris()),
90 1
            'client_id' => $client->getPublicId(),
91 1
            'grant_types' => $client->getAllowedGrantTypes(),
92
        ];
93
    }
94
95
    /**
96
     * Determine if the client is a "public" client, and therefore
97
     * does not require passing credentials for certain grant types
98
     *
99
     * @param $client_id
100
     * Client identifier to be check with.
101
     *
102
     * @return TRUE if the client is public, and FALSE if it isn't.
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean?

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...
103
     * @endcode
104
     *
105
     * @see http://tools.ietf.org/html/rfc6749#section-2.3
106
     * @see https://github.com/bshaffer/oauth2-server-php/issues/257
107
     *
108
     * @ingroup oauth2_section_2
109
     */
110 2
    public function isPublicClient($client_id)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $client_id is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
111
    {
112 2
        $client = $this->getClient($client_id);
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
113
114 2
        if (!$client) {
115 1
            return false;
116
        }
117
118 1
        $secret = $client->getClientSecret();
119
120 1
        return empty($secret);
121
    }
122
123
    /**
124
     * Get the scope associated with this client
125
     *
126
     * @return string the space-delineated scope list for the specified client_id
0 ignored issues
show
Documentation introduced by
Should the return type not be false|string?

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...
127
     */
128 2
    public function getClientScope($client_id)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $client_id is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
129
    {
130 2
        $client = $this->getClient($client_id);
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
131
132 2
        if (!$client instanceof ClientInterface) {
133 1
            return false;
134
        }
135
136
        /*
137
         * TODO: performance issue: if there are too many Remote Claims listing all of them might be an issue
138
         * To solve that we could add a listener to an Authorization event that would add the current Client into a list
139
         * users, then the
140
         */
141 1
        $remoteClaims = $this->getRemoteClaimsTags($this->getAllRemoteClaims());
142
        $allowedScopes = array_merge($client->getAllowedScopes(), $remoteClaims);
143
144
        return implode(' ', $allowedScopes);
145
    }
146
147
    /**
148
     * @param $client_id mixed
149
     * @return null|ClientInterface
150
     */
151 9
    private function getClient($client_id)
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
Coding Style Naming introduced by
The parameter $client_id is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
152
    {
153 9
        $randomId = null;
154 9
        if (strstr($client_id, '_') !== false) {
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
155 7
            $parts = explode('_', $client_id);
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
156 7
            $client_id = $parts[0];
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
157 7
            $randomId = $parts[1];
158
        }
159
160
        /** @var ClientRepository $repo */
161 9
        $repo = $this->em->getRepository('LoginCidadaoOAuthBundle:Client');
162
163 9
        if ($randomId) {
164
            /** @var ClientInterface $client */
165 7
            $client = $repo->findOneBy([
166 7
                'id' => $client_id,
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
167 7
                'randomId' => $randomId,
168
            ]);
169
        } else {
170
            /** @var ClientInterface $client */
171 2
            $client = $repo->find($client_id);
0 ignored issues
show
Coding Style introduced by
$client_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
172
        }
173
174 9
        return $client;
175
    }
176
177
    /**
178
     * @param ClientInterface $client
179
     * @return array|RemoteClaimInterface[]
180
     */
181
    private function getRemoteClaims(ClientInterface $client)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
182
    {
183
        /** @var RemoteClaimRepository $repo */
184
        $repo = $this->em->getRepository('LoginCidadaoRemoteClaimsBundle:RemoteClaim');
185
186
        $remoteClaims = $repo->findByClient($client);
187
188
        return $remoteClaims;
189
    }
190
191
    /**
192
     * @return array|RemoteClaimInterface[]
193
     */
194 1
    private function getAllRemoteClaims()
195
    {
196
        /** @var RemoteClaimRepository $repo */
197 1
        $repo = $this->em->getRepository('LoginCidadaoRemoteClaimsBundle:RemoteClaim');
198
199
        $remoteClaims = $repo->findAll();
200
201
        return $remoteClaims;
202
    }
203
204
    private function getRemoteClaimsTags(array $remoteClaims)
205
    {
206
        if (count($remoteClaims) > 0) {
207
            return array_map(function (RemoteClaimInterface $claim) {
208
                return $claim->getName();
209
            }, $remoteClaims);
210
        }
211
212
        return [];
213
    }
214
}
215