|
@@ -1,3 +1,4 @@
|
|
|
+from typing import Any, Mapping, MutableMapping, Optional
|
|
|
from urllib.parse import urlparse
|
|
|
|
|
|
from django.forms.utils import ErrorList
|
|
@@ -7,6 +8,7 @@ from django.utils.decorators import method_decorator
|
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
|
from django.views.generic import View
|
|
|
from jwt.exceptions import ExpiredSignatureError
|
|
|
+from rest_framework.request import Request
|
|
|
|
|
|
from sentry import options
|
|
|
from sentry.models import Organization
|
|
@@ -20,24 +22,27 @@ from sentry_plugins.jira_ac.models import JiraTenant
|
|
|
from sentry_plugins.jira_ac.utils import ApiError, get_jira_auth_from_request
|
|
|
|
|
|
JIRA_KEY = f"{urlparse(absolute_uri()).hostname}.jira_ac"
|
|
|
+CATCHABLE_AUTH_ERRORS = (ApiError, JiraTenant.DoesNotExist, ExpiredSignatureError)
|
|
|
|
|
|
|
|
|
class BaseJiraWidgetView(View):
|
|
|
jira_auth = None
|
|
|
|
|
|
- def get_jira_auth(self):
|
|
|
+ def get_jira_auth(self) -> JiraTenant:
|
|
|
if self.jira_auth is None:
|
|
|
self.jira_auth = get_jira_auth_from_request(self.request)
|
|
|
return self.jira_auth
|
|
|
|
|
|
- def get_context(self):
|
|
|
+ def get_context(self) -> MutableMapping[str, str]:
|
|
|
return {
|
|
|
"ac_js_src": "https://connect-cdn.atl-paas.net/all.js",
|
|
|
"login_url": absolute_uri(reverse("sentry-login")),
|
|
|
"body_class": "",
|
|
|
}
|
|
|
|
|
|
- def get_response(self, template, context=None):
|
|
|
+ def get_response(
|
|
|
+ self, template: str, context: Optional[Mapping[str, Any]] = None
|
|
|
+ ) -> HttpResponse:
|
|
|
context = context or self.get_context()
|
|
|
res = render_to_response(template, context, self.request)
|
|
|
|
|
@@ -53,12 +58,12 @@ class BaseJiraWidgetView(View):
|
|
|
|
|
|
class JiraUIWidgetView(BaseJiraWidgetView):
|
|
|
@transaction_start("JiraUIWidgetView.get")
|
|
|
- def get(self, request, *args, **kwargs):
|
|
|
+ def get(self, request: Request, *args: Any, **kwargs: Any) -> HttpResponse:
|
|
|
with configure_scope() as scope:
|
|
|
try:
|
|
|
# make sure this exists and is valid
|
|
|
jira_auth = self.get_jira_auth()
|
|
|
- except (ApiError, JiraTenant.DoesNotExist, ExpiredSignatureError) as e:
|
|
|
+ except CATCHABLE_AUTH_ERRORS as e:
|
|
|
scope.set_tag("result", f"error.{e.__class__.__name__}")
|
|
|
return self.get_response("error.html")
|
|
|
|
|
@@ -88,16 +93,16 @@ class JiraUIWidgetView(BaseJiraWidgetView):
|
|
|
|
|
|
|
|
|
class JiraConfigView(BaseJiraWidgetView):
|
|
|
- def get_context(self):
|
|
|
+ def get_context(self) -> MutableMapping[str, str]:
|
|
|
context = super().get_context()
|
|
|
context["body_class"] = "aui-page-focused aui-page-size-medium"
|
|
|
return context
|
|
|
|
|
|
@transaction_start("JiraConfigView.get")
|
|
|
- def get(self, request, *args, **kwargs):
|
|
|
+ def get(self, request: Request, *args: Any, **kwargs: Any) -> HttpResponse:
|
|
|
try:
|
|
|
jira_auth = self.get_jira_auth()
|
|
|
- except (ApiError, JiraTenant.DoesNotExist):
|
|
|
+ except CATCHABLE_AUTH_ERRORS:
|
|
|
return self.get_response("error.html")
|
|
|
|
|
|
if request.user.is_anonymous:
|
|
@@ -116,11 +121,11 @@ class JiraConfigView(BaseJiraWidgetView):
|
|
|
return self.get_response("config.html", context)
|
|
|
|
|
|
@transaction_start("JiraConfigView.post")
|
|
|
- def post(self, request, *args, **kwargs):
|
|
|
+ def post(self, request: Request, *args: Any, **kwargs: Any) -> HttpResponse:
|
|
|
try:
|
|
|
- jira_auth = get_jira_auth_from_request(request)
|
|
|
- except (ApiError, JiraTenant.DoesNotExist):
|
|
|
- self.get_response("error.html")
|
|
|
+ jira_auth = self.get_jira_auth()
|
|
|
+ except CATCHABLE_AUTH_ERRORS:
|
|
|
+ return self.get_response("error.html")
|
|
|
|
|
|
if request.user.is_anonymous:
|
|
|
return self.get_response("signin.html")
|
|
@@ -147,7 +152,7 @@ class JiraConfigView(BaseJiraWidgetView):
|
|
|
|
|
|
class JiraDescriptorView(View):
|
|
|
@transaction_start("JiraDescriptorView.get")
|
|
|
- def get(self, request, *args, **kwargs):
|
|
|
+ def get(self, request: Request, *args: Any, **kwargs: Any) -> HttpResponse:
|
|
|
return HttpResponse(
|
|
|
json.dumps(
|
|
|
{
|
|
@@ -183,12 +188,12 @@ class JiraDescriptorView(View):
|
|
|
|
|
|
class JiraInstalledCallback(View):
|
|
|
@method_decorator(csrf_exempt)
|
|
|
- def dispatch(self, request, *args, **kwargs):
|
|
|
+ def dispatch(self, request: Request, *args: Any, **kwargs: Any) -> HttpResponse:
|
|
|
return super().dispatch(request, *args, **kwargs)
|
|
|
|
|
|
@method_decorator(csrf_exempt)
|
|
|
@transaction_start("JiraInstalledCallback.post")
|
|
|
- def post(self, request, *args, **kwargs):
|
|
|
+ def post(self, request: Request, *args: Any, **kwargs: Any) -> HttpResponse:
|
|
|
registration_info = json.loads(request.body)
|
|
|
JiraTenant.objects.create_or_update(
|
|
|
client_key=registration_info["clientKey"],
|