Merge pull request #963 from taigaio/issue-5017/import-from-jira

Capture invalid response from the jira server
remotes/origin/live-notifications
David Barragán Merino 2017-03-23 18:51:54 +01:00 committed by GitHub
commit 9ea2d9c66b
4 changed files with 35 additions and 12 deletions

View File

@ -55,4 +55,6 @@ urls = {
"project-transfer": "/project/{0}/transfer/{1}", # project.slug, project.transfer_token "project-transfer": "/project/{0}/transfer/{1}", # project.slug, project.transfer_token
"project-admin": "/login?next=/project/{0}/admin/project-profile/details", # project.slug "project-admin": "/login?next=/project/{0}/admin/project-profile/details", # project.slug
"project-import-jira": "/project/new/import/jira?url={}",
} }

View File

@ -22,5 +22,8 @@ class InvalidRequest(Exception):
class InvalidAuthResult(Exception): class InvalidAuthResult(Exception):
pass pass
class InvalidServiceConfiguration(Exception):
pass
class FailedRequest(Exception): class FailedRequest(Exception):
pass pass

View File

@ -13,6 +13,8 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import uuid
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.conf import settings from django.conf import settings
@ -25,6 +27,7 @@ from taiga.users.services import get_user_photo_url
from taiga.users.gravatar import get_user_gravatar_id from taiga.users.gravatar import get_user_gravatar_id
from taiga.importers import permissions from taiga.importers import permissions
from taiga.importers import exceptions
from taiga.importers.services import resolve_users_bindings from taiga.importers.services import resolve_users_bindings
from .normal import JiraNormalImporter from .normal import JiraNormalImporter
from .agile import JiraAgileImporter from .agile import JiraAgileImporter
@ -178,18 +181,21 @@ class JiraImporterViewSet(viewsets.ViewSet):
if not jira_url: if not jira_url:
raise exc.WrongArguments(_("The url param is needed")) raise exc.WrongArguments(_("The url param is needed"))
(oauth_token, oauth_secret, url) = JiraNormalImporter.get_auth_url( try:
jira_url, (oauth_token, oauth_secret, url) = JiraNormalImporter.get_auth_url(
settings.IMPORTERS.get('jira', {}).get('consumer_key', None), jira_url,
settings.IMPORTERS.get('jira', {}).get('cert', None), settings.IMPORTERS.get('jira', {}).get('consumer_key', None),
True settings.IMPORTERS.get('jira', {}).get('cert', None),
) True
)
except exceptions.InvalidServiceConfiguration:
raise exc.BadRequest(_("Invalid Jira server configuration."))
(auth_data, created) = AuthData.objects.get_or_create( (auth_data, created) = AuthData.objects.get_or_create(
user=request.user, user=request.user,
key="jira-oauth", key="jira-oauth",
defaults={ defaults={
"value": "", "value": uuid.uuid4().hex,
"extra": {}, "extra": {},
} }
) )
@ -208,6 +214,7 @@ class JiraImporterViewSet(viewsets.ViewSet):
try: try:
oauth_data = request.user.auth_data.get(key="jira-oauth") oauth_data = request.user.auth_data.get(key="jira-oauth")
oauth_verifier = request.DATA.get("oauth_verifier", None)
oauth_token = oauth_data.extra['oauth_token'] oauth_token = oauth_data.extra['oauth_token']
oauth_secret = oauth_data.extra['oauth_secret'] oauth_secret = oauth_data.extra['oauth_secret']
server_url = oauth_data.extra['url'] server_url = oauth_data.extra['url']
@ -219,7 +226,8 @@ class JiraImporterViewSet(viewsets.ViewSet):
settings.IMPORTERS.get('jira', {}).get('cert', None), settings.IMPORTERS.get('jira', {}).get('cert', None),
oauth_token, oauth_token,
oauth_secret, oauth_secret,
True oauth_verifier,
False
) )
except Exception as e: except Exception as e:
raise exc.WrongArguments(_("Invalid or expired auth token")) raise exc.WrongArguments(_("Invalid or expired auth token"))

View File

@ -17,12 +17,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import requests import requests
from urllib.parse import parse_qsl from urllib.parse import parse_qsl, quote_plus
from oauthlib.oauth1 import SIGNATURE_RSA from oauthlib.oauth1 import SIGNATURE_RSA
from requests_oauthlib import OAuth1 from requests_oauthlib import OAuth1
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from taiga.users.models import User from taiga.users.models import User
from taiga.projects.models import Points from taiga.projects.models import Points
@ -45,6 +46,8 @@ from taiga.projects.custom_attributes.models import (UserStoryCustomAttribute,
from taiga.projects.history.models import HistoryEntry from taiga.projects.history.models import HistoryEntry
from taiga.projects.history.choices import HistoryType from taiga.projects.history.choices import HistoryType
from taiga.mdrender.service import render as mdrender from taiga.mdrender.service import render as mdrender
from taiga.importers import exceptions
from taiga.front.templatetags.functions import resolve as resolve_front_url
EPIC_COLORS = { EPIC_COLORS = {
"ghx-label-0": "#ffffff", "ghx-label-0": "#ffffff",
@ -734,9 +737,13 @@ class JiraImporterCommon:
if verify is None: if verify is None:
verify = server.startswith('https') verify = server.startswith('https')
oauth = OAuth1(consumer_key, signature_method=SIGNATURE_RSA, rsa_key=key_cert_data) callback_uri = resolve_front_url("project-import-jira", quote_plus(server))
oauth = OAuth1(consumer_key, signature_method=SIGNATURE_RSA, rsa_key=key_cert_data, callback_uri=callback_uri)
r = requests.post( r = requests.post(
server + '/plugins/servlet/oauth/request-token', verify=verify, auth=oauth) server + '/plugins/servlet/oauth/request-token', verify=verify, auth=oauth)
if r.status_code != 200:
raise exceptions.InvalidServiceConfiguration()
request = dict(parse_qsl(r.text)) request = dict(parse_qsl(r.text))
request_token = request['oauth_token'] request_token = request['oauth_token']
request_token_secret = request['oauth_token_secret'] request_token_secret = request['oauth_token_secret']
@ -748,13 +755,16 @@ class JiraImporterCommon:
) )
@classmethod @classmethod
def get_access_token(cls, server, consumer_key, key_cert_data, request_token, request_token_secret, verify=False): def get_access_token(cls, server, consumer_key, key_cert_data, request_token, request_token_secret, request_verifier, verify=False):
callback_uri = resolve_front_url("project-import-jira", quote_plus(server))
oauth = OAuth1( oauth = OAuth1(
consumer_key, consumer_key,
signature_method=SIGNATURE_RSA, signature_method=SIGNATURE_RSA,
callback_uri=callback_uri,
rsa_key=key_cert_data, rsa_key=key_cert_data,
resource_owner_key=request_token, resource_owner_key=request_token,
resource_owner_secret=request_token_secret resource_owner_secret=request_token_secret,
verifier=request_verifier,
) )
r = requests.post(server + '/plugins/servlet/oauth/access-token', verify=verify, auth=oauth) r = requests.post(server + '/plugins/servlet/oauth/access-token', verify=verify, auth=oauth)
access = dict(parse_qsl(r.text)) access = dict(parse_qsl(r.text))