From e3b390087a9e18736f9466855b2abfa6bc03dd6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Tue, 21 Mar 2017 12:10:11 +0100 Subject: [PATCH 1/3] Capture invalid response from the jira server --- taiga/importers/exceptions.py | 3 +++ taiga/importers/jira/api.py | 16 ++++++++++------ taiga/importers/jira/common.py | 3 +++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/taiga/importers/exceptions.py b/taiga/importers/exceptions.py index 0646095d..df78efd1 100644 --- a/taiga/importers/exceptions.py +++ b/taiga/importers/exceptions.py @@ -22,5 +22,8 @@ class InvalidRequest(Exception): class InvalidAuthResult(Exception): pass +class InvalidServiceConfiguration(Exception): + pass + class FailedRequest(Exception): pass diff --git a/taiga/importers/jira/api.py b/taiga/importers/jira/api.py index 9c5d0b4d..75c6e2c5 100644 --- a/taiga/importers/jira/api.py +++ b/taiga/importers/jira/api.py @@ -25,6 +25,7 @@ from taiga.users.services import get_user_photo_url from taiga.users.gravatar import get_user_gravatar_id from taiga.importers import permissions +from taiga.importers import exceptions from taiga.importers.services import resolve_users_bindings from .normal import JiraNormalImporter from .agile import JiraAgileImporter @@ -178,12 +179,15 @@ class JiraImporterViewSet(viewsets.ViewSet): if not jira_url: raise exc.WrongArguments(_("The url param is needed")) - (oauth_token, oauth_secret, url) = JiraNormalImporter.get_auth_url( - jira_url, - settings.IMPORTERS.get('jira', {}).get('consumer_key', None), - settings.IMPORTERS.get('jira', {}).get('cert', None), - True - ) + try: + (oauth_token, oauth_secret, url) = JiraNormalImporter.get_auth_url( + jira_url, + settings.IMPORTERS.get('jira', {}).get('consumer_key', None), + 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( user=request.user, diff --git a/taiga/importers/jira/common.py b/taiga/importers/jira/common.py index f1ffa691..3eaa6ee6 100644 --- a/taiga/importers/jira/common.py +++ b/taiga/importers/jira/common.py @@ -45,6 +45,7 @@ from taiga.projects.custom_attributes.models import (UserStoryCustomAttribute, from taiga.projects.history.models import HistoryEntry from taiga.projects.history.choices import HistoryType from taiga.mdrender.service import render as mdrender +from taiga.importers import exceptions EPIC_COLORS = { "ghx-label-0": "#ffffff", @@ -737,6 +738,8 @@ class JiraImporterCommon: oauth = OAuth1(consumer_key, signature_method=SIGNATURE_RSA, rsa_key=key_cert_data) r = requests.post( 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_token = request['oauth_token'] request_token_secret = request['oauth_token_secret'] From 500fe01b6e1b6590361910a6a956a930e50008b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 23 Mar 2017 17:41:14 +0100 Subject: [PATCH 2/3] Fix jira auth data creation --- taiga/importers/jira/api.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/taiga/importers/jira/api.py b/taiga/importers/jira/api.py index 75c6e2c5..905631d8 100644 --- a/taiga/importers/jira/api.py +++ b/taiga/importers/jira/api.py @@ -13,6 +13,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import uuid + from django.utils.translation import ugettext as _ from django.conf import settings @@ -193,7 +195,7 @@ class JiraImporterViewSet(viewsets.ViewSet): user=request.user, key="jira-oauth", defaults={ - "value": "", + "value": uuid.uuid4().hex, "extra": {}, } ) From cfbe29e9a0ce538a58d78f04ac9e46df4ecae65d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 23 Mar 2017 18:04:16 +0100 Subject: [PATCH 3/3] Add callback url to jira importer --- taiga/front/urls.py | 2 ++ taiga/importers/jira/api.py | 4 +++- taiga/importers/jira/common.py | 15 +++++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/taiga/front/urls.py b/taiga/front/urls.py index 393913e3..244e0a72 100644 --- a/taiga/front/urls.py +++ b/taiga/front/urls.py @@ -55,4 +55,6 @@ urls = { "project-transfer": "/project/{0}/transfer/{1}", # project.slug, project.transfer_token "project-admin": "/login?next=/project/{0}/admin/project-profile/details", # project.slug + + "project-import-jira": "/project/new/import/jira?url={}", } diff --git a/taiga/importers/jira/api.py b/taiga/importers/jira/api.py index 905631d8..5606a732 100644 --- a/taiga/importers/jira/api.py +++ b/taiga/importers/jira/api.py @@ -214,6 +214,7 @@ class JiraImporterViewSet(viewsets.ViewSet): try: 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_secret = oauth_data.extra['oauth_secret'] server_url = oauth_data.extra['url'] @@ -225,7 +226,8 @@ class JiraImporterViewSet(viewsets.ViewSet): settings.IMPORTERS.get('jira', {}).get('cert', None), oauth_token, oauth_secret, - True + oauth_verifier, + False ) except Exception as e: raise exc.WrongArguments(_("Invalid or expired auth token")) diff --git a/taiga/importers/jira/common.py b/taiga/importers/jira/common.py index 3eaa6ee6..c4c6c3eb 100644 --- a/taiga/importers/jira/common.py +++ b/taiga/importers/jira/common.py @@ -17,12 +17,13 @@ # along with this program. If not, see . import requests -from urllib.parse import parse_qsl +from urllib.parse import parse_qsl, quote_plus from oauthlib.oauth1 import SIGNATURE_RSA from requests_oauthlib import OAuth1 from django.core.files.base import ContentFile from django.contrib.contenttypes.models import ContentType +from django.conf import settings from taiga.users.models import User from taiga.projects.models import Points @@ -46,6 +47,7 @@ from taiga.projects.history.models import HistoryEntry from taiga.projects.history.choices import HistoryType 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 = { "ghx-label-0": "#ffffff", @@ -735,7 +737,9 @@ class JiraImporterCommon: if verify is None: 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( server + '/plugins/servlet/oauth/request-token', verify=verify, auth=oauth) if r.status_code != 200: @@ -751,13 +755,16 @@ class JiraImporterCommon: ) @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( consumer_key, signature_method=SIGNATURE_RSA, + callback_uri=callback_uri, rsa_key=key_cert_data, 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) access = dict(parse_qsl(r.text))