|
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 PROCERGS\LoginCidadao\CpfVerificationBundle\Service; |
|
12
|
|
|
|
|
13
|
|
|
use GuzzleHttp\Client; |
|
14
|
|
|
use PROCERGS\LoginCidadao\CpfVerificationBundle\Exception\CpfNotSubscribedToNfgException; |
|
15
|
|
|
use PROCERGS\LoginCidadao\CpfVerificationBundle\Model\ChallengeInterface; |
|
16
|
|
|
use PROCERGS\LoginCidadao\CpfVerificationBundle\Model\SelectMotherInitialsChallenge; |
|
17
|
|
|
use PROCERGS\LoginCidadao\CpfVerificationBundle\Model\TypeBirthdayChallenge; |
|
18
|
|
|
use PROCERGS\LoginCidadao\CpfVerificationBundle\Model\TypeMotherInitialsChallenge; |
|
19
|
|
|
use PROCERGS\LoginCidadao\CpfVerificationBundle\Model\TypePostalCodeChallenge; |
|
20
|
|
|
use PROCERGS\LoginCidadao\CpfVerificationBundle\Model\TypeVoterRegistrationChallenge; |
|
21
|
|
|
use PROCERGS\LoginCidadao\CpfVerificationBundle\Parser\ChallengeParser; |
|
22
|
|
|
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; |
|
23
|
|
|
|
|
24
|
|
|
class CpfVerificationService |
|
25
|
|
|
{ |
|
26
|
|
|
/** @var Client */ |
|
27
|
|
|
private $client; |
|
28
|
|
|
|
|
29
|
|
|
/** |
|
30
|
|
|
* CpfVerificationService constructor. |
|
31
|
|
|
* @param Client $client |
|
32
|
|
|
*/ |
|
33
|
3 |
|
public function __construct(Client $client) |
|
34
|
|
|
{ |
|
35
|
3 |
|
$this->client = $client; |
|
36
|
3 |
|
} |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* @param string $cpf |
|
40
|
|
|
* @return ChallengeInterface[] |
|
41
|
|
|
* @throws CpfNotSubscribedToNfgException |
|
42
|
|
|
*/ |
|
43
|
1 |
|
public function listAvailableChallenges(string $cpf): array |
|
44
|
|
|
{ |
|
45
|
1 |
|
$challenges = $this->getAvailableChallengesFromApi($cpf); |
|
46
|
|
|
|
|
47
|
1 |
|
return $challenges; |
|
48
|
|
|
|
|
49
|
|
|
return [ |
|
|
|
|
|
|
50
|
|
|
new TypeMotherInitialsChallenge(1, $cpf), |
|
51
|
|
|
new SelectMotherInitialsChallenge(2, $cpf, ['ABC', 'DEF', 'XYZ']), |
|
52
|
|
|
new TypePostalCodeChallenge(3, $cpf), |
|
53
|
|
|
new TypeBirthdayChallenge(4, $cpf), |
|
54
|
|
|
new TypeVoterRegistrationChallenge(5, $cpf), |
|
55
|
|
|
]; |
|
56
|
|
|
} |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* @param ChallengeInterface $challenge |
|
60
|
|
|
* @return ChallengeInterface |
|
61
|
|
|
* @throws CpfNotSubscribedToNfgException |
|
62
|
|
|
*/ |
|
63
|
1 |
|
public function selectChallenge(ChallengeInterface $challenge): ChallengeInterface |
|
64
|
|
|
{ |
|
65
|
1 |
|
return $this->selectChallengeFromApi($challenge); |
|
66
|
|
|
|
|
67
|
|
|
return $challenge; |
|
|
|
|
|
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* @param ChallengeInterface $challenge |
|
72
|
|
|
* @param $answer |
|
73
|
|
|
* @return bool |
|
74
|
|
|
* @throws CpfNotSubscribedToNfgException |
|
75
|
|
|
*/ |
|
76
|
1 |
|
public function answerChallenge(ChallengeInterface $challenge, $answer): bool |
|
|
|
|
|
|
77
|
|
|
{ |
|
78
|
|
|
// TODO: implement actual method |
|
79
|
|
|
|
|
80
|
1 |
|
return true; |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
1 |
|
private function getAvailableChallengesFromApi(string $cpf): array |
|
84
|
|
|
{ |
|
85
|
1 |
|
$response = $this->client->get("cpf/{$cpf}/challenges"); |
|
86
|
1 |
|
$statusCode = $response->getStatusCode(); |
|
87
|
1 |
|
$body = (string)$response->getBody(); |
|
88
|
1 |
|
if ($statusCode === 200) { |
|
89
|
1 |
|
return $this->parseChallengesList($body); |
|
90
|
|
|
} |
|
91
|
|
|
|
|
92
|
|
|
if ($statusCode === 403) { |
|
93
|
|
|
$response = json_decode($body); |
|
94
|
|
|
if ($response['error'] === CpfNotSubscribedToNfgException::ERROR_CODE) { |
|
95
|
|
|
throw new CpfNotSubscribedToNfgException($cpf, $response['message'] ?? null); |
|
|
|
|
|
|
96
|
|
|
} |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
if ($statusCode === 429) { |
|
100
|
|
|
throw new TooManyRequestsHttpException(); |
|
101
|
|
|
} |
|
102
|
|
|
|
|
103
|
|
|
throw new \LogicException("Invalid response code {$statusCode} with body {$body}"); |
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
1 |
|
private function selectChallengeFromApi(ChallengeInterface $challenge): ChallengeInterface |
|
107
|
|
|
{ |
|
108
|
1 |
|
$response = $this->client->get("cpf/{$challenge->getCpf()}/challenges/{$challenge->getName()}"); |
|
109
|
1 |
|
$statusCode = $response->getStatusCode(); |
|
110
|
1 |
|
$body = (string)$response->getBody(); |
|
111
|
|
|
|
|
112
|
1 |
|
if ($statusCode === 200) { |
|
113
|
1 |
|
return ChallengeParser::parseJson((string)$response->getBody()); |
|
114
|
|
|
} |
|
115
|
|
|
|
|
116
|
|
|
if ($statusCode === 403) { |
|
117
|
|
|
$response = json_decode($body); |
|
118
|
|
|
if ($response['error'] === CpfNotSubscribedToNfgException::ERROR_CODE) { |
|
119
|
|
|
throw new CpfNotSubscribedToNfgException($challenge->getCpf(), $response['message'] ?? null); |
|
|
|
|
|
|
120
|
|
|
} |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
if ($statusCode === 429) { |
|
124
|
|
|
throw new TooManyRequestsHttpException(); |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
throw new \LogicException("Invalid response code {$statusCode} with body {$body}"); |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
/** |
|
131
|
|
|
* @param string $json |
|
132
|
|
|
* @return ChallengeInterface[] |
|
133
|
|
|
*/ |
|
134
|
1 |
|
private function parseChallengesList(string $json): array |
|
135
|
|
|
{ |
|
136
|
1 |
|
$response = json_decode($json, true); |
|
137
|
1 |
|
$challenges = []; |
|
138
|
1 |
|
if (array_key_exists('challenges', $response)) { |
|
139
|
1 |
|
$cpf = $response['cpf']; |
|
140
|
1 |
|
foreach ($response['challenges'] as $challenge) { |
|
141
|
1 |
|
$challenges[] = ChallengeParser::parseArray($challenge, $cpf); |
|
142
|
|
|
} |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
1 |
|
return $challenges; |
|
146
|
|
|
} |
|
147
|
|
|
} |
|
148
|
|
|
|
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return,dieorexitstatements that have been added for debug purposes.In the above example, the last
return falsewill never be executed, because a return statement has already been met in every possible execution path.