Skip to content

Commit

Permalink
Add auth header error handling (#250)
Browse files Browse the repository at this point in the history
* Allow WP_Error return from get_request_headers()
* Bubble auth errors from get_request_headers() in Salesforce integration queries
* Early return error in Google Sheets' get_request_headers()
* Fix phpcs errors from "useless @inheritdoc."

---------

Co-authored-by: Max Schmeling <max.schmeling@automattic.com>
  • Loading branch information
alecgeatches and maxschmeling authored Dec 17, 2024
1 parent e933244 commit 2534f64
Show file tree
Hide file tree
Showing 19 changed files with 63 additions and 45 deletions.
2 changes: 1 addition & 1 deletion docs/extending/data-source.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class ZipCodeDataSource extends HttpDataSource {
return 'https://api.zippopotam.us/us/';
}

public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
return [
'Content-Type' => 'application/json',
];
Expand Down
2 changes: 1 addition & 1 deletion docs/extending/query.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ By default, the `get_request_headers` method proxies to the `get_request_headers
### Example

```php
public function get_request_headers( array $input_variables ): array {
public function get_request_headers( array $input_variables ): array|WP_Error {
return array_merge(
$this->get_data_source()->get_request_headers(),
[ 'X-Product-ID' => $input_variables['product_id'] ]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace RemoteDataBlocks\Example\ArtInstituteOfChicago;

use RemoteDataBlocks\Config\DataSource\HttpDataSource;
use WP_Error;

class ArtInstituteOfChicagoDataSource extends HttpDataSource {
public function get_display_name(): string {
Expand All @@ -13,7 +14,7 @@ public function get_endpoint(): string {
return 'https://api.artic.edu/api/v1/artworks';
}

public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
return [
'Content-Type' => 'application/json',
];
Expand Down
5 changes: 1 addition & 4 deletions inc/Config/DataSource/HttpDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ abstract public function get_display_name(): string;

abstract public function get_endpoint(): string;

/**
* @inheritDoc
*/
abstract public function get_request_headers(): array;
abstract public function get_request_headers(): array|WP_Error;

public function get_image_url(): ?string {
return null;
Expand Down
4 changes: 3 additions & 1 deletion inc/Config/DataSource/HttpDataSourceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace RemoteDataBlocks\Config\DataSource;

use WP_Error;

/**
* HttpDataSourceInterface
*
Expand Down Expand Up @@ -38,5 +40,5 @@ public function get_endpoint(): string;
*
* @return array Associative array of request headers.
*/
public function get_request_headers(): array;
public function get_request_headers(): array|WP_Error;
}
3 changes: 2 additions & 1 deletion inc/Config/QueryContext/HttpQueryContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use RemoteDataBlocks\Config\QueryRunner\QueryRunnerInterface;
use RemoteDataBlocks\Validation\Validator;
use RemoteDataBlocks\Validation\ValidatorInterface;
use WP_Error;

defined( 'ABSPATH' ) || exit();

Expand Down Expand Up @@ -175,7 +176,7 @@ public function get_request_method(): string {
*
* @param array $input_variables The input variables for this query.
*/
public function get_request_headers( array $input_variables ): array {
public function get_request_headers( array $input_variables ): array|WP_Error {
return $this->get_data_source()->get_request_headers();
}

Expand Down
4 changes: 3 additions & 1 deletion inc/Config/QueryContext/HttpQueryContextInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace RemoteDataBlocks\Config\QueryContext;

use WP_Error;

/**
* HttpQueryContextInterface interface
*
Expand All @@ -10,6 +12,6 @@ interface HttpQueryContextInterface {
public function get_cache_ttl( array $input_variables ): null|int;
public function get_endpoint( array $input_variables ): string;
public function get_request_method(): string;
public function get_request_headers( array $input_variables ): array;
public function get_request_headers( array $input_variables ): array|WP_Error;
public function get_request_body( array $input_variables ): array|null;
}
5 changes: 5 additions & 0 deletions inc/Config/QueryRunner/QueryRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public function __construct(
*/
protected function get_request_details( array $input_variables ): array|WP_Error {
$headers = $this->query_context->get_request_headers( $input_variables );

if ( is_wp_error( $headers ) ) {
return $headers;
}

$method = $this->query_context->get_request_method();
$body = $this->query_context->get_request_body( $input_variables );
$endpoint = $this->query_context->get_endpoint( $input_variables );
Expand Down
6 changes: 2 additions & 4 deletions inc/ExampleApi/Queries/ExampleApiDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace RemoteDataBlocks\ExampleApi\Queries;

use RemoteDataBlocks\Config\DataSource\HttpDataSource;
use WP_Error;

/**
* This is a placeholder DataSource used only to represent the data source in the
Expand All @@ -21,10 +22,7 @@ public function get_endpoint(): string {
return '';
}

/**
* @inheritDoc
*/
public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
return [];
}
}
3 changes: 2 additions & 1 deletion inc/Integrations/Airtable/AirtableDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace RemoteDataBlocks\Integrations\Airtable;

use RemoteDataBlocks\Config\DataSource\HttpDataSource;
use WP_Error;

class AirtableDataSource extends HttpDataSource {
protected const SERVICE_SCHEMA_VERSION = 1;
Expand Down Expand Up @@ -82,7 +83,7 @@ public function get_endpoint(): string {
return 'https://api.airtable.com/v0/' . $this->config['base']['id'];
}

public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
return [
'Authorization' => sprintf( 'Bearer %s', $this->config['access_token'] ),
'Content-Type' => 'application/json',
Expand Down
3 changes: 2 additions & 1 deletion inc/Integrations/GenericHttp/GenericHttpDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace RemoteDataBlocks\Integrations\GenericHttp;

use RemoteDataBlocks\Config\DataSource\HttpDataSource;
use WP_Error;

class GenericHttpDataSource extends HttpDataSource {
protected const SERVICE_NAME = REMOTE_DATA_BLOCKS_GENERIC_HTTP_SERVICE;
Expand Down Expand Up @@ -62,7 +63,7 @@ public function get_endpoint(): string {
return $this->config['url'];
}

public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
return [
'Accept' => 'application/json',
];
Expand Down
3 changes: 2 additions & 1 deletion inc/Integrations/GitHub/GitHubDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace RemoteDataBlocks\Integrations\GitHub;

use RemoteDataBlocks\Config\DataSource\HttpDataSource;
use WP_Error;

class GitHubDataSource extends HttpDataSource {
protected const SERVICE_NAME = REMOTE_DATA_BLOCKS_GITHUB_SERVICE;
Expand Down Expand Up @@ -42,7 +43,7 @@ public function get_endpoint(): string {
);
}

public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
return [
'Accept' => 'application/vnd.github+json',
];
Expand Down
6 changes: 5 additions & 1 deletion inc/Integrations/Google/Sheets/GoogleSheetsDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,16 @@ public function get_endpoint(): string {
return sprintf( 'https://sheets.googleapis.com/v4/spreadsheets/%s', $this->config['spreadsheet']['id'] );
}

public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
$access_token = GoogleAuth::generate_token_from_service_account_key(
$this->config['credentials'],
GoogleAuth::GOOGLE_SHEETS_SCOPES
);

if ( is_wp_error( $access_token ) ) {
return $access_token;
}

return [
'Authorization' => sprintf( 'Bearer %s', $access_token ),
'Content-Type' => 'application/json',
Expand Down
17 changes: 12 additions & 5 deletions inc/Integrations/SalesforceB2C/Auth/SalesforceB2CAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,28 @@ class SalesforceB2CAuth {
* @param string $organization_id The organization ID for the data source.
* @param string $client_id The client ID (a version 4 UUID).
* @param string $client_secret The client secret.
* @return WP_Error|string The token or an error.
* @return string|WP_Error The token or an error.
*/
public static function generate_token(
string $endpoint,
string $organization_id,
string $client_id,
string $client_secret
): WP_Error|string {
): string|WP_Error {
$saved_access_token = self::get_saved_access_token( $organization_id, $client_id );

if ( null !== $saved_access_token ) {
return $saved_access_token;
}

$access_token = null;

$saved_refresh_token = self::get_saved_refresh_token( $organization_id, $client_id );
if ( null !== $saved_refresh_token ) {
$access_token = self::get_token_using_refresh_token( $saved_refresh_token, $client_id, $client_secret, $endpoint, $organization_id );
}

if ( null !== $access_token ) {
if ( null !== $access_token && ! is_wp_error( $access_token ) ) {
return $access_token;
}

Expand Down Expand Up @@ -123,16 +125,21 @@ public static function get_token_using_refresh_token(
],
]);

$refresh_token_error = new WP_Error(
'salesforce_b2c_auth_error_refresh_token',
__( 'Failed to refresh authorization with refresh token', 'remote-data-blocks' )
);

if ( is_wp_error( $client_auth_response ) ) {
return null;
return $refresh_token_error;
}

$response_code = wp_remote_retrieve_response_code( $client_auth_response );
$response_body = wp_remote_retrieve_body( $client_auth_response );
$response_data = json_decode( $response_body, true );

if ( 400 === $response_code ) {
return null;
return $refresh_token_error;
}

$access_token = $response_data['access_token'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use RemoteDataBlocks\Config\QueryContext\HttpQueryContext;
use RemoteDataBlocks\Integrations\SalesforceB2C\Auth\SalesforceB2CAuth;
use WP_Error;

class SalesforceB2CGetProductQuery extends HttpQueryContext {

Expand Down Expand Up @@ -60,7 +61,7 @@ public function get_output_schema(): array {
];
}

public function get_request_headers( array $input_variables ): array {
public function get_request_headers( array $input_variables ): array|WP_Error {
$data_source_config = $this->get_data_source()->to_array();
$data_source_endpoint = $this->get_data_source()->get_endpoint();

Expand All @@ -71,16 +72,14 @@ public function get_request_headers( array $input_variables ): array {
$data_source_config['client_secret']
);

$headers = [
'Content-Type' => 'application/json',
];

if ( is_wp_error( $access_token ) ) {
return $headers;
return $access_token;
}

$headers['Authorization'] = sprintf( 'Bearer %s', $access_token );
return $headers;
return [
'Content-Type' => 'application/json',
'Authorization' => sprintf( 'Bearer %s', $access_token ),
];
}

public function get_endpoint( array $input_variables ): string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use RemoteDataBlocks\Config\QueryContext\HttpQueryContext;
use RemoteDataBlocks\Integrations\SalesforceB2C\Auth\SalesforceB2CAuth;
use WP_Error;

class SalesforceB2CSearchProductsQuery extends HttpQueryContext {
public function get_input_schema(): array {
Expand Down Expand Up @@ -55,7 +56,7 @@ public function get_endpoint( array $input_variables ): string {
);
}

public function get_request_headers( array $input_variables ): array {
public function get_request_headers( array $input_variables ): array|WP_Error {
$data_source_config = $this->get_data_source()->to_array();
$data_source_endpoint = $this->get_data_source()->get_endpoint();

Expand All @@ -66,16 +67,14 @@ public function get_request_headers( array $input_variables ): array {
$data_source_config['client_secret']
);

$headers = [
'Content-Type' => 'application/json',
];

if ( is_wp_error( $access_token ) ) {
return $headers;
return $access_token;
}

$headers['Authorization'] = sprintf( 'Bearer %s', $access_token );
return $headers;
return [
'Content-Type' => 'application/json',
'Authorization' => sprintf( 'Bearer %s', $access_token ),
];
}

public function get_query_name(): string {
Expand Down
3 changes: 2 additions & 1 deletion inc/Integrations/SalesforceB2C/SalesforceB2CDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace RemoteDataBlocks\Integrations\SalesforceB2C;

use RemoteDataBlocks\Config\DataSource\HttpDataSource;
use WP_Error;

use function plugins_url;

Expand Down Expand Up @@ -42,7 +43,7 @@ public function get_endpoint(): string {
return sprintf( 'https://%s.api.commercecloud.salesforce.com', $this->config['shortcode'] );
}

public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
return [
'Content-Type' => 'application/json',
];
Expand Down
3 changes: 2 additions & 1 deletion inc/Integrations/Shopify/ShopifyDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace RemoteDataBlocks\Integrations\Shopify;

use RemoteDataBlocks\Config\DataSource\HttpDataSource;
use WP_Error;

use function plugins_url;

Expand Down Expand Up @@ -40,7 +41,7 @@ public function get_endpoint(): string {
return 'https://' . $this->config['store_name'] . '.myshopify.com/api/2024-04/graphql.json';
}

public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
return [
'Content-Type' => 'application/json',
'X-Shopify-Storefront-Access-Token' => $this->config['access_token'],
Expand Down
6 changes: 2 additions & 4 deletions tests/inc/Mocks/MockDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace RemoteDataBlocks\Tests\Mocks;

use RemoteDataBlocks\Config\DataSource\HttpDataSource;
use WP_Error;

class MockDataSource extends HttpDataSource {
private $endpoint = 'https://example.com/api';
Expand Down Expand Up @@ -31,10 +32,7 @@ public function get_endpoint(): string {
return $this->endpoint;
}

/**
* @inheritDoc
*/
public function get_request_headers(): array {
public function get_request_headers(): array|WP_Error {
return $this->headers;
}

Expand Down

0 comments on commit 2534f64

Please sign in to comment.