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
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Changed
- Revert support for token auth, added in v5.2.0.
- Label username and password for clientId and clientSecret. No param changes.

## [5.2.0] - 2025-06-25
### Added
- Support for API token authentication. Username and password can still be used
as a fallback.
- ~~Support for API token authentication. Username and password can still be used
as a fallback.~~ Reverted in v5.2.1.
### Changed
- Deprecate `getConfig()` method. Packages can maintain their config internally.

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ $ composer require maxemail/api-php
```php
// Instantiate Client:
$config = [
'token' => 'apitoken',
'username' => 'client ID',
'password' => 'client secret'
];
$api = new \Maxemail\Api\Client($config);

Expand Down
3 changes: 2 additions & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
<!-- Configuration to enable functional tests -->
<env name="FUNC_ENABLED" value="false" />
<env name="FUNC_API_URI" value="https://mxm.xtremepush.com/" />
<env name="FUNC_API_TOKEN" value="apitoken" />
<env name="FUNC_API_USERNAME" value="clientId" />
<env name="FUNC_API_PASSWORD" value="clientSecret" />
</php>

<testsuites>
Expand Down
52 changes: 18 additions & 34 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ class Client implements \Psr\Log\LoggerAwareInterface
*/
private $uri = 'https://mxm.xtremepush.com/';

/**
* @var string
*/
private $token;

/**
* @var string
*/
Expand Down Expand Up @@ -113,9 +108,8 @@ class Client implements \Psr\Log\LoggerAwareInterface

/**
* @param array $config {
* @var string $token Required, or username & password
* @var string $username Required, if no token
* @var string $password Required, if no token
* @var string $username Required; API client ID
* @var string $password Required; API client secret
* @var string $uri Optional. Default https://mxm.xtremepush.com/
* @var string $user @deprecated See username
* @var string $pass @deprecated See password
Expand All @@ -124,25 +118,20 @@ class Client implements \Psr\Log\LoggerAwareInterface
*/
public function __construct(array $config)
{
// Must have API token
if (!isset($config['token'])) {
// Support deprecated key names from v3
if (!isset($config['username']) && isset($config['user'])) {
$config['username'] = $config['user'];
}
if (!isset($config['password']) && isset($config['pass'])) {
$config['password'] = $config['pass'];
}
// Support deprecated key names from v3
if (!isset($config['username']) && isset($config['user'])) {
$config['username'] = $config['user'];
}
if (!isset($config['password']) && isset($config['pass'])) {
$config['password'] = $config['pass'];
}

// Must have user/pass
if (!isset($config['username']) || !isset($config['password'])) {
throw new Exception\InvalidArgumentException('API config requires token OR username & password');
}
$this->username = $config['username'];
$this->password = $config['password'];
} else {
$this->token = $config['token'];
// Must have user/pass
if (!isset($config['username']) || !isset($config['password'])) {
throw new Exception\InvalidArgumentException('API config requires username & password');
}
$this->username = $config['username'];
$this->password = $config['password'];

if (isset($config['uri'])) {
$parsed = parse_url($config['uri']);
Expand Down Expand Up @@ -186,6 +175,10 @@ private function getClient(): GuzzleClientInterface

$clientConfig = [
'base_uri' => $this->uri . 'api/json/',
'auth' => [
$this->username,
$this->password,
],
'headers' => [
'User-Agent' => 'MxmApiClient/' . self::VERSION . ' PHP/' . PHP_VERSION,
'Content-Type' => 'application/x-www-form-urlencoded',
Expand All @@ -194,15 +187,6 @@ private function getClient(): GuzzleClientInterface
'handler' => $stack,
];

if (isset($this->token)) {
$clientConfig['headers']['Authorization'] = 'Bearer ' . $this->token;
} else {
$clientConfig['auth'] = [
$this->username,
$this->password,
];
}

if (!isset($this->httpClientFactory)) {
$this->httpClient = new GuzzleClient($clientConfig);
} else {
Expand Down
86 changes: 22 additions & 64 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class ClientTest extends TestCase
{
private $testConfig = [
'uri' => 'https://maxemail.example.com/',
'token' => 'apitoken',
'username' => 'clientId',
'password' => 'clientSecret',
];

public function testConfigValid()
Expand All @@ -30,11 +31,16 @@ public function testConfigValid()
$expectedUri = $this->testConfig['uri'] . 'api/json/';
static::assertSame($expectedUri, $actual['base_uri']);

$expectedAuth = [
$this->testConfig['username'],
$this->testConfig['password'],
];
static::assertSame($expectedAuth, $actual['auth']);

$expectedHeaders = [
'User-Agent' => 'MxmApiClient/' . Client::VERSION . ' PHP/' . PHP_VERSION,
'Content-Type' => 'application/x-www-form-urlencoded',
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $this->testConfig['token'],
];
static::assertSame($expectedHeaders, $actual['headers']);

Expand Down Expand Up @@ -75,7 +81,8 @@ public function testConfigSupportDeprecatedUserPass()
public function testConfigDefaultHost()
{
$config = [
'token' => 'apitoken',
'username' => 'clientId',
'password' => 'clientSecret',
];

$api = new Client($config);
Expand All @@ -97,7 +104,8 @@ public function testConfigStripsUriPath()
{
$config = [
'uri' => 'https://maxemail.example.com/some/extra/path',
'token' => 'apitoken',
'username' => 'clientId',
'password' => 'clientSecret',
];

$api = new Client($config);
Expand All @@ -122,7 +130,8 @@ public function testConfigInvalidUri()

$config = [
'uri' => '//',
'token' => 'apitoken',
'username' => 'clientId',
'password' => 'clientSecret',
];

new Client($config);
Expand All @@ -135,52 +144,20 @@ public function testConfigMissingUriProtocol()

$config = [
'uri' => 'maxemail.example.com',
'token' => 'apitoken',
'username' => 'clientId',
'password' => 'clientSecret',
];

new Client($config);
}

public function testConfigLegacyAuthentication(): void
{
$config = [
'username' => 'api@user.com',
'password' => 'apipass',
];

$api = new Client($config);

$factory = function (array $actual) use ($config): GuzzleClient {
$expectedAuth = [
$config['username'],
$config['password'],
];
static::assertSame($expectedAuth, $actual['auth']);

return $this->createMock(GuzzleClient::class);
};

$api->setHttpClientFactory($factory);

// Get a service, to trigger the HTTP Client factory
$api->folder;
}

public function testConfigMissingToken(): void
{
$this->expectException(Exception\InvalidArgumentException::class);
$this->expectExceptionMessage('API config requires token OR username & password');

new Client([]);
}

public function testConfigMissingUsername(): void
{
$this->expectException(Exception\InvalidArgumentException::class);
$this->expectExceptionMessage('API config requires token OR username & password');
$this->expectExceptionMessage('API config requires username & password');

$config = [
'password' => 'apipass',
'password' => 'clientSecret',
];

new Client($config);
Expand All @@ -189,39 +166,20 @@ public function testConfigMissingUsername(): void
public function testConfigMissingPassword(): void
{
$this->expectException(Exception\InvalidArgumentException::class);
$this->expectExceptionMessage('API config requires token OR username & password');
$this->expectExceptionMessage('API config requires username & password');

$config = [
'username' => 'api@user.com',
'username' => 'clientId',
];

new Client($config);
}

public function testGetConfigWithToken(): void
public function testGetConfig(): void
{
$api = new Client($this->testConfig);

$expected = [
'uri' => $this->testConfig['uri'],
'username' => null,
'password' => null,
];

static::assertSame($expected, $api->getConfig());
}

public function testGetConfigWithLegacyAuthentication(): void
{
$config = [
'uri' => 'https://maxemail.example.com/',
'username' => 'api@user.com',
'password' => 'apipass',
];

$api = new Client($config);

static::assertSame($config, $api->getConfig());
static::assertSame($this->testConfig, $api->getConfig());
}

public function testSetGetLogger()
Expand Down
3 changes: 2 additions & 1 deletion tests/FunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ protected function setUp(): void

$config = [
'uri' => getenv('FUNC_API_URI'),
'token' => getenv('FUNC_API_TOKEN'),
'username' => getenv('FUNC_API_USERNAME'),
'password' => getenv('FUNC_API_PASSWORD'),
];
$this->client = new Client($config);
}
Expand Down