generated from Firehed/php-library-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add more detail when errors occur (#24)
Adds several specific exceptions, including a CodedError with additional codes, to handle various configuration and runtime errors. This converts `ApiError` from a concrete class to an interface, which ensures that catch blocks following the documented best practices will continue to work as before. Fixes #23 In a real application, you'll now (typically) get back some actionable details. ![Screenshot 2024-09-25 at 12 23 03 PM](https://github.com/user-attachments/assets/9c357712-945e-4cb4-8365-3cf28f7b01ee)
- Loading branch information
Showing
15 changed files
with
329 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,8 +4,6 @@ | |
|
||
namespace SnapAuth; | ||
|
||
use Exception; | ||
|
||
class ApiError extends Exception | ||
interface ApiError | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SnapAuth; | ||
|
||
enum ErrorCode: string | ||
{ | ||
case AuthenticatingUserAccountNotFound = 'AuthenticatingUserAccountNotFound'; | ||
case EntityNotFound = 'EntityNotFound'; | ||
case HandleCannotChange = 'HandleCannotChange'; | ||
case HandleInUseByDifferentAccount = 'HandleInUseByDifferentAccount'; | ||
case InvalidAuthorizationHeader = 'InvalidAuthorizationHeader'; | ||
case InvalidInput = 'InvalidInput'; | ||
case PermissionViolation = 'PermissionViolation'; | ||
case PublishableKeyNotFound = 'PublishableKeyNotFound'; | ||
case RegisteredUserLimitReached = 'RegisteredUserLimitReached'; | ||
case SecretKeyExpired = 'SecretKeyExpired'; | ||
case SecretKeyNotFound = 'SecretKeyNotFound'; | ||
case TokenExpired = 'TokenExpired'; | ||
case TokenNotFound = 'TokenNotFound'; | ||
case UsingDeactivatedCredential = 'UsingDeactivatedCredential'; | ||
|
||
/** | ||
* This is a catch-all code if the API has returned an error code that's | ||
* unknown to this SDK. Often this means that a new SDK version will handle | ||
* the new code. | ||
*/ | ||
case Unknown = '(unknown)'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SnapAuth\Exception; | ||
|
||
use RuntimeException; | ||
use SnapAuth\{ | ||
ApiError, | ||
ErrorCode, | ||
}; | ||
|
||
use function sprintf; | ||
|
||
/** | ||
* The API returned a well-formed coded error message. Examine the $errorCode | ||
* property for additional information. | ||
*/ | ||
class CodedError extends RuntimeException implements ApiError | ||
{ | ||
public readonly ErrorCode $errorCode; | ||
|
||
/** | ||
* @param int $httpCode The HTTP status code of the error response | ||
* | ||
* @internal Constructing errors is not covered by BC | ||
*/ | ||
public function __construct(string $message, string $errorCode, int $httpCode) | ||
{ | ||
parent::__construct( | ||
message: sprintf( | ||
'[HTTP %d] %s: %s', | ||
$httpCode, | ||
$errorCode, | ||
$message, | ||
), | ||
code: $httpCode, | ||
); | ||
$this->errorCode = ErrorCode::tryFrom($errorCode) ?? ErrorCode::Unknown; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SnapAuth\Exception; | ||
|
||
use InvalidArgumentException; | ||
use SnapAuth\ApiError; | ||
|
||
class InvalidSecretKey extends InvalidArgumentException implements ApiError | ||
{ | ||
public function __construct() | ||
{ | ||
parent::__construct( | ||
message: 'Invalid secret key. Please verify you copied the full value from the SnapAuth dashboard.', | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SnapAuth\Exception; | ||
|
||
use RuntimeException; | ||
use SnapAuth\ApiError; | ||
|
||
use function sprintf; | ||
|
||
/** | ||
* A response arrived, but was not in an expected format | ||
*/ | ||
class MalformedResponse extends RuntimeException implements ApiError | ||
{ | ||
/** | ||
* @internal Constructing errors is not covered by BC | ||
*/ | ||
public function __construct(string $details, int $statusCode) | ||
{ | ||
parent::__construct( | ||
message: sprintf( | ||
'[HTTP %d] SnapAuth API returned data in an unexpected format: %s', | ||
$statusCode, | ||
$details, | ||
), | ||
code: $statusCode, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SnapAuth\Exception; | ||
|
||
use InvalidArgumentException; | ||
use SnapAuth\ApiError; | ||
|
||
class MissingSecretKey extends InvalidArgumentException implements ApiError | ||
{ | ||
public function __construct() | ||
{ | ||
parent::__construct( | ||
'Secret key missing. It can be explictly provided, or it can be ' . | ||
'auto-detected from the SNAPAUTH_SECRET_KEY environment variable.' | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SnapAuth\Exception; | ||
|
||
use RuntimeException; | ||
use SnapAuth\ApiError; | ||
|
||
/** | ||
* A network interruption occurred. | ||
*/ | ||
class Network extends RuntimeException implements ApiError | ||
{ | ||
/** | ||
* @param $code a cURL error code | ||
* | ||
* @internal Constructing errors is not covered by BC | ||
*/ | ||
public function __construct(int $code) | ||
{ | ||
$message = curl_strerror($code); | ||
parent::__construct( | ||
message: 'SnapAuth network error: ' . $message, | ||
code: $code, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SnapAuth\Exception; | ||
|
||
use SnapAuth\ErrorCode; | ||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use PHPUnit\Framework\Attributes\Small; | ||
use PHPUnit\Framework\MockObject\MockObject; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
#[CoversClass(CodedError::class)] | ||
#[Small] | ||
class CodedErrorTest extends TestCase | ||
{ | ||
public function testFormattingFromKnownErrorCode(): void | ||
{ | ||
$e = new CodedError('Missing parameter foo', 'InvalidInput', 400); | ||
self::assertSame(ErrorCode::InvalidInput, $e->errorCode); | ||
} | ||
|
||
public function testFormattingFromUnknownErrorCode(): void | ||
{ | ||
$e = new CodedError('Something bad happened', 'SevereError', 400); | ||
self::assertSame(ErrorCode::Unknown, $e->errorCode); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SnapAuth\Exception; | ||
|
||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use PHPUnit\Framework\Attributes\Small; | ||
use PHPUnit\Framework\MockObject\MockObject; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
#[CoversClass(InvalidSecretKey::class)] | ||
#[Small] | ||
class InvalidSecretKeyTest extends TestCase | ||
{ | ||
public function testConstruct(): void | ||
{ | ||
$e = new InvalidSecretKey(); | ||
self::assertStringContainsString('Invalid secret key', $e->getMessage()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SnapAuth\Exception; | ||
|
||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use PHPUnit\Framework\Attributes\Small; | ||
use PHPUnit\Framework\MockObject\MockObject; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
#[CoversClass(MalformedResponse::class)] | ||
#[Small] | ||
class MalformedResponseTest extends TestCase | ||
{ | ||
public function testConstruct(): void | ||
{ | ||
$e = new MalformedResponse('Invalid data', 503); | ||
self::assertStringContainsString('Invalid data', $e->getMessage()); | ||
self::assertSame(503, $e->getCode()); | ||
} | ||
} |
Oops, something went wrong.