Oauth2ViewClientAction::run()   F
last analyzed

Complexity

Conditions 29
Paths > 20000

Size

Total Lines 136
Code Lines 97

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 870

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 97
c 1
b 0
f 0
dl 0
loc 136
ccs 0
cts 104
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\controllers\console\client\Oauth2ViewClientActionInterface;
9
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ClientScopeInterface;
10
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ScopeInterface;
11
use rhertogh\Yii2Oauth2Server\Oauth2Module;
12
use Throwable;
13
use yii\base\InvalidConfigException;
14
use yii\console\Exception as ConsoleException;
15
use yii\console\ExitCode;
16
use yii\console\widgets\Table;
17
use yii\helpers\Console;
18
19
/**
20
 * @property Oauth2ClientController $controller
21
 */
22
class Oauth2ViewClientAction extends Oauth2BaseClientAction implements Oauth2ViewClientActionInterface
23
{
24
    /**
25
     * View configuration details of an Oauth2 Client.
26
     *
27
     * @throws Throwable
28
     * @throws InvalidConfigException
29
     * @throws ConsoleException
30
     */
31
    public function run($id)
32
    {
33
        $module = $this->controller->module;
34
        $client = $this->findByIdOrIdentifier($id);
35
36
        $clientInfo = [
37
            'ID' => $client->getPrimaryKey(),
38
            'Identifier' => $client->getIdentifier(),
39
            'Name' => $client->getName(),
40
            'Type' => $client->isConfidential()
41
                ? 'Confidential (client secret required)'
42
                : 'Public (no client secret required)',
43
            'Redirect URIs' => implode(', ', $client->getRedirectUri()),
44
            'Allow Variable URI Query' => $client->isVariableRedirectUriQueryAllowed() ? 'Yes' : 'No',
45
            'Grant Types' => implode(',', Oauth2Module::getGrantTypeIdentifiers($client->getGrantTypes())),
46
            'Allow Generic Scopes' => $client->getAllowGenericScopes() ? 'Yes' : 'No',
47
            'Throw Exception on invalid Scope' => $client->getExceptionOnInvalidScope() !== null
48
                ? ($client->getExceptionOnInvalidScope() ? 'Yes' : 'No')
49
                : '[Not set, using module: ' . ($module->exceptionOnInvalidScope ? 'Yes' : 'No') . ']',
50
            'End Users may authorize client' => $client->endUsersMayAuthorizeClient() ? 'Yes' : 'No',
51
            'User Account Selection' => $client->getUserAccountSelection() !== null
52
                ? Oauth2Module::USER_ACCOUNT_SELECTION_NAMES[$client->getUserAccountSelection()]
53
                : '[Not set, using module: '
54
                    . Oauth2Module::USER_ACCOUNT_SELECTION_NAMES[$module->defaultUserAccountSelection]
55
                    . ']',
56
            'Is Auth Code without PKCE allowed' => $client->isAuthCodeWithoutPkceAllowed() ? 'Yes' : 'No',
57
            'Skip authorization if scope is allowed' => $client->skipAuthorizationIfScopeIsAllowed() ? 'Yes' : 'No',
58
            'Logo URI' => $client->getLogoUri(),
59
            'Terms of Service URI' => $client->getTermsOfServiceUri(),
60
            'Contacts' => $client->getContacts(),
61
        ];
62
63
        if ($client->validateGrantType(Oauth2Module::GRANT_TYPE_IDENTIFIER_CLIENT_CREDENTIALS)) {
64
            $clientInfo['Client Credentials Grant User'] = $client->getClientCredentialsGrantUserId();
65
        }
66
67
        if ($module->enableOpenIdConnect) {
68
            $clientInfo['OIDC allow offline access without consent'] =
69
                $client->getOpenIdConnectAllowOfflineAccessWithoutConsent() ? 'Yes' : 'No';
70
        }
71
72
        $clientInfo['Enabled'] = $client->isEnabled() ? 'Yes' : 'No';
73
74
        $this->controller->stdout(Table::widget([
75
            'rows' => array_map(fn($property) => [$property, $clientInfo[$property]], array_keys($clientInfo)),
76
        ]));
77
78
        $scopes = $client->getAllowedScopes(true);
79
80
        if ($this->controller->verbose) {
81
            $this->controller->stdout(PHP_EOL);
82
83
            usort(
84
                $scopes,
85
                fn(Oauth2ScopeInterface $a, Oauth2ScopeInterface $b) => strcmp($a->getIdentifier(), $b->getIdentifier())
86
            );
87
88
            $scopeInfo = [];
89
            $showInheritedInfo = false;
90
            foreach ($scopes as $scope) {
91
                $clientScope = $scope->getClientScope($client->getPrimaryKey());
92
                $appliedByDefault = null;
93
                $requiredOnAuthorization = null;
94
                if ($clientScope) {
95
                    if ($clientScope->getAppliedByDefault() !== null) {
96
                        $appliedByDefault = $this->generateAppliedByDefaultLabel($clientScope->getAppliedByDefault());
97
                    }
98
                    if ($clientScope->getRequiredOnAuthorization() !== null) {
99
                        $requiredOnAuthorization = ($clientScope->getRequiredOnAuthorization() ? 'Yes' : 'No');
100
                    }
101
                }
102
                if (empty($appliedByDefault)) {
103
                    $appliedByDefault = $this->generateAppliedByDefaultLabel($scope->getAppliedByDefault()) . '¹';
104
                    $showInheritedInfo = true;
105
                }
106
                if (empty($requiredOnAuthorization)) {
107
                    $requiredOnAuthorization = ($scope->getRequiredOnAuthorization() ? 'Yes' : 'No') . '¹';
108
                    $showInheritedInfo = true;
109
                }
110
111
                $scopeInfo[] = [
112
                    $scope->getIdentifier(),
113
                    $appliedByDefault,
114
                    $requiredOnAuthorization,
115
                    $clientScope ? 'Client' : 'Generic',
116
                ];
117
            }
118
119
            $this->controller->stdout(count($scopes) . ' scope(s) configured for "'
120
                . $client->getIdentifier() . '" client using '
121
                . ($client->getAllowGenericScopes()
122
                    ? 'generic mode (scopes don\'t need to be explicitly configured for this client)'
123
                    : 'strict mode (scopes need to be explicitly configured for this client)'
124
                )
125
                . '.' . PHP_EOL);
126
127
            $this->controller->stdout(Table::widget([
128
                'headers' => [
129
                    'Scope',
130
                    'Applied by default',
131
                    'Required on authorization',
132
                    'Origin',
133
                ],
134
                'rows' => $scopeInfo,
135
            ]));
136
137
            if ($showInheritedInfo) {
138
                $this->controller->stdout('¹ Config inherited from scope.' . PHP_EOL);
139
            }
140
141
            /** @var Oauth2ClientScopeInterface $clientScopeClass */
142
            $clientScopeClass = DiHelper::getValidatedClassName(Oauth2ClientScopeInterface::class);
143
            $clientScopeTableName = $clientScopeClass::tableName();
144
            $disabledClientScopes = $clientScopeClass::find()
145
                ->innerJoinWith('scope')
146
                ->andWhere([$clientScopeTableName . '.client_id' => $client->getPrimaryKey()])
147
                ->andWhere([$clientScopeTableName . '.enabled' => false])
148
                ->select('identifier')
149
                ->column();
150
151
            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...
152
                $this->controller->stdout('Note: there is/are ' . count($disabledClientScopes)
153
                    . ' scope(s) explicitly disabled for this client: ' . implode(', ', $disabledClientScopes)
154
                    . '.' . PHP_EOL);
155
            }
156
        } else {
157
            $this->controller->stdout(count($scopes) . ' scope(s) configured for "'
158
                . $client->getIdentifier() . '" client.' . PHP_EOL);
159
160
            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...
161
                $this->controller->stdout('Hint: use `--verbose` to show scope configuration.'
162
                    . PHP_EOL, Console::ITALIC);
163
            }
164
        }
165
166
        return ExitCode::OK;
167
    }
168
169
    protected function generateAppliedByDefaultLabel($appliedByDefault)
170
    {
171
        switch ($appliedByDefault) {
172
            case Oauth2ScopeInterface::APPLIED_BY_DEFAULT_NO:
173
                return 'No';
174
            case Oauth2ScopeInterface::APPLIED_BY_DEFAULT_CONFIRM:
175
                return 'Yes (with user confirm)';
176
            case Oauth2ScopeInterface::APPLIED_BY_DEFAULT_AUTOMATICALLY:
177
                return 'Yes (w/o user confirm)';
178
            case Oauth2ScopeInterface::APPLIED_BY_DEFAULT_IF_REQUESTED:
179
                return 'Yes (upon client request w/o user confirm)';
180
        }
181
182
        throw new \LogicException('Unknown "applied by default" value: ' . $appliedByDefault);
183
    }
184
}
185