Skip to content

Commit

Permalink
Add subscription status
Browse files Browse the repository at this point in the history
  • Loading branch information
digiservnet committed Oct 7, 2024
1 parent af51f5d commit 5065b8b
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 13 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]



## [6.5.0] - 2024-10-07

- Add additional Paste sources for link generation
- Add subscription status endpoint
- Fix date object creation for Breach Site Entities
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,20 @@ $data = $paste->lookup('test@example.com');

This will return a `Collection` of `PasteEntity` objects.

## Subscription Status

### Get the current subscription status for an API Key

```php
use Icawebdesign\Hibp\HibpHttp;
use Icawebdesign\Hibp\Subscription\Subscription;

$subscription = new Subscription(new HibpHttp($apiKey));
$status = $subscription->status();
```

This will return a `SubscriptionStatusEntity` object.

## Laravel specifics
If using the package within a Laravel application, you can use the provided facades.
First, you need to add your HIBP API key to your `.env` file, or your preferred method for adding values to your server environment variables.
Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
"type": "library",
"require": {
"php": "^8.1||^8.2||^8.3",
"guzzlehttp/guzzle": "^7.5",
"symfony/yaml": "^6.1||^7.0",
"nesbot/carbon": "^2.63||^3.0",
"ext-json": "*",
"guzzlehttp/guzzle": "^7.5",
"guzzlehttp/psr7": "^2.4",
"illuminate/collections": "^8.0||^9.43||^10.0||^11.0",
"nesbot/carbon": "^2.63||^3.0",
"psr/http-message": "^1.0||^2.0",
"guzzlehttp/psr7": "^2.4"
"symfony/http-foundation": "^6.4",
"symfony/yaml": "^6.1||^7.0"
},
"require-dev": {
"mockery/mockery": "^1.6",
Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
</logging>
<source>
<include>
<directory>src/</directory>
<directory>src</directory>
</include>
</source>
</phpunit>
10 changes: 10 additions & 0 deletions src/Exception/UnauthorizedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Icawebdesign\Hibp\Exception;

use RuntimeException;

class UnauthorizedException extends RuntimeException
{

}
5 changes: 3 additions & 2 deletions src/Subscription/Subscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Icawebdesign\Hibp\Traits\HibpConfig;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\RequestException;
use Icawebdesign\Hibp\Exception\UnauthorizedException;
use Icawebdesign\Hibp\Exception\PasteNotFoundException;

use function sprintf;
Expand All @@ -25,7 +26,7 @@ class Subscription implements SubscriptionInterface

public function __construct(HibpHttp $hibpHttp)
{
$this->apiRoot = "{$this->hibp['api_root']}/v/{$this->hibp['api_version']}/";
$this->apiRoot = "{$this->hibp['api_root']}/v{$this->hibp['api_version']}";
$this->client = $hibpHttp->client();
}

Expand All @@ -41,7 +42,7 @@ public function status(array $options = []): SubscriptionStatusEntity
$this->statusCode = $exception->getCode();

throw match ($exception->getCode()) {
404 => new PasteNotFoundException($exception->getMessage()),
401 => new UnauthorizedException($exception->getMessage(), $exception->getCode()),
400 => new RequestException($exception->getMessage(), $exception->getRequest()),
default => $exception,
};
Expand Down
4 changes: 2 additions & 2 deletions src/Subscription/SubscriptionStatusEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class SubscriptionStatusEntity

public readonly Carbon $expires;

public readonly int $requestsPerSecond;
public readonly int $requestsPerMinute;

public readonly int $domainSearchMaxBreachedAccounts;

Expand All @@ -34,7 +34,7 @@ public function __construct(?stdClass $data = null)
$this->tier = $tier;
$this->description = $data->Description;
$this->expires = Carbon::parse($data->SubscribedUntil);
$this->requestsPerSecond = $data->Rpm;
$this->requestsPerMinute = $data->Rpm;
$this->domainSearchMaxBreachedAccounts = $data->DomainSearchMaxBreachedAccounts;
}
}
32 changes: 28 additions & 4 deletions tests/SubscriptionStatusTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
namespace Icawebdesign\Hibp\Tests;

use Mockery;
use Carbon\Carbon;
use RuntimeException;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\TestCase;
use Icawebdesign\Hibp\HibpHttp;
use PHPUnit\Framework\Attributes\Test;
use GuzzleHttp\Exception\ClientException;
use Icawebdesign\Hibp\Enums\SubscriptionTier;
use Icawebdesign\Hibp\Subscription\Subscription;
use Icawebdesign\Hibp\Exception\UnauthorizedException;
use Icawebdesign\Hibp\Subscription\SubscriptionStatusEntity;
use Symfony\Component\HttpFoundation\Response as HttpResponse;

class SubscriptionStatusTest extends TestCase
Expand All @@ -28,12 +33,31 @@ public function a_valid_api_key_will_return_status_of_the_subscription(): void
$client
->expects('request')
->once()
->andReturn(new Response(HttpResponse::HTTP_OK, [], json_encode([
'SubscriptionName' => 'Pwned 1',
])));
->andReturn(new Response(HttpResponse::HTTP_OK, [], self::mockSubscriptionStatus()));

$status = (new Subscription(hibpHttp: new HibpHttp($client)))->status();
$status = (new Subscription(hibpHttp: new HibpHttp(client: $client)))->status();

self::assertEquals(new Carbon('2024-11-07T21:26:19'), $status->expires);
self::assertSame(SubscriptionTier::Pwned1, $status->tier);
self::assertNotEmpty($status->description);
self::assertSame(25, $status->domainSearchMaxBreachedAccounts);
self::assertSame(10, $status->requestsPerMinute);
}

#[Test]
public function invalid_subscription_data_throws_runtime_exception(): void
{
$this->expectException(RuntimeException::class);

new SubscriptionStatusEntity(data: null);
}

private static function mockSubscriptionStatus(): string
{
$data = file_get_contents(
sprintf('%s/_responses/subscription/status.json', __DIR__),
);

return ($data !== false) ? $data : '[]';
}
}
7 changes: 7 additions & 0 deletions tests/_responses/subscription/status.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"SubscribedUntil": "2024-11-07T21:26:19",
"SubscriptionName": "Pwned 1",
"Description": "Domains with up to 25 breached addresses each, and a rate limited API key allowing 10 email address searches per minute",
"DomainSearchMaxBreachedAccounts": 25,
"Rpm": 10
}

0 comments on commit 5065b8b

Please sign in to comment.