Passed
Push — master ( b8bdbf...0c1875 )
by Rutger
15:13
created

Oauth2ViewClientAction::run()   F

Complexity

Conditions 29
Paths > 20000

Size

Total Lines 135
Code Lines 95

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 870

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 95
c 1
b 0
f 0
dl 0
loc 135
ccs 0
cts 102
cp 0
rs 0
cc 29
nc 73728
nop 1
crap 870

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace rhertogh\Yii2Oauth2Server\controllers\console\client;
4
5
use rhertogh\Yii2Oauth2Server\controllers\console\client\base\Oauth2BaseClientAction;
6
use rhertogh\Yii2Oauth2Server\controllers\console\Oauth2ClientController;
7
use rhertogh\Yii2Oauth2Server\helpers\DiHelper;
8
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ClientScopeInterface;
9
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ScopeInterface;
10
use rhertogh\Yii2Oauth2Server\Oauth2Module;
11
use yii\console\ExitCode;
12
use yii\console\widgets\Table;
13
use yii\helpers\Console;
14
15
/**
16
 * @property Oauth2ClientController $controller
17
 */
18
class Oauth2ViewClientAction extends Oauth2BaseClientAction
19
{
20
    public function run($id)
21
    {
22
        $module = $this->controller->module;
23
        $client = $this->findByIdOrIdentifier($id);
24
25
        $clientInfo = [
26
            'ID' => $client->getPrimaryKey(),
27
            'Identifier' => $client->getIdentifier(),
28
            'Name' => $client->getName(),
29
            'Type' => $client->isConfidential() ? 'Confidential (client secret required)' : 'Public (no client secret required)',
30
            'Redirect URIs' => implode(', ', $client->getRedirectUri()),
0 ignored issues
show
Bug introduced by
It seems like $client->getRedirectUri() can also be of type string; however, parameter $pieces of implode() does only seem to accept array, 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

30
            'Redirect URIs' => implode(', ', /** @scrutinizer ignore-type */ $client->getRedirectUri()),
Loading history...
31
            'Allow Variable URI Query' => $client->isVariableRedirectUriQueryAllowed() ? 'Yes' : 'No',
32
            'Grant Types' => implode(',', Oauth2Module::getGrantTypeIdentifiers($client->getGrantTypes())),
33
            'Allow Generic Scopes' => $client->getAllowGenericScopes() ? 'Yes' : 'No',
34
            'Throw Exception on invalid Scope' => $client->getExceptionOnInvalidScope() !== null
35
                ? ($client->getExceptionOnInvalidScope() ? 'Yes' : 'No')
36
                : '[Not set, using module: ' . ($module->exceptionOnInvalidScope ? 'Yes' : 'No') . ']',
37
            'End Users may authorize client' => $client->endUsersMayAuthorizeClient() ? 'Yes' : 'No',
38
            'User Account Selection' => $client->getUserAccountSelection() !== null
39
                ? Oauth2Module::USER_ACCOUNT_SELECTION_NAMES[$client->getUserAccountSelection()]
40
                : '[Not set, using module: '
41
                    . Oauth2Module::USER_ACCOUNT_SELECTION_NAMES[$module->defaultUserAccountSelection]
42
                    . ']',
43
            'Is Auth Code without PKCE allowed' => $client->isAuthCodeWithoutPkceAllowed() ? 'Yes' : 'No',
44
            'Skip authorization if scope is allowed' => $client->skipAuthorizationIfScopeIsAllowed() ? 'Yes' : 'No',
45
            'Logo URI' => $client->getLogoUri(),
46
            'Terms of Service URI' => $client->getTermsOfServiceUri(),
47
            'Contacts' => $client->getContacts(),
48
        ];
49
50
        if ($client->validateGrantType(Oauth2Module::GRANT_TYPE_IDENTIFIER_CLIENT_CREDENTIALS)) {
51
            $clientInfo['Client Credentials Grant User'] = $client->getClientCredentialsGrantUserId();
52
        }
53
54
        if ($module->enableOpenIdConnect) {
55
            $clientInfo['OIDC allow offline access without consent'] =
56
                $client->getOpenIdConnectAllowOfflineAccessWithoutConsent() ? 'Yes' : 'No';
57
        }
58
59
        $clientInfo['Enabled'] = $client->isEnabled() ? 'Yes' : 'No';
60
61
        $this->controller->stdout(Table::widget([
62
            'rows' => array_map(fn($property) => [$property, $clientInfo[$property]], array_keys($clientInfo)),
63
        ]));
64
65
        $scopes = $client->getAllowedScopes(true);
66
67
        if ($this->controller->verbose) {
68
            $this->controller->stdout(PHP_EOL);
69
70
            usort(
71
                $scopes,
72
                fn(Oauth2ScopeInterface $a, Oauth2ScopeInterface $b) => strcmp($a->getIdentifier(), $b->getIdentifier())
73
            );
74
75
            $scopeInfo = [];
76
            $showInheritedInfo = false;
77
            foreach ($scopes as $scope) {
78
                $clientScope = $scope->getClientScope($client->getPrimaryKey());
79
                $appliedByDefault = null;
80
                $requiredOnAuthorization = null;
81
                if ($clientScope) {
82
                    if ($clientScope->getAppliedByDefault() !== null) {
83
                        $appliedByDefault = $this->generateAppliedByDefaultLabel($clientScope->getAppliedByDefault());
84
                    }
85
                    if ($clientScope->getRequiredOnAuthorization() !== null) {
86
                        $requiredOnAuthorization = ($clientScope->getRequiredOnAuthorization() ? 'Yes' : 'No');
87
                    }
88
                }
89
                if (empty($appliedByDefault)) {
90
                    $appliedByDefault = $this->generateAppliedByDefaultLabel($scope->getAppliedByDefault()) . '¹';
91
                    $showInheritedInfo = true;
92
                }
93
                if (empty($requiredOnAuthorization)) {
94
                    $requiredOnAuthorization = ($scope->getRequiredOnAuthorization() ? 'Yes' : 'No') . '¹';
95
                    $showInheritedInfo = true;
96
                }
97
98
                $scopeInfo[] = [
99
                    $scope->getIdentifier(),
100
                    $appliedByDefault,
101
                    $requiredOnAuthorization,
102
                    $clientScope ? 'Client' : 'Generic',
103
                ];
104
            }
105
106
            $this->controller->stdout(count($scopes) . ' scope(s) configured for "'
107
                . $client->getIdentifier() . '" client using '
108
                . ($client->getAllowGenericScopes()
109
                    ? 'generic mode (scopes don\'t need to be explicitly configured for this client)'
110
                    : 'strict mode (scopes need to be explicitly configured for this client)'
111
                )
112
                . '.' . PHP_EOL);
113
114
            $this->controller->stdout(Table::widget([
115
                'headers' => [
116
                    'Scope',
117
                    'Applied by default',
118
                    'Required on authorization',
119
                    'Origin',
120
                ],
121
                'rows' => $scopeInfo,
122
            ]));
123
124
            if ($showInheritedInfo) {
125
                $this->controller->stdout('¹ Config inherited from scope.'. PHP_EOL);
0 ignored issues
show
Coding Style introduced by
Expected at least 1 space before "."; 0 found
Loading history...
126
            }
127
128
            /** @var Oauth2ClientScopeInterface $clientScopeClass */
129
            $clientScopeClass = DiHelper::getValidatedClassName(Oauth2ClientScopeInterface::class);
130
            $clientScopeTableName = $clientScopeClass::tableName();
131
            $disabledClientScopes = $clientScopeClass::find()
132
                ->innerJoinWith('scope')
133
                ->andWhere([$clientScopeTableName . '.client_id' => $client->getPrimaryKey()])
134
                ->andWhere([$clientScopeTableName . '.enabled' => false])
135
                ->select('identifier')
136
                ->column();
137
138
            if ($disabledClientScopes) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $disabledClientScopes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
139
                $this->controller->stdout('Note: there is/are ' . count($disabledClientScopes)
140
                    . ' scope(s) explicitly disabled for this client: ' . implode(', ', $disabledClientScopes)
141
                    . '.' . PHP_EOL);
142
            }
143
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
144
        } else {
145
            $this->controller->stdout(count($scopes) . ' scope(s) configured for "'
146
                . $client->getIdentifier() . '" client.' . PHP_EOL);
147
148
            if ($scopes) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $scopes of type rhertogh\Yii2Oauth2Serve...\Oauth2ScopeInterface[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
149
                $this->controller->stdout('Hint: use `--verbose` to show scope configuration.'
150
                    . PHP_EOL, Console::ITALIC);
151
            }
152
        }
153
154
        return ExitCode::OK;
155
    }
156
157
    protected function generateAppliedByDefaultLabel($appliedByDefault)
158
    {
159
        switch ($appliedByDefault) {
160
            case Oauth2ScopeInterface::APPLIED_BY_DEFAULT_NO:
161
                return 'No';
162
            case Oauth2ScopeInterface::APPLIED_BY_DEFAULT_CONFIRM:
163
                return 'Yes (with user confirm)';
164
            case Oauth2ScopeInterface::APPLIED_BY_DEFAULT_AUTOMATICALLY:
165
                return 'Yes (w/o user confirm)';
166
            case Oauth2ScopeInterface::APPLIED_BY_DEFAULT_IF_REQUESTED:
167
                return 'Yes (upon client request w/o user confirm)';
168
        }
169
170
        throw new \LogicException('Unknown "applied by default" value: ' . $appliedByDefault);
171
    }
172
}
173