Skip to content

Commit

Permalink
#51 Support access token auth (#55)
Browse files Browse the repository at this point in the history
#51 Support access token auth
  • Loading branch information
LeJeanbono authored Oct 13, 2021
1 parent 8fbcd2e commit 9ce4076
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 46 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Many of the options are optional since they can be added directly to the `compos
[--src-url=<URL of the source code repository which will be added to source tag of composer package>]\
[--src-ref=<The reference to the current code version for this package which will be added to source tag of composer package>]\
[--ssl-verify=true/]\
[--access-token=<ACCESS_TOKEN added in Bearer>]
<version>

# Example
Expand Down
9 changes: 9 additions & 0 deletions src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,15 @@ public function getType()
return $type;
}

/**
* Return the access token
* @return string
*/
public function getAccessToken()
{
return $this->input->getOption('access-token');
}

/**
* @return boolean
*/
Expand Down
1 change: 1 addition & 0 deletions src/PushCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ protected function configure()
new InputOption('keep-vendor', null, InputOption::VALUE_NONE, 'Keep vendor directory when creating zip'),
new InputOption('keep-dot-files', null, InputOption::VALUE_NONE, 'Keep dots files/dirs when creating zip'),
new InputOption('ssl-verify', null, InputOption::VALUE_OPTIONAL, 'Enable (true) or disable (false) the SSL verification'),
new InputOption('access-token', null, InputOption::VALUE_OPTIONAL, 'Access Token to get authenticated with'),
])
->setHelp(
<<<EOT
Expand Down
59 changes: 51 additions & 8 deletions src/RepositoryProvider/AbstractProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ public function sendFile(
];
}

if ($this->getConfiguration()->getAccessToken()) {
$credentials['access_token']['token'] = $this->getConfiguration()->getAccessToken();
}

if (preg_match(
'{^(?:https?)://([^/]+)(?:/.*)?}',
Expand All @@ -93,15 +96,15 @@ public function sendFile(
);

try {
if (empty($credential) || empty($credential['username']) || empty($credential['password'])) {
if (!empty($credential['token'])) {
$this->getIO()
->write(
'[postFile] Use no credentials',
'[postFile] Use ' . $type,
true,
IOInterface::VERY_VERBOSE
);
$this->postFile($filePath);
} else {
$this->postFileWithToken($filePath, $credential['token']);
} elseif (!empty($credential['username']) && !empty($credential['password'])) {
$this->getIO()
->write(
'[postFile] Use user ' . $credential['username'],
Expand All @@ -113,6 +116,14 @@ public function sendFile(
$credential['username'],
$credential['password']
);
} else {
$this->getIO()
->write(
'[postFile] Use no credentials',
true,
IOInterface::VERY_VERBOSE
);
$this->postFile($filePath);
}

return;
Expand Down Expand Up @@ -149,13 +160,45 @@ public function sendFile(
}

/**
* Post the given file
* Process the API call
* @param $file file to upload
* @param $options http call options
*/
abstract protected function apiCall($file, $options);

/**
* The file has to be uploaded by hand because of composer limitations
* (impossible to use Guzzle functions.php file in a composer plugin).
*
* @param $file
* @param $username
* @param $password
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function postFile($file, $username = null, $password = null)
{
$options = [];

if (!empty($username) && !empty($password)) {
$options['auth'] = [$username, $password];
}

$this->apiCall($file, $options);
}

/**
* Post the given file with access token
* @param $file
* @param null $username
* @param null $password
* @param string $token
* @return mixed
*/
abstract protected function postFile($file, $username = null, $password = null);
protected function postFileWithToken($file, $token)
{
$options = [];
$options['headers']['Authorization'] = 'Bearer ' . $token;
$this->apiCall($file, $options);
}

/**
* @return Configuration
Expand Down
25 changes: 6 additions & 19 deletions src/RepositoryProvider/ArtifactoryProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,15 @@ public function getUrl()
}

/**
* The file has to be uploaded by hand because of composer limitations
* (impossible to use Guzzle functions.php file in a composer plugin).
*
* @param $file
* @param $username
* @param $password
*
* @throws \GuzzleHttp\Exception\GuzzleException
* Process the API call
* @param $file file to upload
* @param $options http call options
*/
protected function postFile($file, $username = null, $password = null)
protected function apiCall($file, $options)
{
$options['debug'] = $this->getIO()->isVeryVerbose();
$options['body'] = fopen($file, 'r');
$url = $this->getUrl() . '.' . pathinfo($file, PATHINFO_EXTENSION) . '?properties=composer.version=' . $this->getConfiguration()->getVersion();

$options = [
'debug' => $this->getIO()->isVeryVerbose(),
'body' => fopen($file, 'r')
];

if (!empty($username) && !empty($password)) {
$options['auth'] = [$username, $password];
}

$this->getClient()->request('PUT', $url, $options);
}
}
22 changes: 6 additions & 16 deletions src/RepositoryProvider/NexusProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,20 @@ public function getUrl()
}

/**
* The file has to be uploaded by hand because of composer limitations
* (impossible to use Guzzle functions.php file in a composer plugin).
*
* @param $file
* @param $username
* @param $password
*
* @throws \GuzzleHttp\Exception\GuzzleException
* Process the API call
* @param $file file to upload
* @param $options http call options
*/
protected function postFile($file, $username = null, $password = null)
protected function apiCall($file, $options)
{
$url = $this->getUrl();

$sourceType = $this->getConfiguration()->getSourceType();
$sourceUrl = $this->getConfiguration()->getSourceUrl();
$sourceReference = $this->getConfiguration()->getSourceReference();

$options = [
'debug' => $this->getIO()->isVeryVerbose(),
];
$options['debug'] = $this->getIO()->isVeryVerbose();

if (!empty($sourceType) && !empty($sourceUrl) && !empty($sourceReference)) {
$options['multipart'] = [
[
Expand All @@ -73,10 +67,6 @@ protected function postFile($file, $username = null, $password = null)
$options['body'] = fopen($file, 'r');
}

if (!empty($username) && !empty($password)) {
$options['auth'] = [$username, $password];
}

$this->getClient()->request('PUT', $url, $options);
}
}
7 changes: 7 additions & 0 deletions tests/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ public function testGetSourceType()
$this->assertEquals('my-src-type', $this->configuration->getSourceType());
}

public function testGetAccessToken()
{
$this->assertEquals('my-token', $this->configuration->getAccessToken());
}

public function testGetUrl()
{
$this->assertEquals('https://option-url.com', $this->configuration->getUrl());
Expand Down Expand Up @@ -267,6 +272,8 @@ private function createInputMock()
return $this->configType;
case 'ssl-verify':
return $this->configVerifySsl;
case 'access-token':
return 'my-token';
}
});

Expand Down
38 changes: 35 additions & 3 deletions tests/RepositoryProvider/NexusProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,15 @@ public function testSendFileWithMultipleCredentials()
$configurationMock->method('get')->willReturnCallback(function($parameter) {
switch($parameter) {
case 'username':
return 'admin';
return '';
case 'password':
return 'my-password';
return '';
case 'access-token':
return '';
}
});

$mock = new MockHandler([
new Response(401),
new Response(200)
]);
$handlerStack = HandlerStack::create($mock);
Expand Down Expand Up @@ -223,6 +224,37 @@ public function testSendFileWithBadCredentials()
$nexusProvider->sendFile($this->getFilePath());
}

/**
* @covers \Elendev\ComposerPush\RepositoryProvider\NexusProvider::sendFile
*/
public function testSendFileWithAccessToken()
{
$configurationMock = $this->createBaseConfigurationMock();
$ioMock = $this->createMock(IOInterface::class);
$configurationMock->method('getAccessToken')->willReturn('my-token');

$mock = new MockHandler([
new Response(200)
]);
$handlerStack = HandlerStack::create($mock);
$client = new Client(['handler' => $handlerStack]);

$nexusProvider = new NexusProvider($configurationMock, $ioMock, $client);

$nexusProvider->sendFile($this->getFilePath());

$request = $mock->getLastRequest();

$this->assertEquals('https', $request->getUri()->getScheme());
$this->assertEquals('example.com', $request->getUri()->getHost());
$this->assertEquals('/my-repository/packages/upload/my-package/2.1.0', $request->getUri()->getPath());
$this->assertEquals('PUT', $request->getMethod());

$this->assertEquals('Bearer my-token', $request->getHeader('Authorization')[0]);

$this->assertEquals('Simple test file to push.', $request->getBody()->getContents());
}

/**
* Create a base configuration mock
* @return Configuration|\PHPUnit\Framework\MockObject\MockObject
Expand Down

0 comments on commit 9ce4076

Please sign in to comment.