Skip to content

Commit

Permalink
Implement Access endpoints (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
rapkis authored Sep 14, 2023
1 parent c41ef02 commit 93c4a53
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/ControlD.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Rapkis\Controld;

use Illuminate\Http\Client\PendingRequest;
use Rapkis\Controld\Resources\Access;
use Rapkis\Controld\Resources\Devices;
use Rapkis\Controld\Resources\Profiles;

Expand All @@ -23,4 +24,9 @@ public function devices(): Devices
{
return app(Devices::class, ['client' => $this->request]);
}

public function access(): Access
{
return app(Access::class, ['client' => $this->request]);
}
}
17 changes: 17 additions & 0 deletions src/Entities/LearnedIp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Rapkis\Controld\Entities;

class LearnedIp
{
public function __construct(
public readonly string $ip,
public readonly int $timestamp,
public readonly string $isp,
public readonly ?string $country,
public readonly ?string $city,
) {
}
}
22 changes: 22 additions & 0 deletions src/Factories/LearnedIpFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Rapkis\Controld\Factories;

use Rapkis\Controld\Contracts\Factories\Factory;
use Rapkis\Controld\Entities\LearnedIp;

class LearnedIpFactory implements Factory
{
public function make(array $data): LearnedIp
{
return new LearnedIp(
ip: $data['ip'],
timestamp: (int) $data['ts'],
isp: $data['isp'],
country: $data['country'] ?? null,
city: $data['city'] ?? null,
);
}
}
50 changes: 50 additions & 0 deletions src/Resources/Access.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Rapkis\Controld\Resources;

use Illuminate\Http\Client\PendingRequest;
use Rapkis\Controld\Factories\LearnedIpFactory;
use Rapkis\Controld\Responses\LearnedIps;

class Access
{
public function __construct(private readonly PendingRequest $client, private readonly LearnedIpFactory $learnedIp)
{
}

public function list(string $devicePk): LearnedIps
{
$response = $this->client->get('access', ['device_id' => $devicePk])->json('body.ips');

$result = new LearnedIps();

foreach ($response as $learnedIp) {
$learnedIp = $this->learnedIp->make($learnedIp);
$result->put($learnedIp->ip, $learnedIp);
}

return $result;
}

public function learn(string $devicePk, array $ips): bool
{
$this->client->post('access', [
'device_id' => $devicePk,
'ips' => $ips,
]);

return true;
}

public function delete(string $devicePk, array $ips): bool
{
$this->client->delete('access', [
'device_id' => $devicePk,
'ips' => $ips,
]);

return true;
}
}
11 changes: 11 additions & 0 deletions src/Responses/LearnedIps.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Rapkis\Controld\Responses;

use Illuminate\Support\Collection;

class LearnedIps extends Collection
{
}
6 changes: 6 additions & 0 deletions tests/ControlDTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Http\Client\PendingRequest;
use Rapkis\Controld\ControlD;
use Rapkis\Controld\Resources\Access;
use Rapkis\Controld\Resources\Devices;
use Rapkis\Controld\Resources\Profiles;

Expand All @@ -16,3 +17,8 @@
$client = new ControlD($this->createStub(PendingRequest::class));
expect($client->devices())->toBeInstanceOf(Devices::class);
});

it('accesses access resource', function () {
$client = new ControlD($this->createStub(PendingRequest::class));
expect($client->access())->toBeInstanceOf(Access::class);
});
43 changes: 43 additions & 0 deletions tests/Factories/LearnedIpFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

use Rapkis\Controld\Entities\LearnedIp;
use Rapkis\Controld\Factories\LearnedIpFactory;

it('builds an action', function (array $data, LearnedIp $expected) {
expect((new LearnedIpFactory())->make($data))->toEqual($expected);
})->with([
[
[
'ip' => '127.0.0.1',
'ts' => 111111111,
'country' => null,
'city' => null,
'isp' => 'Cloudflare',
],
new LearnedIp(
ip: '127.0.0.1',
timestamp: 111111111,
isp: 'Cloudflare',
country: null,
city: null,
),
],
[
[
'ip' => '2606:1a40::2',
'ts' => 111111111,
'country' => 'US',
'city' => 'New York',
'isp' => 'Cloudflare',
],
new LearnedIp(
ip: '2606:1a40::2',
timestamp: 111111111,
isp: 'Cloudflare',
country: 'US',
city: 'New York',
),
],
]);
5 changes: 5 additions & 0 deletions tests/Mocks/Endpoints/access-delete.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"body": {},
"success": true,
"message": "1 IPs deleted"
}
5 changes: 5 additions & 0 deletions tests/Mocks/Endpoints/access-learn.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"body": {},
"success": true,
"message": "1 IPs added"
}
28 changes: 28 additions & 0 deletions tests/Mocks/Endpoints/access-list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"body": {
"ips": [
{
"ip": "2606:1a40::2",
"ts": 1694584816,
"country": "US",
"city": null,
"isp": "Cloudflare"
},
{
"ip": "22606:1a40:1::2",
"ts": 1694584816,
"country": "US",
"city": null,
"isp": "Cloudflare"
},
{
"ip": "127.0.0.1",
"ts": 1694443821,
"country": "NL",
"city": "Amsterdam",
"isp": "Cloudflare"
}
]
},
"success": true
}
58 changes: 58 additions & 0 deletions tests/Resources/AccessTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

use Illuminate\Support\Facades\Http;
use Rapkis\Controld\Factories\LearnedIpFactory;
use Rapkis\Controld\Resources\Access;
use Rapkis\Controld\Responses\LearnedIps;

beforeEach(function () {
Http::preventStrayRequests();
});

it('lists known ips', function () {
$request = Http::fake([
'access?device_id=device_pk' => Http::response(mockJsonEndpoint('access-list')),
])->asJson();

$resource = new Access(
$request,
app(LearnedIpFactory::class),
);

$result = $resource->list('device_pk');

expect($result)->toBeInstanceOf(LearnedIps::class)
->and($result)->toHaveCount(3);
});

it('learns a new ip', function () {
$request = Http::fake([
'access' => Http::response(mockJsonEndpoint('access-learn')),
])->asJson();

$resource = new Access(
$request,
$this->createStub(LearnedIpFactory::class),
);

$result = $resource->learn('device_pk', ['0.0.0.0']);

expect($result)->toBeTrue();
});

it('deletes an IP', function () {
$request = Http::fake([
'access' => Http::response(mockJsonEndpoint('access-delete')),
])->asJson();

$resource = new Access(
$request,
$this->createStub(LearnedIpFactory::class),
);

$result = $resource->delete('device_pk', ['0.0.0.0']);

expect($result)->toBeTrue();
});

0 comments on commit 93c4a53

Please sign in to comment.