Skip to content
Prev Previous commit
Next Next commit
[master] add more return types
  • Loading branch information
annadamm-check24 committed Mar 4, 2024
commit 00beaff507c16068c62a84cb2737a8d5a8254b30
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- PHP 8.1 is now required
- All class properties and function parameters are now typed
- All functions now are properly return typed

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ parameters:
tmpDir: data/phpstan
cache:
nodesByStringCountMax: 0
level: 5
level: 6
fileExtensions:
- php
paths:
Expand Down
39 changes: 27 additions & 12 deletions src/Client/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@

namespace Dflydev\Hawk\Client;

use InvalidArgumentException;
use Dflydev\Hawk\Credentials\CredentialsInterface;
use Dflydev\Hawk\Crypto\Artifacts;
use Dflydev\Hawk\Crypto\Crypto;
use Dflydev\Hawk\Header\HeaderFactory;
use Dflydev\Hawk\Nonce\NonceProviderInterface;
use Dflydev\Hawk\Time\TimeProviderInterface;
use InvalidArgumentException;

/**
* @see \Dflydev\Hawk\Client\ClientTest
*/
class Client implements ClientInterface
{
/**
Expand All @@ -22,18 +19,22 @@ public function __construct(
private readonly Crypto $crypto,
private readonly TimeProviderInterface $timeProvider,
private readonly NonceProviderInterface $nonceProvider,
private $localtimeOffset
private int $localtimeOffset
) {
}

public function createRequest(CredentialsInterface $credentials, $uri, $method, array $options = []): Request
{
public function createRequest(
CredentialsInterface $credentials,
string $uri,
string $method,
array $options = []
): Request {
$timestamp = $options['timestamp'] ?? $this->timeProvider->createTimestamp();
if ($this->localtimeOffset) {
$timestamp += $this->localtimeOffset;
}

$parsed = parse_url((string)$uri);
$parsed = parse_url($uri);
$host = $parsed['host'];
$resource = $parsed['path'] ?? '';

Expand Down Expand Up @@ -106,7 +107,7 @@ public function createRequest(CredentialsInterface $credentials, $uri, $method,
public function authenticate(
CredentialsInterface $credentials,
Request $request,
$headerObjectOrString,
mixed $headerObjectOrString,
array $options = []
): bool {
$header = HeaderFactory::createFromHeaderObjectOrString(
Expand Down Expand Up @@ -169,14 +170,28 @@ function (): never {
return $artifacts->hash() === $hash;
}

public function createBewit(CredentialsInterface $credentials, $uri, $ttlSec, array $options = []): string
{
/**
* @param CredentialsInterface $credentials
* @param string $uri
* @param int $ttlSec
* @param array{
* timestamp?: int,
* ext?: string,
* } $options
* @return string
*/
public function createBewit(
CredentialsInterface $credentials,
string $uri,
int $ttlSec,
array $options = []
): string {
$timestamp = $options['timestamp'] ?? $this->timeProvider->createTimestamp();
if ($this->localtimeOffset) {
$timestamp += $this->localtimeOffset;
}

$parsed = parse_url((string)$uri);
$parsed = parse_url($uri);
$host = $parsed['host'];
$resource = $parsed['path'] ?? '';

Expand Down
33 changes: 30 additions & 3 deletions src/Client/ClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,41 @@
namespace Dflydev\Hawk\Client;

use Dflydev\Hawk\Credentials\CredentialsInterface;
use Dflydev\Hawk\Header\FieldValueParserException;
use Dflydev\Hawk\Header\NotHawkAuthorizationException;

interface ClientInterface
{
public function createRequest(CredentialsInterface $credentials, string $uri, string $method, array $options = []);
/**
* @param array{
* timestamp?: int,
* nonce?: string,
* payload?: mixed,
* content_type?: string,
* ext?: string,
* app?: string,
* dlg?: string,
* } $options
*/
public function createRequest(
CredentialsInterface $credentials,
string $uri,
string $method,
array $options = []
): Request;

/**
* @param array{
* payload?: mixed,
* content_type?: string,
* } $options
* @throws FieldValueParserException
* @throws NotHawkAuthorizationException
*/
public function authenticate(
CredentialsInterface $credentials,
Request $request,
$headerObjectOrString,
mixed $headerObjectOrString,
array $options = []
);
): bool;
}
3 changes: 3 additions & 0 deletions src/Credentials/CallbackCredentialsProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

class CallbackCredentialsProvider implements CredentialsProviderInterface
{
/**
* @param callable(string): CredentialsInterface $callback
*/
public function __construct(private $callback)
{
}
Expand Down
48 changes: 24 additions & 24 deletions src/Crypto/Artifacts.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,77 +8,77 @@
class Artifacts
{
public function __construct(
private $method,
private $host,
private $port,
private $resource,
private $timestamp,
private $nonce,
private $ext = null,
private $payload = null,
private $contentType = null,
private $hash = null,
private $app = null,
private $dlg = null
private string $method,
private string $host,
private int $port,
private mixed $resource,
private int $timestamp,
private string $nonce,
private ?string $ext = null,
private mixed $payload = null,
private ?string $contentType = null,
private ?string $hash = null,
private ?string $app = null,
private ?string $dlg = null
) {
}

public function timestamp()
public function timestamp(): int
{
return $this->timestamp;
}

public function nonce()
public function nonce(): string
{
return $this->nonce;
}

public function ext()
public function ext(): ?string
{
return $this->ext;
}

public function payload()
public function payload(): mixed
{
return $this->payload;
}

public function contentType()
public function contentType(): string
{
return $this->contentType;
}

public function hash()
public function hash(): ?string
{
return $this->hash;
}

public function app()
public function app(): ?string
{
return $this->app;
}

public function dlg()
public function dlg(): ?string
{
return $this->dlg;
}

public function resource()
public function resource(): mixed
{
return $this->resource;
}

public function host()
public function host(): string
{
return $this->host;
}

public function port()
public function port(): int
{
return $this->port;
}

public function method()
public function method(): string
{
return $this->method;
}
Expand Down
12 changes: 6 additions & 6 deletions src/Crypto/Crypto.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ class Crypto
{
public const HEADER_VERSION = 1;

public function calculatePayloadHash(string $payload, $algorithm, $contentType): string
public function calculatePayloadHash(string $payload, string $algorithm, string $contentType): string
{
[$contentType] = explode(';', (string) $contentType);
[$contentType] = explode(';', $contentType);
$contentType = strtolower(trim($contentType));

$normalized = 'hawk.' . self::HEADER_VERSION . '.payload' . "\n" .
$contentType . "\n" .
$payload . "\n";

return base64_encode(hash((string) $algorithm, $normalized, true));
return base64_encode(hash($algorithm, $normalized, true));
}

public function calculateMac(string $type, CredentialsInterface $credentials, Artifacts $attributes): string
Expand Down Expand Up @@ -50,14 +50,14 @@ public function calculateTsMac(int $timestamp, CredentialsInterface $credentials
));
}

public function fixedTimeComparison($a, $b): bool
public function fixedTimeComparison(string $a, string $b): bool
{
$mismatch = strlen((string) $a) === strlen((string) $b) ? 0 : 1;
$mismatch = strlen($a) === strlen($b) ? 0 : 1;
if ($mismatch !== 0) {
$b = $a;
}

for ($i = 0; $i < strlen((string) $a); $i++) {
for ($i = 0; $i < strlen($a); $i++) {
$ac = $a[$i];
$bc = $b[$i];
$mismatch += $ac === $bc ? 0 : 1;
Expand Down
9 changes: 8 additions & 1 deletion src/Header/Header.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

class Header
{
/**
* @param array<string, mixed> $attributes
*/
public function __construct(
private string $fieldName,
private string $fieldValue,
Expand All @@ -21,6 +24,10 @@ public function fieldValue(): string
return $this->fieldValue;
}

/**
* @param string[]|null $keys
* @return array<string, mixed>
*/
public function attributes(array $keys = null): array
{
if (null === $keys) {
Expand All @@ -37,7 +44,7 @@ public function attributes(array $keys = null): array
return $attributes;
}

public function attribute($key): ?string
public function attribute(string $key): mixed
{
return $this->attributes[$key] ?? null;
}
Expand Down
24 changes: 20 additions & 4 deletions src/Header/HeaderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

class HeaderFactory
{
public static function create($fieldName, array $attributes = null): Header
/**
* @param array<string, string>|null $attributes
*/
public static function create(string $fieldName, array $attributes = null): Header
{
$fieldValue = 'Hawk';

Expand All @@ -22,16 +25,29 @@ public static function create($fieldName, array $attributes = null): Header
return new Header($fieldName, $fieldValue, $attributes);
}

public static function createFromString($fieldName, $fieldValue, array $requiredKeys = null): Header
/**
* @param string[]|null $requiredKeys
* @throws FieldValueParserException
* @throws NotHawkAuthorizationException
*/
public static function createFromString(string $fieldName, string $fieldValue, array $requiredKeys = null): Header
{
return static::create(
$fieldName,
HeaderParser::parseFieldValue($fieldValue, $requiredKeys)
);
}

public static function createFromHeaderObjectOrString($fieldName, $headerObjectOrString, $onError)
{
/**
* @param callable(): void $onError
* @throws FieldValueParserException
* @throws NotHawkAuthorizationException
*/
public static function createFromHeaderObjectOrString(
string $fieldName,
mixed $headerObjectOrString,
callable $onError
): Header|string|null {
if (is_string($headerObjectOrString)) {
return static::createFromString($fieldName, $headerObjectOrString);
} elseif ($headerObjectOrString instanceof Header) {
Expand Down
10 changes: 7 additions & 3 deletions src/Header/HeaderParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@

class HeaderParser
{
public static function parseFieldValue($fieldValue, array $requiredKeys = null): array
/**
* @param string[]|null $requiredKeys
* @return array<string, string>
*/
public static function parseFieldValue(string $fieldValue, array $requiredKeys = null): array
{
if (!str_starts_with((string) $fieldValue, 'Hawk')) {
if (!str_starts_with($fieldValue, 'Hawk')) {
throw new NotHawkAuthorizationException();
}

$attributes = [];
$fieldValue = substr((string) $fieldValue, 5);
$fieldValue = substr($fieldValue, 5);
foreach (explode(', ', $fieldValue) as $part) {
$equalsPos = strpos($part, '=');
$key = substr($part, 0, $equalsPos);
Expand Down
Loading