123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- import json
- from django.db import IntegrityError
- from django.conf import settings
- from django.template.loader import render_to_string
- from django.utils.safestring import mark_safe
- from rest_framework import views, viewsets, exceptions, permissions, renderers
- from rest_framework.response import Response
- from projects.models import ProjectKey
- from events.models import Event
- from issues.permissions import EventPermission
- from .models import UserReport
- from .forms import UserReportForm
- from .serializers import ErrorPageEmbedSerializer, UserReportSerializer
- class JavaScriptSuccessRenderer(renderers.JSONRenderer):
- """
- Render as JavaScript when status code is 200.
- On failure status codes, render as JSON instead.
- """
- media_type = "application/javascript"
- format = "js"
- def render(self, data, media_type=None, renderer_context=None):
- if renderer_context["response"].status_code == 200:
- charset = "utf-8"
- return data.encode(charset)
- return super().render(data, "application/json", renderer_context)
- class ErrorPageEmbedView(views.APIView):
- """
- Ideas taken from OSS Sentry sentry/web/error_page_embed.py
- Modified for DRF
- """
- permission_classes = [permissions.AllowAny]
- renderer_classes = [
- renderers.JSONRenderer,
- renderers.BrowsableAPIRenderer,
- JavaScriptSuccessRenderer,
- ]
- def get_format_suffix(self, **kwargs):
- if self.request.method == "GET":
- return "js"
- return super().get_format_suffix(**kwargs)
- def process_get_params(self, params):
- serializer = ErrorPageEmbedSerializer(data=params)
- serializer.is_valid(raise_exception=True)
- return serializer.validated_data
- def get_project_key(self, validated_data):
- dsn = validated_data["dsn"]
- try:
- return ProjectKey.from_dsn(dsn)
- except ProjectKey.DoesNotExist:
- raise exceptions.NotFound("Invalid dsn parameter")
- def get(self, request):
- data = self.process_get_params(request.GET)
- self.get_project_key(data)
- initial = {"name": request.GET.get("name"), "email": request.GET.get("email")}
- # Stubbed, should be configurable
- show_branding = True
- form = UserReportForm(initial=initial)
- template = render_to_string(
- "user_reports/error-page-embed.html",
- {
- "form": form,
- "show_branding": show_branding,
- "title": data["title"],
- "subtitle": data["subtitle"],
- "subtitle2": data["subtitle2"],
- "name_label": data["labelName"],
- "email_label": data["labelEmail"],
- "comments_label": data["labelComments"],
- "submit_label": data["labelSubmit"],
- "close_label": data["labelClose"],
- },
- )
- url = settings.GLITCHTIP_URL.geturl() + request.get_full_path()
- context = {
- "endpoint": mark_safe("*/" + json.dumps(url) + ";/*"),
- "template": mark_safe("*/" + json.dumps(template) + ";/*"),
- "strings": mark_safe(
- json.dumps(
- {
- "generic_error": str(data["errorGeneric"]),
- "form_error": str(data["errorFormEntry"]),
- "sent_message": str(data["successMessage"]),
- }
- )
- ),
- }
- return Response(
- render_to_string("user_reports/error-page-embed.js", context, request),
- content_type="application/javascript",
- )
- def post(self, request):
- data = self.process_get_params(request.GET)
- project_key = self.get_project_key(data)
- event_id = data["eventId"]
- initial = {"name": request.GET.get("name"), "email": request.GET.get("email")}
- form = UserReportForm(request.POST, initial=initial)
- if form.is_valid():
- report = form.save(commit=False)
- report.project = project_key.project
- report.event_id = event_id
- event = Event.objects.filter(event_id=event_id).first()
- if event:
- report.issue = event.issue
- try:
- report.save()
- except IntegrityError:
- pass # Duplicate, ignore
- return Response()
- return Response({"errors": form.errors}, status=400)
- class UserReportViewSet(viewsets.ReadOnlyModelViewSet):
- queryset = UserReport.objects.all()
- serializer_class = UserReportSerializer
- permission_classes = [EventPermission]
- def get_queryset(self):
- if not self.request.user.is_authenticated:
- return self.queryset.none()
- queryset = super().get_queryset()
- queryset = queryset.filter(project__team__members__user=self.request.user)
- issue_id = self.kwargs.get("issue_pk")
- if issue_id:
- queryset = queryset.filter(issue_id=issue_id)
- return queryset
|