123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- import json
- from typing import Optional
- from urllib.parse import urlparse
- from django.conf import settings
- from django.db import IntegrityError
- from django.http import HttpRequest, HttpResponse
- from django.template.loader import render_to_string
- from django.utils.safestring import mark_safe
- from ninja import Field, Form, Query, Router
- from ninja.errors import AuthenticationError
- from apps.issue_events.models import IssueEvent
- from apps.projects.models import Project
- from glitchtip.schema import CamelSchema
- from .forms import UserReportForm
- async def embed_auth(request: HttpRequest):
- dsn = request.GET.get("dsn")
- urlparts = urlparse(dsn)
- public_key = urlparts.username
- path = str(urlparts.path)
- project_id = path.rsplit("/", 1)[-1]
- try:
- project = (
- await Project.objects.filter(
- id=project_id, projectkey__public_key=public_key
- )
- .select_related("organization")
- .only("id", "organization__is_accepting_events")
- .aget()
- )
- except ValueError:
- raise AuthenticationError([{"message": "Invalid DSN"}])
- if not project.organization.is_accepting_events:
- raise AuthenticationError([{"message": "Invalid DSN"}])
- return project
- class EmbedAuthHttpRequest(HttpRequest):
- """Django HttpRequest that is known to be authenticated by the embed api"""
- auth: Project
- router = Router(auth=embed_auth)
- # Copy credited to OSS Sentry sentry/web/error_page_embed.py
- DEFAULT_TITLE = "It looks like we're having issues."
- GENERIC_ERROR = (
- "An unknown error occurred while submitting your report. Please try again."
- )
- FORM_ERROR = "Some fields were invalid. Please correct the errors and try again."
- SENT_MESSAGE = "Your feedback has been sent. Thank you!"
- DEFAULT_SUBTITLE = "Our team has been notified."
- DEFAULT_SUBTITLE2 = "If you'd like to help, tell us what happened below."
- DEFAULT_NAME_LABEL = "Name"
- DEFAULT_EMAIL_LABEL = "Email"
- DEFAULT_COMMENTS_LABEL = "What happened?"
- DEFAULT_CLOSE_LABEL = "Close"
- DEFAULT_SUBMIT_LABEL = "Submit Crash Report"
- class EmbedSchema(CamelSchema):
- dsn: str
- eventId: str = Field()
- class EmbedGetSchema(EmbedSchema):
- title: str = DEFAULT_TITLE
- subtitle: str = DEFAULT_SUBTITLE
- subtitle2: str = DEFAULT_SUBTITLE2
- label_name: str = DEFAULT_NAME_LABEL
- label_email: str = DEFAULT_EMAIL_LABEL
- label_comments: str = DEFAULT_COMMENTS_LABEL
- label_close: str = DEFAULT_CLOSE_LABEL
- label_submit: str = DEFAULT_SUBMIT_LABEL
- error_generic: str = GENERIC_ERROR
- error_form_entry: str = FORM_ERROR
- success_message: str = SENT_MESSAGE
- name: Optional[str] = None
- email: Optional[str] = None
- class UserReportFormInput(CamelSchema):
- name: Optional[str]
- email: Optional[str]
- comments: Optional[str]
- @router.get("/error-page/")
- async def get_embed_error_page(request: HttpRequest, data: Query[EmbedGetSchema]):
- initial = {"name": data.name, "email": data.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.label_name,
- "email_label": data.label_email,
- "comments_label": data.label_comments,
- "submit_label": data.label_submit,
- "close_label": data.label_close,
- },
- )
- 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": data.error_generic,
- "form_error": data.error_form_entry,
- "sent_message": data.success_message,
- }
- )
- ),
- }
- return HttpResponse(
- render_to_string("user_reports/error-page-embed.js", context, request),
- content_type="application/javascript",
- )
- @router.post("/error-page/")
- async def submit_embed_error_page(
- request: EmbedAuthHttpRequest,
- data: Query[EmbedGetSchema],
- form: Form[UserReportFormInput],
- ):
- event_id = data.eventId
- initial = {"name": data.name, "email": data.email}
- form = UserReportForm(form.dict(), initial=initial)
- if form.is_valid():
- report = form.save(commit=False)
- report.project_id = request.auth.id
- report.event_id = event_id
- event = await IssueEvent.objects.filter(id=event_id).afirst()
- if event:
- report.issue_id = event.issue_id
- try:
- await report.asave()
- except IntegrityError:
- pass # Duplicate, ignore
- return HttpResponse()
- return HttpResponse(
- json.dumps({"errors": form.errors}),
- status=400,
- content_type="application/json",
- )
|