HaveIBeenPwnedService::checkPwnedPassword()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 12
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 21
rs 9.8666
1
<?php
2
3
namespace Firesphere\HaveIBeenPwned\Services;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\GuzzleException;
7
use Psr\Http\Message\ResponseInterface;
8
use SilverStripe\Core\Config\Configurable;
9
use SilverStripe\Core\Convert;
10
use SilverStripe\Core\Injector\Injector;
11
use SilverStripe\Security\Member;
12
13
/**
14
 * Class HaveIBeenPwnedService
15
 * @package Firesphere\HaveIBeenPwned\Services
16
 */
17
class HaveIBeenPwnedService
18
{
19
    use Configurable;
20
21
    /**
22
     * Api endpoint emails
23
     */
24
    const PWND_URL = 'https://haveibeenpwned.com/api/v3';
25
26
    /**
27
     * API endpoint passwords
28
     */
29
    const PWND_API_URL = 'https://api.pwnedpasswords.com/';
30
31
    /**
32
     * API Version
33
     */
34
    const API_VERSION = '3';
35
36
    /**
37
     * Useragent
38
     */
39
    const USER_AGENT = 'Firesphere-HaveIBeenPwned-checker/1.0';
40
41
    /**
42
     * @config
43
     * @var bool
44
     */
45
    private static $allow_pwnd = false;
46
47
    /**
48
     * @config
49
     * @var bool
50
     */
51
    private static $save_pwnd = true;
52
53
    /**
54
     * @var array
55
     */
56
    protected $args;
57
58
    /**
59
     * HaveIBeenPwnedService constructor.
60
     * @param array $args
61
     */
62
    public function __construct($args = [])
63
    {
64
        $this->args = $args;
65
    }
66
67
    /**
68
     * @param string $pwd
69
     * @return int
70
     * @throws GuzzleException
71
     */
72
    public function checkPwnedPassword($pwd)
73
    {
74
        $this->args['base_uri'] = static::PWND_API_URL;
75
76
        $sha = sha1($pwd);
77
        $shaStart = substr($sha, 0, 5);
78
        $shaEnd = substr($sha, 5);
79
        /** @var Client $client */
80
        $client = Injector::inst()->createWithArgs(Client::class, [$this->args]);
81
        $result = $client->request(
82
            'GET',
83
            'range/' . $shaStart,
84
            [
85
                'headers' => [
86
                    'user-agent'  => static::USER_AGENT,
87
                    'api-version' => static::API_VERSION
88
                ]
89
            ]
90
        );
91
92
        return $this->checkList($result, $shaEnd);
93
    }
94
95
    /**
96
     * @param ResponseInterface $result
97
     * @param $shaEnd
98
     * @return int
99
     */
100
    private function checkList($result, $shaEnd)
101
    {
102
        $count = 0;
103
        $shaEnd = strtoupper($shaEnd);
104
        $suffixes = explode("\n", $result->getBody());
105
        foreach ($suffixes as $suffix) {
106
            list($suffix, $pwnCount) = explode(':', trim($suffix));
107
            if ($suffix === $shaEnd) {
108
                $count += (int)$pwnCount;
109
                break;
110
            }
111
        }
112
113
        return $count;
114
    }
115
116
    /**
117
     * @param Member $member
118
     * @return string
119
     * @throws GuzzleException
120
     */
121
    public function checkPwnedEmail($member)
122
    {
123
        $this->args['base_uri'] = static::PWND_URL;
124
        $api_key = $this->hibp_api_key;
0 ignored issues
show
Bug Best Practice introduced by
The property hibp_api_key does not exist on Firesphere\HaveIBeenPwne...s\HaveIBeenPwnedService. Did you maybe forget to declare it?
Loading history...
125
        $uniqueField = Member::config()->get('unique_identifier_field');
126
        $account = $member->{$uniqueField};
127
128
        /** @var Client $client */
129
        $client = Injector::inst()->createWithArgs(Client::class, [$this->args]);
130
131
        $result = $client->request(
132
            'GET',
133
            'breachedaccount/' . $account . '?truncateResponse=true',
134
            [
135
                'headers' => [
136
                    'user-agent'  => static::USER_AGENT,
137
                    'api-version' => static::API_VERSION,
138
                    'hibp-api-key' => $api_key
139
                ]
140
            ]
141
        );
142
143
        return $this->checkBreaches($result);
144
    }
145
146
    /**
147
     * @param ResponseInterface $result
148
     * @return string
149
     */
150
    private function checkBreaches($result)
151
    {
152
        $body = $result->getBody();
153
154
        $sites = [];
155
156
        $breaches = Convert::json2array($body);
0 ignored issues
show
Deprecated Code introduced by
The function SilverStripe\Core\Convert::json2array() has been deprecated: 4.4.0:5.0.0 Use json_decode() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

156
        $breaches = /** @scrutinizer ignore-deprecated */ Convert::json2array($body);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
157
        foreach ($breaches as $breach) {
158
            if (!empty($breach['Name'])) {
159
                $sites[] = $breach['Name'];
160
            }
161
        }
162
163
        if (count($sites)) {
164
            return implode(', ', $sites);
165
        }
166
167
        return '';
168
    }
169
170
    /**
171
     * @return array
172
     */
173
    public function getArgs()
174
    {
175
        return $this->args;
176
    }
177
178
    /**
179
     * @param array $args
180
     */
181
    public function setArgs($args)
182
    {
183
        $this->args = $args;
184
    }
185
}
186