ClientCommand::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 3
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace OAuth\Command;
4
5
use Del\Service\UserService;
6
use OAuth\Client;
7
use OAuth\Repository\ScopeRepository;
8
use OAuth\Scope;
9
use OAuth\Service\ClientService;
10
use OAuth\OAuthUser as User;
11
use Symfony\Component\Console\Command\Command;
12
use Symfony\Component\Console\Helper\QuestionHelper;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\Console\Question\ChoiceQuestion;
16
use Symfony\Component\Console\Question\ConfirmationQuestion;
17
use Symfony\Component\Console\Question\Question;
18
19
/**
20
 * Class ClientCommand
21
 * @package OAuth\Command
22
 */
23
class ClientCommand extends Command
24
{
25
    /**
26
     * @var ClientService $clientService
27
     */
28
    private $clientService;
29
30
    /**
31
     * @var UserService $userService
32
     */
33
    private $userService;
34
35
    /**
36
     * @var ScopeRepository $scopeRepository
37
     */
38
    private $scopeRepository;
39
40
    /** @var QuestionHelper $helper */
41
    private $helper;
42
43
    /** @var User $user */
44
    private $user;
45
46
    public function __construct(ClientService $clientService, UserService $userService, ScopeRepository $scopeRepository)
47
    {
48
        $this->clientService = $clientService;
49
        $this->userService = $userService;
50
        $this->scopeRepository = $scopeRepository;
51
        parent::__construct('client:create');
52
    }
53
54
    /**
55
     * configure options
56
     */
57
    protected function configure()
58
    {
59
        $this->setDescription('Creates a new client.');
60
        $this->setHelp('Create a new OAuth2 client application');
61
    }
62
63
    private function userQuestion(InputInterface $input, OutputInterface $output)
64
    {
65
        $question = new Question('Enter the email of the account: ', false);
66
        $email = $this->helper->ask($input, $output, $question);
67
68
        $this->userService->setUserClass(User::class);
69
        /** @var User $user */
70
        $this->user = $this->userService->findUserByEmail($email);
0 ignored issues
show
Bug introduced by
It seems like $email can also be of type string[] and string[]; however, parameter $email of Del\Service\UserService::findUserByEmail() does only seem to accept 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

70
        $this->user = $this->userService->findUserByEmail(/** @scrutinizer ignore-type */ $email);
Loading history...
71
    }
72
73
    /**
74
     * @param InputInterface $input
75
     * @param OutputInterface $output
76
     * @throws \Doctrine\ORM\OptimisticLockException
77
     */
78
    protected function execute(InputInterface $input, OutputInterface $output)
79
    {
80
        $output->writeln('Bone API client creator');
81
        $this->helper = $this->getHelper('question');
82
83
        $this->userQuestion($input, $output);
84
85
        if (!$this->user) {
86
            $output->writeln('User not found. Exiting.');
87
            return null;
88
        }
89
90
        $question = new ConfirmationQuestion('Is this a machine only (client_credentials) API key? ', false);
91
        $isClientCredentials = $this->helper->ask($input, $output, $question);
92
93
        if ($isClientCredentials) {
94
            $authGrant = 'client_credentials';
95
            $confidential = true;
96
        } else {
97
98
            $question = new ChoiceQuestion('What type of app is this? ', [
99
                'browser', 'server', 'native'
100
            ]);
101
            $clientType = $this->helper->ask($input, $output, $question);
102
103
            $question = new ConfirmationQuestion('Is this a trusted first party app? ', true);
104
            $confidential = (int) $this->helper->ask($input, $output, $question);
105
106
            switch ($clientType) {
107
                case 'browser':
108
                    $authGrant = 'auth_code';
109
                    break;
110
                case 'useragent':
111
                case 'native':
112
                    $grants = [
113
                        'native' => [
114
                            0 => 'auth_code',
115
                            1 => 'password',
116
                        ],
117
                        'useragent' => [
118
                            0 => 'implicit',
119
                            1 => 'password',
120
                        ],
121
                    ];
122
                    $authGrant = $grants[$clientType][$confidential];
123
                    break;
124
            }
125
        }
126
127
        $output->writeln('Setting GrantType to ' . $authGrant . '..');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $authGrant does not seem to be defined for all execution paths leading up to this point.
Loading history...
128
        $output->writeln('Setting confidential to ' . ($confidential ? 'true' : 'false') . '..');
129
130
        $question = new Question('Give a name for this application: ', false);
131
        $name = $this->helper->ask($input, $output, $question);
132
133
        $question = new Question('Give a description: ', false);
134
        $description = $this->helper->ask($input, $output, $question);
135
136
        $question = new Question('Give an icon URL: ', false);
137
        $icon = $this->helper->ask($input, $output, $question);
138
139
        $question = new Question('Give a redirect URI: ', '');
140
        $uri = $this->helper->ask($input, $output, $question);
141
142
        $scopes = $this->scopeRepository->findAll();
143
        $choices = [];
144
        /** @var Scope $scope */
145
        foreach($scopes as $scope) {
146
            $scopeName = $scope->getIdentifier();
147
            $choices[] = $scopeName;
148
            $scopes[$scopeName] = $scope;
149
        }
150
151
        $question = new ChoiceQuestion('Which scopes would you like to add?', $choices);
152
        $question->setMultiselect(true);
153
        $scopeChoices = $this->helper->ask($input, $output, $question);
154
155
        $client = new Client();
156
        $client->setName($name);
157
        $client->setDescription($description);
158
        $client->setIcon($icon);
159
        $client->setGrantType($authGrant);
160
        $client->setIdentifier(md5($name));
161
        $client->setRedirectUri($uri);
162
        $client->setConfidential($confidential);
0 ignored issues
show
Bug introduced by
It seems like $confidential can also be of type integer; however, parameter $confidential of OAuth\Client::setConfidential() does only seem to accept boolean, 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

162
        $client->setConfidential(/** @scrutinizer ignore-type */ $confidential);
Loading history...
163
        $client->setUser($this->user);
164
165
        foreach ($scopeChoices as $name) {
166
            $output->writeln('Registering ' . $name . ' scope with client..');
167
            $scope = $scopes[$name];
168
            $client->getScopes()->add($scope);
169
        }
170
171
        if ($confidential) {
172
            $output->writeln('Generating client secret..');
173
            $this->clientService->generateSecret($client);
174
        }
175
176
        $this->clientService->getClientRepository()->create($client);
177
178
        $output->writeln('Client created.');
179
    }
180
}