Skip to content

Commit 56191e4

Browse files
committed
fixed lesstif#394 support personal access token based auth
1 parent ce4ab24 commit 56191e4

File tree

9 files changed

+160
-44
lines changed

9 files changed

+160
-44
lines changed

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ JIRA_LOG_FILE="jira-rest-client.log"
66
JIRA_LOG_LEVEL="WARNING"
77

88
JIRA_REST_API_V3=false
9+
10+
## if TOKEN_BASED_AUTH set to true, ignore JIRA_USER and JIRA_PASS.
11+
TOKEN_BASED_AUTH=true
12+
PERSONAL_ACCESS_TOKEN="your-access-token-here"

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ public/
3535
storage/
3636

3737
.phpunit.result.cache
38+
.env*
39+
.php_cs.cache

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ copy .env.example file to .env on your project root.
6565
JIRA_HOST="https://your-jira.host.com"
6666
JIRA_USER="jira-username"
6767
JIRA_PASS="jira-password-OR-api-token"
68+
# if TOKEN_BASED_AUTH set to true, ignore JIRA_USER and JIRA_PASS.
69+
TOKEN_BASED_AUTH=true
70+
PERSONAL_ACCESS_TOKEN="your-access-token-here"
6871
# to enable session cookie authorization
6972
# COOKIE_AUTH_ENABLED=true
7073
# COOKIE_FILE=storage/jira-cookie.txt

src/Configuration/AbstractConfiguration.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ abstract class AbstractConfiguration implements ConfigurationInterface
148148
/** @var int */
149149
protected $timeout;
150150

151+
/** @var boolean */
152+
protected $useTokenBasedAuth;
153+
154+
/** @var string */
155+
protected $personalAccessToken;
156+
151157
/**
152158
* @return string
153159
*/
@@ -345,4 +351,20 @@ public function getTimeout()
345351
{
346352
return $this->timeout;
347353
}
354+
355+
/**
356+
* @return bool
357+
*/
358+
public function isTokenBasedAuth()
359+
{
360+
return $this->useTokenBasedAuth;
361+
}
362+
363+
/**
364+
* @return string
365+
*/
366+
public function getPeronalAccessToken()
367+
{
368+
return $this->personalAccessToken;
369+
}
348370
}

src/Configuration/ArrayConfiguration.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ public function __construct(array $configuration)
3434

3535
$this->useV3RestApi = false;
3636

37+
$this->useTokenBasedAuth = false;
38+
$this->personalAccessToken = '';
39+
3740
foreach ($configuration as $key => $value) {
3841
if (property_exists($this, $key)) {
3942
$this->$key = $value;

src/Configuration/ConfigurationInterface.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,20 @@ public function getUseV3RestApi();
165165
* @return int
166166
*/
167167
public function getTimeout();
168+
169+
/**
170+
* check whether token based auth.
171+
*
172+
* @see https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html
173+
*
174+
* @return bool
175+
*/
176+
public function isTokenBasedAuth();
177+
178+
/**
179+
* Personal Access Token
180+
*
181+
* @return string
182+
*/
183+
public function getPeronalAccessToken();
168184
}

src/Configuration/DotEnvConfiguration.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ public function __construct($path = '.')
4343
$this->useV3RestApi = $this->env('JIRA_REST_API_V3', false);
4444

4545
$this->timeout = $this->env('JIRA_TIMEOUT', 30);
46+
47+
$this->useTokenBasedAuth = $this->env('TOKEN_BASED_AUTH', false);
48+
$this->personalAccessToken = $this->env('PERSONAL_ACCESS_TOKEN', false);
4649
}
4750

4851
/**
@@ -134,7 +137,7 @@ public function endsWith($haystack, $needles)
134137
private function loadDotEnv(string $path)
135138
{
136139
$requireParam = [
137-
'JIRA_HOST', 'JIRA_USER', 'JIRA_PASS',
140+
'JIRA_HOST', 'TOKEN_BASED_AUTH',
138141
];
139142

140143
// support for dotenv 1.x and 2.x. see also https://github.com/lesstif/php-jira-rest-client/issues/102

src/JiraClient.php

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,14 @@ public function exec($context, $post_data = null, $custom_request = null, $cooki
235235
}
236236
}
237237

238-
$this->authorization($ch, $cookieFile);
238+
// save HTTP Headers
239+
$curl_http_headers = [
240+
'Accept: */*',
241+
'Content-Type: application/json',
242+
'X-Atlassian-Token: no-check'
243+
];
244+
245+
$this->authorization($ch, $curl_http_headers, $cookieFile);
239246

240247
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->getConfiguration()->isCurlOptSslVerifyHost());
241248
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->getConfiguration()->isCurlOptSslVerifyPeer());
@@ -263,10 +270,11 @@ public function exec($context, $post_data = null, $custom_request = null, $cooki
263270
}
264271

265272
curl_setopt($ch, CURLOPT_ENCODING, '');
273+
266274
curl_setopt(
267275
$ch,
268276
CURLOPT_HTTPHEADER,
269-
['Accept: */*', 'Content-Type: application/json', 'X-Atlassian-Token: no-check']
277+
$curl_http_headers
270278
);
271279

272280
curl_setopt($ch, CURLOPT_VERBOSE, $this->getConfiguration()->isCurlOptVerbose());
@@ -316,11 +324,18 @@ public function exec($context, $post_data = null, $custom_request = null, $cooki
316324
*
317325
* @param string $url Request URL
318326
* @param string $upload_file Filename
327+
* @param resource $ch CUrl handler
319328
*
320329
* @return resource
321330
*/
322331
private function createUploadHandle($url, $upload_file, $ch)
323332
{
333+
$curl_http_headers = [
334+
'Accept: */*',
335+
'Content-Type: multipart/form-data',
336+
'X-Atlassian-Token: no-check'
337+
];
338+
324339
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
325340
curl_setopt($ch, CURLOPT_URL, $url);
326341

@@ -352,7 +367,7 @@ private function createUploadHandle($url, $upload_file, $ch)
352367
$this->log->debug('using CURLFile='.var_export($attachments, true));
353368
}
354369

355-
$this->authorization($ch);
370+
$this->authorization($ch, $curl_http_headers);
356371

357372
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->getConfiguration()->isCurlOptSslVerifyHost());
358373
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->getConfiguration()->isCurlOptSslVerifyPeer());
@@ -379,11 +394,8 @@ private function createUploadHandle($url, $upload_file, $ch)
379394
if (!function_exists('ini_get') || !ini_get('open_basedir')) {
380395
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
381396
}
382-
curl_setopt($ch, CURLOPT_HTTPHEADER, [
383-
'Accept: */*',
384-
'Content-Type: multipart/form-data',
385-
'X-Atlassian-Token: nocheck',
386-
]);
397+
398+
curl_setopt($ch, CURLOPT_HTTPHEADER, $curl_http_headers);
387399

388400
curl_setopt($ch, CURLOPT_VERBOSE, $this->getConfiguration()->isCurlOptVerbose());
389401

@@ -482,8 +494,10 @@ protected function createUrlByContext($context)
482494
* Add authorize to curl request.
483495
*
484496
* @param resource $ch
497+
* @param $curl_http_headers
498+
* @param null $cookieFile
485499
*/
486-
protected function authorization($ch, $cookieFile = null)
500+
protected function authorization($ch, &$curl_http_headers, $cookieFile = null)
487501
{
488502
// use cookie
489503
if ($this->getConfiguration()->isCookieAuthorizationEnabled()) {
@@ -499,9 +513,13 @@ protected function authorization($ch, $cookieFile = null)
499513

500514
// if cookie file not exist, using id/pwd login
501515
if (!file_exists($cookieFile)) {
502-
$username = $this->getConfiguration()->getJiraUser();
503-
$password = $this->getConfiguration()->getJiraPassword();
504-
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
516+
if ($this->getConfiguration()->isTokenBasedAuth() === true ){
517+
$curl_http_headers[] = 'Authorization: Bearer ' . $this->getConfiguration()->getPeronalAccessToken();
518+
} else {
519+
$username = $this->getConfiguration()->getJiraUser();
520+
$password = $this->getConfiguration()->getJiraPassword();
521+
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
522+
}
505523
}
506524
}
507525

@@ -566,6 +584,12 @@ public function toHttpQueryParameter(array $paramArray)
566584
*/
567585
public function download(string $url, string $outDir, string $file, string $cookieFile = null)
568586
{
587+
$curl_http_header = [
588+
'Accept: */*',
589+
'Content-Type: application/json',
590+
'X-Atlassian-Token: no-check'
591+
];
592+
569593
$file = fopen($outDir.DIRECTORY_SEPARATOR.urldecode($file), 'w');
570594

571595
curl_reset($this->curl);
@@ -576,7 +600,7 @@ public function download(string $url, string $outDir, string $file, string $cook
576600
// output to file handle
577601
curl_setopt($ch, CURLOPT_FILE, $file);
578602

579-
$this->authorization($ch, $cookieFile);
603+
$this->authorization($ch, $curl_http_header, $cookieFile);
580604

581605
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->getConfiguration()->isCurlOptSslVerifyHost());
582606
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->getConfiguration()->isCurlOptSslVerifyPeer());
@@ -604,18 +628,18 @@ public function download(string $url, string $outDir, string $file, string $cook
604628
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
605629
}
606630

631+
if ($this->isRestApiV3()) {
632+
$curl_http_header[] = 'x-atlassian-force-account-id: true';
633+
}
634+
607635
curl_setopt(
608636
$ch,
609637
CURLOPT_HTTPHEADER,
610-
['Accept: */*', 'Content-Type: application/json', 'X-Atlassian-Token: no-check']
638+
$curl_http_header
611639
);
612640

613641
curl_setopt($ch, CURLOPT_VERBOSE, $this->getConfiguration()->isCurlOptVerbose());
614642

615-
if ($this->isRestApiV3()) {
616-
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-atlassian-force-account-id: true']);
617-
}
618-
619643
$this->log->debug('Curl exec='.$url);
620644
$response = curl_exec($ch);
621645

0 commit comments

Comments
 (0)