Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/API/Enums/SystemLogTopic.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Uxicodev\UnifiAccessApi\API\Enums;

enum SystemLogTopic: string
{
/** Fetch all logs. */
case All = 'all';
/** Fetch door opening logs. */
case DoorOpenings = 'door_openings';
/** Fetch logs for device restart, deletion, offline status, and detection. */
case Critical = 'critical';
/** Fetch device update logs. */
case Updates = 'updates';
/** Fetch logs for device online status, device updates, access policy synchronization, and active/inactive door unlock schedules. */
case DeviceEvents = 'device_events';
/** Fetch logs for admin activity, such as access policy updates, settings changes, and user management. */
case AdminActivity = 'admin_activity';
/** Fetch logs of visitor-related operations. */
case Visitor = 'visitor';
}
102 changes: 102 additions & 0 deletions src/API/Requests/System/SystemLogRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

namespace Uxicodev\UnifiAccessApi\API\Requests\System;

use Carbon\Carbon;
use Uxicodev\UnifiAccessApi\API\Enums\SystemLogTopic;
use Uxicodev\UnifiAccessApi\API\Requests\Validators\SystemLogValidator;
use Uxicodev\UnifiAccessApi\API\ValueObjects\UuidV4;
use Uxicodev\UnifiAccessApi\Exceptions\ValidationException;

readonly class SystemLogRequest
{
/**
* @throws ValidationException
*/
public function __construct(
public SystemLogTopic $topic,
public Carbon $since,
public ?Carbon $until = null,
public ?UuidV4 $actor_id = null,
public ?int $page_size = null,
public ?int $page_num = null
) {
$this::validate($this->toArray());
}

/**
* @param array<string, mixed> $data
*
* @throws ValidationException
*/
public static function fromArray(array $data): self
{
self::validate($data);
$since = Carbon::parse($data['since']);
$until = isset($data['until']) ? Carbon::parse($data['until']) : null;

return new self(
SystemLogTopic::from($data['topic']),
$since,
$until,
isset($data['actor_id']) ? new UuidV4($data['actor_id']) : null,
$data['page_size'] ?? null,
$data['page_num'] ?? null
);
}

/**
* @param array<string, mixed> $data
*
* @throws ValidationException
*/
private static function validate(array $data): void
{
$validator = new SystemLogValidator($data);
if (! $validator->passes()) {
throw new ValidationException(
errors: $validator->getErrors(),
message: 'SystemLogRequest validation failed.'
);
}
}

/**
* @return array<string, mixed>
*/
public function toArray(): array
{
return [
'topic' => $this->topic->value,
'since' => $this->since->unix(),
'until' => $this->until?->unix(),
'actor_id' => $this->actor_id?->getValue(),
'page_size' => $this->page_size,
'page_num' => $this->page_num,
];
}

/**
* @return array<string, mixed>
*/
public function getQueryParams(): array
{
return [
'page_size' => $this->page_size,
'page_num' => $this->page_num,
];
}

/**
* @return array<string, mixed>
*/
public function getPostBody(): array
{
return [
'topic' => $this->topic->value,
'since' => $this->since->unix(),
'until' => $this->until?->unix(),
'actor_id' => $this->actor_id?->getValue(),
];
}
}
18 changes: 18 additions & 0 deletions src/API/Requests/Validators/AbstractValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,29 @@ abstract class AbstractValidator implements ValidatorContract
/** @var array<string, array<array-key, string>> */
protected array $errors = [];

/**
* @var string[]
*/
protected array $required = [];

/**
* @param array<array-key, mixed> $data
*/
public function __construct(protected readonly array $data) {}

protected function validateRequiredFields(): bool
{
$valid = true;
foreach ($this->required as $field) {
if (! array_key_exists($field, $this->data) || $this->data[$field] === null || $this->data[$field] === '') {
$this->errors[$field][] = "The field '{$field}' is required.";
$valid = false;
}
}

return $valid;
}

public function getErrors(): MessageBagContract
{
return new MessageBag($this->errors);
Expand Down
27 changes: 27 additions & 0 deletions src/API/Requests/Validators/SystemLogValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Uxicodev\UnifiAccessApi\API\Requests\Validators;

use Carbon\Carbon;

class SystemLogValidator extends AbstractValidator
{
protected array $required = ['topic', 'since'];

public function passes(): bool
{
$valid = $this->validateRequiredFields();
$since = $this->data['since'] ?? null;
$until = $this->data['until'] ?? null;
if ($since && $until) {
$sinceCarbon = $since instanceof Carbon ? $since : Carbon::parse($since);
$untilCarbon = $until instanceof Carbon ? $until : Carbon::parse($until);
if ($untilCarbon->lessThanOrEqualTo($sinceCarbon)) {
$this->errors['until'][] = "'until' must be after 'since'.";
$valid = false;
}
}

return $valid && count($this->errors) === 0;
}
}
2 changes: 1 addition & 1 deletion src/API/Responses/Resource/ResourceGroupResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Illuminate\Support\Collection;
use Uxicodev\UnifiAccessApi\API\Responses\UnifiResponse;
use Uxicodev\UnifiAccessApi\Entities\DoorGroupEntity;
use Uxicodev\UnifiAccessApi\Entities\DoorGroups\DoorGroupEntity;

readonly class ResourceGroupResponse extends UnifiResponse
{
Expand Down
35 changes: 35 additions & 0 deletions src/API/Responses/System/SystemLogsResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Uxicodev\UnifiAccessApi\API\Responses\System;

use Illuminate\Support\Collection;
use Uxicodev\UnifiAccessApi\API\Responses\UnifiResponse;
use Uxicodev\UnifiAccessApi\Entities\System\SystemLogEntity;

readonly class SystemLogsResponse extends UnifiResponse
{
/** @param Collection<int, SystemLogEntity> $logs */
public function __construct(
string $code,
public Collection $logs,
public int $page,
public int $total,
) {
parent::__construct($code, '');
}

/**
* @param array<string, mixed> $response
*/
public static function fromArray(array $response): self
{
$hits = collect($response['data']['hits'] ?? [])->map(fn ($item) => SystemLogEntity::fromArray($item));

return new self(
$response['code'] ?? '',
$hits,
$response['page'] ?? 1,
$response['total'] ?? 0
);
}
}
2 changes: 1 addition & 1 deletion src/API/Responses/Visitor/VisitorResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Uxicodev\UnifiAccessApi\API\Responses\Visitor;

use Uxicodev\UnifiAccessApi\API\Responses\UnifiResponse;
use Uxicodev\UnifiAccessApi\Entities\VisitorEntity;
use Uxicodev\UnifiAccessApi\Entities\Visitor\VisitorEntity;

readonly class VisitorResponse extends UnifiResponse
{
Expand Down
2 changes: 1 addition & 1 deletion src/API/Responses/Visitor/VisitorsResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Illuminate\Support\Collection;
use Uxicodev\UnifiAccessApi\API\Responses\UnifiResponse;
use Uxicodev\UnifiAccessApi\Entities\VisitorEntity;
use Uxicodev\UnifiAccessApi\Entities\Visitor\VisitorEntity;

readonly class VisitorsResponse extends UnifiResponse
{
Expand Down
30 changes: 30 additions & 0 deletions src/API/SystemClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Uxicodev\UnifiAccessApi\API;

use GuzzleHttp\Exception\GuzzleException;
use Uxicodev\UnifiAccessApi\API\Requests\System\SystemLogRequest;
use Uxicodev\UnifiAccessApi\API\Responses\System\SystemLogsResponse;
use Uxicodev\UnifiAccessApi\Exceptions\InvalidResponseException;
use Uxicodev\UnifiAccessApi\Exceptions\UnifiApiErrorException;

class SystemClient extends ApiResourceClient
{
private const ENDPOINT = 'system';

/**
* @throws InvalidResponseException
* @throws GuzzleException
* @throws UnifiApiErrorException
*/
public function logs(SystemLogRequest $request): SystemLogsResponse
{
$response = $this->client->post($this::ENDPOINT.'/logs?'.http_build_query($request->getQueryParams()),
$request->getPostBody()
);

$data = json_decode($response->getBody()->getContents(), true);

return SystemLogsResponse::fromArray($data);
}
}
9 changes: 9 additions & 0 deletions src/Client/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Psr\Http\Message\ResponseInterface;
use Uxicodev\UnifiAccessApi\API\CredentialClient;
use Uxicodev\UnifiAccessApi\API\DoorGroupsClient;
use Uxicodev\UnifiAccessApi\API\SystemClient;
use Uxicodev\UnifiAccessApi\API\VisitorClient;
use Uxicodev\UnifiAccessApi\Exceptions\InvalidResponseException;
use Uxicodev\UnifiAccessApi\Exceptions\UnifiApiErrorException;
Expand All @@ -20,11 +21,14 @@ class Client

protected DoorGroupsClient $doorGroupsClient;

protected SystemClient $systemClient;

public function __construct(protected GuzzleHttpClient $client)
{
$this->visitorClient = new VisitorClient($this);
$this->credentialClient = new CredentialClient($this);
$this->doorGroupsClient = new DoorGroupsClient($this);
$this->systemClient = new SystemClient($this);
}

/**
Expand Down Expand Up @@ -138,6 +142,11 @@ public function doorGroups(): DoorGroupsClient
return $this->doorGroupsClient;
}

public function system(): SystemClient
{
return $this->systemClient;
}

/**
* @throws InvalidResponseException
* @throws UnifiApiErrorException
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Uxicodev\UnifiAccessApi\Entities;
namespace Uxicodev\UnifiAccessApi\Entities\DoorGroups;

use Uxicodev\UnifiAccessApi\API\Enums\ResourceType;
use Uxicodev\UnifiAccessApi\API\ValueObjects\UuidV4;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Uxicodev\UnifiAccessApi\Entities;
namespace Uxicodev\UnifiAccessApi\Entities\DoorGroups;

use Illuminate\Support\Collection;
use Uxicodev\UnifiAccessApi\API\Enums\ResourceType;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Uxicodev\UnifiAccessApi\Entities;
namespace Uxicodev\UnifiAccessApi\Entities\DoorGroups;

use Illuminate\Support\Collection;
use Uxicodev\UnifiAccessApi\API\Enums\ResourceType;
Expand Down
26 changes: 26 additions & 0 deletions src/Entities/System/SystemLogActorEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Uxicodev\UnifiAccessApi\Entities\System;

readonly class SystemLogActorEntity
{
public function __construct(
public string $alternate_id,
public string $alternate_name,
public string $display_name,
public string $id,
public string $type
) {}

/** @param array<array-key, string> $data */
public static function fromArray(array $data): self
{
return new self(
$data['alternate_id'] ?? '',
$data['alternate_name'] ?? '',
$data['display_name'] ?? '',
$data['id'] ?? '',
$data['type'] ?? ''
);
}
}
20 changes: 20 additions & 0 deletions src/Entities/System/SystemLogAuthenticationEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Uxicodev\UnifiAccessApi\Entities\System;

readonly class SystemLogAuthenticationEntity
{
public function __construct(
public string $credential_provider,
public string $issuer
) {}

/** @param array<array-key, string> $data */
public static function fromArray(array $data): self
{
return new self(
$data['credential_provider'] ?? '',
$data['issuer'] ?? ''
);
}
}
Loading