stingus/StingusJiraBundle

View on GitHub
Oauth/Oauth.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
 
namespace Stingus\JiraBundle\Oauth;
 
use Stingus\JiraBundle\Doctrine\OauthTokenManager;
use Stingus\JiraBundle\Event\OauthTokenGeneratedEvent;
use Stingus\JiraBundle\Exception\JiraAuthorizationException;
use Stingus\JiraBundle\Model\OauthTokenInterface;
use Stingus\JiraBundle\Request\JiraRequest;
use Stingus\JiraBundle\StingusJiraEvents;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
 
/**
* Class Oauth.
* Responsible with Jira Oauth 1.0a authorization
*
* @package Stingus\JiraBundle\Oauth
*/
class Oauth
{
const SERVICE_ID = 'stingus_jira.oauth';
 
const FILENAME_PRIVATE = 'private.key';
const FILENAME_PUBLIC = 'public.key';
const FILENAME_CERT = 'cert.pem';
 
const URL_REQUEST_TOKEN = '/plugins/servlet/oauth/request-token';
const URL_AUTHORIZE_TOKEN = '/plugins/servlet/oauth/authorize';
const URL_ACCESS_TOKEN = '/plugins/servlet/oauth/access-token';
 
/** @var Router */
private $router;
 
/** @var JiraRequest */
private $jiraRequest;
 
/** @var EventDispatcherInterface */
private $dispatcher;
 
/** @var OauthTokenManager */
private $tokenManager;
 
/**
* Oauth constructor.
*
* @param Router $router
* @param JiraRequest $jiraRequest
* @param EventDispatcherInterface $dispatcher
* @param OauthTokenManager $tokenManager
*/
public function __construct(
Router $router,
JiraRequest $jiraRequest,
EventDispatcherInterface $dispatcher,
OauthTokenManager $tokenManager = null
) {
$this->router = $router;
$this->jiraRequest = $jiraRequest;
$this->dispatcher = $dispatcher;
$this->tokenManager = $tokenManager;
}
 
/**
* Get the Oauth request endpoint, with the temporary token
*
* @param OauthTokenInterface $oauthToken
*
* @return string
* @throws JiraAuthorizationException
*/
public function getRequestEndpoint(OauthTokenInterface $oauthToken): string
{
$callback = $this->router
->generate(
'stingus_jira_callback',
[
'token_id' => $oauthToken->getId(),
'consumer_key' => $oauthToken->getConsumerKey(),
'base_url' => $oauthToken->getBaseUrl(),
],
UrlGeneratorInterface::ABSOLUTE_URL
);
$response = $this->jiraRequest
->post($oauthToken, self::URL_REQUEST_TOKEN, ['oauth_callback' => $callback])
->getBody()
->getContents();
 
parse_str($response, $responseTokens);
 
if (!array_key_exists('oauth_token', $responseTokens)) {
throw new JiraAuthorizationException('Request authorization oauth_token key missing');
}
 
return sprintf(
'%s%s?oauth_token=%s',
$oauthToken->getBaseUrl(),
self::URL_AUTHORIZE_TOKEN,
$responseTokens['oauth_token']
);
}
 
/**
* Get the OAuth tokens (token and secret).
*
* @param OauthTokenInterface $oauthToken
*
* @throws JiraAuthorizationException
*/
public function getAccessToken(OauthTokenInterface $oauthToken)
{
if (null === $oauthToken->getVerifier()) {
throw new JiraAuthorizationException('Verifier missing from the OauthToken');
}
 
$response = $this->jiraRequest
->post($oauthToken, self::URL_ACCESS_TOKEN, ['oauth_verifier' => $oauthToken->getVerifier()])
->getBody()
->getContents();
 
parse_str($response, $responseTokens);
 
$this->validateAccessTokens($responseTokens);
 
Missing class import via use statement (line '126', column '27').
$expiresAt = (new \DateTime())
Missing class import via use statement (line '127', column '23').
->add(new \DateInterval(sprintf('PT%sS', $responseTokens['oauth_expires_in'])));
Missing class import via use statement (line '128', column '31').
$authExpiresAt = (new \DateTime())
Missing class import via use statement (line '129', column '23').
->add(new \DateInterval(sprintf('PT%sS', $responseTokens['oauth_authorization_expires_in'])));
 
$oauthToken
->setToken($responseTokens['oauth_token'])
->setTokenSecret($responseTokens['oauth_token_secret'])
->setExpiresAt($expiresAt)
->setAuthExpiresAt($authExpiresAt)
->setSessionHandle($responseTokens['oauth_session_handle']);
 
$this->dispatcher->dispatch(StingusJiraEvents::OAUTH_TOKEN_GENERATE, new OauthTokenGeneratedEvent($oauthToken));
 
if (null !== $this->tokenManager) {
$this->tokenManager->save($oauthToken);
}
}
 
/**
* Validate access tokens
*
* @param array $tokens
*/
private function validateAccessTokens(array $tokens)
{
$this->validateAccessTokenKeyString('oauth_token', $tokens);
$this->validateAccessTokenKeyString('oauth_token_secret', $tokens);
$this->validateAccessTokenKeyInt('oauth_expires_in', $tokens);
$this->validateAccessTokenKeyInt('oauth_authorization_expires_in', $tokens);
$this->validateAccessTokenKeyString('oauth_session_handle', $tokens);
}
 
/**
* Validate string access tokens
*
* @param string $key
* @param array $tokens
*
* @return bool
* @throws JiraAuthorizationException
*/
private function validateAccessTokenKeyString(string $key, array $tokens)
{
if (!array_key_exists($key, $tokens) || '' === $tokens[$key]) {
throw new JiraAuthorizationException(sprintf('Invalid %s key', $key));
}
 
return true;
}
 
/**
* Validate integer access tokens
*
* @param string $key
* @param array $tokens
*
* @return bool
* @throws JiraAuthorizationException
*/
private function validateAccessTokenKeyInt(string $key, array $tokens)
{
if (!array_key_exists($key, $tokens)
|| false === filter_var($tokens[$key], FILTER_VALIDATE_INT)
) {
throw new JiraAuthorizationException(sprintf('Invalid %s key', $key));
}
 
return true;
}
}