def test_user_feedback(self): user_feedback_received.send(project=self.project, sender=type(self.project)) feature_complete = FeatureAdoption.objects.get_by_slug( organization=self.organization, slug="user_feedback") assert feature_complete
def test_user_feedback(self): user_feedback_received.send(project=self.project, sender=type(self.project)) feature_complete = FeatureAdoption.objects.get_by_slug( organization=self.organization, slug="user_feedback" ) assert feature_complete
def post(self, request, project): """ Submit User Feedback ```````````````````` Submit and associate user feedback with an issue. :pparam string organization_slug: the slug of the organization. :pparam string project_slug: the slug of the project. :auth: required :param string event_id: the event ID :param string name: user's name :param string email: user's email address :param string comments: comments supplied by user """ serializer = UserReportSerializer(data=request.DATA) if not serializer.is_valid(): return Response(serializer.errors, status=400) report = serializer.object report.project = project # TODO(dcramer): we should probably create the user if they dont # exist, and ideally we'd also associate that with the event euser = self.find_event_user(report) if euser and not euser.name and report.name: euser.update(name=report.name) if euser: report.event_user_id = euser.id try: report.group = Group.objects.from_event_id(project, report.event_id) except Group.DoesNotExist: pass try: with transaction.atomic(): report.save() except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. existing_report = UserReport.objects.get( project=report.project, event_id=report.event_id, ) existing_report.update( name=report.name, email=report.email, comments=report.comments, date_added=timezone.now(), event_user_id=euser.id if euser else None, ) report = existing_report if report.group_id is None: backfill_group.apply_async( kwargs={ 'report_id': report.id, }, countdown=30, ) user_feedback_received.send(project=report.project, group=report.group, sender=self) return Response( serialize(report, request.user, ProjectUserReportSerializer()))
def dispatch(self, request): try: event_id = request.GET['eventId'] except KeyError: return self._smart_response( request, {'eventId': 'Missing or invalid parameter.'}, status=400) if event_id and not is_event_id(event_id): return self._smart_response( request, {'eventId': 'Missing or invalid parameter.'}, status=400) # XXX(dcramer): enforce case insensitivty by coercing this to a lowercase string event_id = event_id.lower() key = self._get_project_key(request) if not key: return self._smart_response( request, {'dsn': 'Missing or invalid parameter.'}, status=404) origin = self._get_origin(request) if not is_valid_origin(origin, key.project): return self._smart_response(request, status=403) if request.method == 'OPTIONS': return self._smart_response(request) # customization options options = DEFAULT_OPTIONS.copy() for name in six.iterkeys(options): if name in request.GET: options[name] = six.text_type(request.GET[name]) # TODO(dcramer): since we cant use a csrf cookie we should at the very # least sign the request / add some kind of nonce initial = { 'name': request.GET.get('name'), 'email': request.GET.get('email'), } form = UserReportForm( request.POST if request.method == 'POST' else None, initial=initial) if form.is_valid(): # TODO(dcramer): move this to post to the internal API report = form.save(commit=False) report.project = key.project report.event_id = event_id try: event = Event.objects.filter(project_id=report.project.id, event_id=report.event_id)[0] except IndexError: try: report.group = Group.objects.from_event_id( report.project, report.event_id) except Group.DoesNotExist: pass else: Event.objects.bind_nodes([event]) report.environment = event.get_environment() report.group = event.group try: with transaction.atomic(): report.save() except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. UserReport.objects.filter( project=report.project, event_id=report.event_id, ).update( name=report.name, email=report.email, comments=report.comments, date_added=timezone.now(), ) else: if report.group: report.notify() user_feedback_received.send(project=report.project, group=report.group, sender=self) return self._smart_response(request) elif request.method == 'POST': return self._smart_response(request, { "errors": dict(form.errors), }, status=400) show_branding = ProjectOption.objects.get_value( project=key.project, key='feedback:branding', default='1') == '1' template = render_to_string( 'sentry/error-page-embed.html', { 'form': form, 'show_branding': show_branding, 'title': options['title'], 'subtitle': options['subtitle'], 'subtitle2': options['subtitle2'], 'name_label': options['labelName'], 'email_label': options['labelEmail'], 'comments_label': options['labelComments'], 'submit_label': options['labelSubmit'], 'close_label': options['labelClose'], }) context = { 'endpoint': mark_safe('*/' + json.dumps(request.build_absolute_uri()) + ';/*'), 'template': mark_safe('*/' + json.dumps(template) + ';/*'), 'strings': json.dumps_htmlsafe({ 'generic_error': six.text_type(options['errorGeneric']), 'form_error': six.text_type(options['errorFormEntry']), 'sent_message': six.text_type(options['successMessage']), }), } return render_to_response('sentry/error-page-embed.js', context, request, content_type='text/javascript')
def dispatch(self, request): try: event_id = request.GET["eventId"] except KeyError: return self._smart_response( request, {"eventId": "Missing or invalid parameter."}, status=400) normalized_event_id = normalize_event_id(event_id) if normalized_event_id: event_id = normalized_event_id elif event_id: return self._smart_response( request, {"eventId": "Missing or invalid parameter."}, status=400) key = self._get_project_key(request) if not key: return self._smart_response( request, {"dsn": "Missing or invalid parameter."}, status=404) origin = self._get_origin(request) if not is_valid_origin(origin, key.project): return self._smart_response(request, status=403) if request.method == "OPTIONS": return self._smart_response(request) # customization options options = DEFAULT_OPTIONS.copy() for name in options.keys(): if name in request.GET: options[name] = str(request.GET[name]) # TODO(dcramer): since we cant use a csrf cookie we should at the very # least sign the request / add some kind of nonce initial = { "name": request.GET.get("name"), "email": request.GET.get("email") } form = UserReportForm( request.POST if request.method == "POST" else None, initial=initial) if form.is_valid(): # TODO(dcramer): move this to post to the internal API report = form.save(commit=False) report.project_id = key.project_id report.event_id = event_id event = eventstore.get_event_by_id(report.project_id, report.event_id) if event is not None: report.environment_id = event.get_environment().id report.group_id = event.group_id try: with transaction.atomic(): report.save() except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. UserReport.objects.filter(project_id=report.project_id, event_id=report.event_id).update( name=report.name, email=report.email, comments=report.comments, date_added=timezone.now(), ) else: if report.group_id: report.notify() user_feedback_received.send( project=Project.objects.get(id=report.project_id), sender=self, ) return self._smart_response(request) elif request.method == "POST": return self._smart_response(request, {"errors": dict(form.errors)}, status=400) show_branding = (ProjectOption.objects.get_value( project=key.project, key="feedback:branding", default="1") == "1") template = render_to_string( "sentry/error-page-embed.html", context={ "form": form, "show_branding": show_branding, "title": options["title"], "subtitle": options["subtitle"], "subtitle2": options["subtitle2"], "name_label": options["labelName"], "email_label": options["labelEmail"], "comments_label": options["labelComments"], "submit_label": options["labelSubmit"], "close_label": options["labelClose"], }, ) context = { "endpoint": mark_safe("*/" + json.dumps(absolute_uri(request.get_full_path())) + ";/*"), "template": mark_safe("*/" + json.dumps(template) + ";/*"), "strings": mark_safe("*/" + json.dumps_htmlsafe( { "generic_error": str(options["errorGeneric"]), "form_error": str(options["errorFormEntry"]), "sent_message": str(options["successMessage"]), }) + ";/*"), } return render_to_response("sentry/error-page-embed.js", context, request, content_type="text/javascript")
def post(self, request, project): """ Submit User Feedback ```````````````````` Submit and associate user feedback with an issue. Feedback must be received by the server no more than 30 minutes after the event was saved. Additionally, within 5 minutes of submitting feedback it may also be overwritten. This is useful in situations where you may need to retry sending a request due to network failures. If feedback is rejected due to a mutability threshold, a 409 status code will be returned. :pparam string organization_slug: the slug of the organization. :pparam string project_slug: the slug of the project. :auth: required :param string event_id: the event ID :param string name: user's name :param string email: user's email address :param string comments: comments supplied by user """ serializer = UserReportSerializer(data=request.DATA) if not serializer.is_valid(): return self.respond(serializer.errors, status=400) report = serializer.object report.project = project # TODO(dcramer): we should probably create the user if they dont # exist, and ideally we'd also associate that with the event euser = self.find_event_user(report) if euser and not euser.name and report.name: euser.update(name=report.name) if euser: report.event_user_id = euser.id event = Event.objects.filter( project_id=project.id, event_id=report.event_id, ).first() if not event: try: report.group = Group.objects.from_event_id( project, report.event_id) except Group.DoesNotExist: pass else: # if the event is more than 30 minutes old, we dont allow updates # as it might be abusive if event.datetime < timezone.now() - timedelta(minutes=30): return self.respond( {'detail': 'Feedback for this event cannot be modified.'}, status=409) report.environment = event.get_environment() report.group = event.group try: with transaction.atomic(): report.save() except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. existing_report = UserReport.objects.get( project=report.project, event_id=report.event_id, ) # if the existing report was submitted more than 5 minutes ago, we dont # allow updates as it might be abusive (replay attacks) if existing_report.date_added < timezone.now() - timedelta( minutes=5): return self.respond( {'detail': 'Feedback for this event cannot be modified.'}, status=409) existing_report.update( name=report.name, email=report.email, comments=report.comments, date_added=timezone.now(), event_user_id=euser.id if euser else None, ) report = existing_report else: if report.group: report.notify() user_feedback_received.send(project=report.project, group=report.group, sender=self) return self.respond( serialize( report, request.user, ProjectUserReportSerializer( environment_func=self._get_environment_func( request, project.organization_id))))
def dispatch(self, request): try: event_id = request.GET['eventId'] except KeyError: return self._json_response(request, status=400) if not is_event_id(event_id): return self._json_response(request, status=400) key = self._get_project_key(request) if not key: return self._json_response(request, status=404) origin = self._get_origin(request) if not origin: return self._json_response(request, status=403) if not is_valid_origin(origin, key.project): return HttpResponse(status=403) if request.method == 'OPTIONS': return self._json_response(request) # TODO(dcramer): since we cant use a csrf cookie we should at the very # least sign the request / add some kind of nonce initial = { 'name': request.GET.get('name'), 'email': request.GET.get('email'), } form = UserReportForm( request.POST if request.method == 'POST' else None, initial=initial) if form.is_valid(): # TODO(dcramer): move this to post to the internal API report = form.save(commit=False) report.project = key.project report.event_id = event_id try: mapping = EventMapping.objects.get( event_id=report.event_id, project_id=key.project_id, ) except EventMapping.DoesNotExist: # XXX(dcramer): the system should fill this in later pass else: report.group = Group.objects.get(id=mapping.group_id) try: with transaction.atomic(): report.save() except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. UserReport.objects.filter( project=report.project, event_id=report.event_id, ).update( name=report.name, email=report.email, comments=report.comments, date_added=timezone.now(), ) user_feedback_received.send(project=report.project, group=report.group, sender=self) return self._json_response(request) elif request.method == 'POST': return self._json_response(request, { "errors": dict(form.errors), }, status=400) show_branding = ProjectOption.objects.get_value( project=key.project, key='feedback:branding', default='1') == '1' template = render_to_string('sentry/error-page-embed.html', { 'form': form, 'show_branding': show_branding, }) context = { 'endpoint': mark_safe('*/' + json.dumps(request.build_absolute_uri()) + ';/*'), 'template': mark_safe('*/' + json.dumps(template) + ';/*'), 'strings': json.dumps_htmlsafe({ 'generic_error': six.text_type(GENERIC_ERROR), 'form_error': six.text_type(FORM_ERROR), 'sent_message': six.text_type(SENT_MESSAGE), }), } return render_to_response('sentry/error-page-embed.js', context, request, content_type='text/javascript')
def post(self, request, project): """ Submit User Feedback ```````````````````` Submit and associate user feedback with an issue. Feedback must be received by the server no more than 30 minutes after the event was saved. Additionally, within 5 minutes of submitting feedback it may also be overwritten. This is useful in situations where you may need to retry sending a request due to network failures. If feedback is rejected due to a mutability threshold, a 409 status code will be returned. Note: Feedback may be submitted with DSN authentication (see auth documentation). :pparam string organization_slug: the slug of the organization. :pparam string project_slug: the slug of the project. :auth: required :param string event_id: the event ID :param string name: user's name :param string email: user's email address :param string comments: comments supplied by user """ if hasattr(request.auth, 'project_id') and project.id != request.auth.project_id: return self.respond(status=400) serializer = UserReportSerializer(data=request.DATA) if not serializer.is_valid(): return self.respond(serializer.errors, status=400) report = serializer.object # XXX(dcramer): enforce case insensitivty by coercing this to a lowercase string report.event_id = report.event_id.lower() report.project = project # TODO(dcramer): we should probably create the user if they dont # exist, and ideally we'd also associate that with the event euser = self.find_event_user(report) if euser and not euser.name and report.name: euser.update(name=report.name) if euser: report.event_user_id = euser.id event = Event.objects.from_event_id(report.event_id, project.id) if not event: try: report.group = Group.objects.from_event_id(project, report.event_id) except Group.DoesNotExist: pass else: # if the event is more than 30 minutes old, we dont allow updates # as it might be abusive if event.datetime < timezone.now() - timedelta(minutes=30): return self.respond( {'detail': 'Feedback for this event cannot be modified.'}, status=409) report.environment = event.get_environment() report.group = event.group try: with transaction.atomic(): report.save() except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. existing_report = UserReport.objects.get( project=report.project, event_id=report.event_id, ) # if the existing report was submitted more than 5 minutes ago, we dont # allow updates as it might be abusive (replay attacks) if existing_report.date_added < timezone.now() - timedelta(minutes=5): return self.respond( {'detail': 'Feedback for this event cannot be modified.'}, status=409) existing_report.update( name=report.name, email=report.email, comments=report.comments, date_added=timezone.now(), event_user_id=euser.id if euser else None, ) report = existing_report else: if report.group: report.notify() user_feedback_received.send(project=report.project, group=report.group, sender=self) return self.respond(serialize(report, request.user, UserReportWithGroupSerializer( environment_func=self._get_environment_func( request, project.organization_id) )))
def save_userreport(project, report, start_time=None): if start_time is None: start_time = timezone.now() # XXX(dcramer): enforce case insensitivity by coercing this to a lowercase string report["event_id"] = report["event_id"].lower() report["project_id"] = project.id event = eventstore.get_event_by_id(project.id, report["event_id"]) # TODO(dcramer): we should probably create the user if they dont # exist, and ideally we'd also associate that with the event euser = find_event_user(report, event) if euser and not euser.name and report.get("name"): euser.update(name=report["name"]) if euser: report["event_user_id"] = euser.id if event: # if the event is more than 30 minutes old, we dont allow updates # as it might be abusive if event.datetime < start_time - timedelta(minutes=30): raise Conflict("Feedback for this event cannot be modified.") report["environment_id"] = event.get_environment().id report["group_id"] = event.group_id try: with transaction.atomic(): report_instance = UserReport.objects.create(**report) except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. existing_report = UserReport.objects.get( project_id=report["project_id"], event_id=report["event_id"]) # if the existing report was submitted more than 5 minutes ago, we dont # allow updates as it might be abusive (replay attacks) if existing_report.date_added < timezone.now() - timedelta(minutes=5): raise Conflict("Feedback for this event cannot be modified.") existing_report.update( name=report.get("name", ""), email=report["email"], comments=report["comments"], date_added=timezone.now(), event_user_id=euser.id if euser else None, ) report_instance = existing_report else: if report_instance.group_id: report_instance.notify() user_feedback_received.send(project=project, sender=save_userreport) return report_instance
def post(self, request, project): """ Submit User Feedback ```````````````````` Submit and associate user feedback with an issue. Feedback must be received by the server no more than 30 minutes after the event was saved. Additionally, within 5 minutes of submitting feedback it may also be overwritten. This is useful in situations where you may need to retry sending a request due to network failures. If feedback is rejected due to a mutability threshold, a 409 status code will be returned. Note: Feedback may be submitted with DSN authentication (see auth documentation). :pparam string organization_slug: the slug of the organization. :pparam string project_slug: the slug of the project. :auth: required :param string event_id: the event ID :param string name: user's name :param string email: user's email address :param string comments: comments supplied by user """ if hasattr(request.auth, 'project_id') and project.id != request.auth.project_id: return self.respond(status=400) serializer = UserReportSerializer(data=request.data) if not serializer.is_valid(): return self.respond(serializer.errors, status=400) report = serializer.validated_data # XXX(dcramer): enforce case insensitivty by coercing this to a lowercase string report['event_id'] = report['event_id'].lower() report['project'] = project event = eventstore.get_event_by_id(project.id, report['event_id']) # TODO(dcramer): we should probably create the user if they dont # exist, and ideally we'd also associate that with the event euser = self.find_event_user(report, event) if euser and not euser.name and report['name']: euser.update(name=report['name']) if euser: report['event_user_id'] = euser.id if event: # if the event is more than 30 minutes old, we dont allow updates # as it might be abusive if event.datetime < timezone.now() - timedelta(minutes=30): return self.respond( {'detail': 'Feedback for this event cannot be modified.'}, status=409) report['environment'] = event.get_environment() report['group'] = event.group try: with transaction.atomic(): report_instance = UserReport.objects.create(**report) except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. existing_report = UserReport.objects.get( project=report['project'], event_id=report['event_id'], ) # if the existing report was submitted more than 5 minutes ago, we dont # allow updates as it might be abusive (replay attacks) if existing_report.date_added < timezone.now() - timedelta( minutes=5): return self.respond( {'detail': 'Feedback for this event cannot be modified.'}, status=409) existing_report.update( name=report['name'], email=report['email'], comments=report['comments'], date_added=timezone.now(), event_user_id=euser.id if euser else None, ) report_instance = existing_report else: if report_instance.group: report_instance.notify() user_feedback_received.send(project=report_instance.project, group=report_instance.group, sender=self) return self.respond( serialize( report_instance, request.user, UserReportWithGroupSerializer( environment_func=self._get_environment_func( request, project.organization_id))))
def post(self, request, project): """ Submit User Feedback ```````````````````` Submit and associate user feedback with an issue. :pparam string organization_slug: the slug of the organization. :pparam string project_slug: the slug of the project. :auth: required :param string event_id: the event ID :param string name: user's name :param string email: user's email address :param string comments: comments supplied by user """ serializer = UserReportSerializer(data=request.DATA) if not serializer.is_valid(): return Response(serializer.errors, status=400) report = serializer.object report.project = project # TODO(dcramer): we should probably create the user if they dont # exist, and ideally we'd also associate that with the event euser = self.find_event_user(report) if euser and not euser.name and report.name: euser.update(name=report.name) if euser: report.event_user_id = euser.id try: event = Event.objects.filter(project_id=project.id, event_id=report.event_id)[0] except IndexError: try: report.group = Group.objects.from_event_id(project, report.event_id) except Group.DoesNotExist: pass else: report.environment = event.get_environment() report.group = event.group try: with transaction.atomic(): report.save() except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. existing_report = UserReport.objects.get( project=report.project, event_id=report.event_id, ) existing_report.update( name=report.name, email=report.email, comments=report.comments, date_added=timezone.now(), event_user_id=euser.id if euser else None, ) report = existing_report else: if report.group: report.notify() user_feedback_received.send(project=report.project, group=report.group, sender=self) return Response(serialize(report, request.user, ProjectUserReportSerializer( environment_func=self._get_environment_func( request, project.organization_id) )))
def dispatch(self, request): try: event_id = request.GET['eventId'] except KeyError: return self._smart_response( request, {'eventId': 'Missing or invalid parameter.'}, status=400) if event_id and not is_event_id(event_id): return self._smart_response( request, {'eventId': 'Missing or invalid parameter.'}, status=400) key = self._get_project_key(request) if not key: return self._smart_response( request, {'dsn': 'Missing or invalid parameter.'}, status=404) origin = self._get_origin(request) if not is_valid_origin(origin, key.project): return self._smart_response(request, status=403) if request.method == 'OPTIONS': return self._smart_response(request) # customization options options = DEFAULT_OPTIONS.copy() for name in six.iterkeys(options): if name in request.GET: options[name] = six.text_type(request.GET[name]) # TODO(dcramer): since we cant use a csrf cookie we should at the very # least sign the request / add some kind of nonce initial = { 'name': request.GET.get('name'), 'email': request.GET.get('email'), } form = UserReportForm(request.POST if request.method == 'POST' else None, initial=initial) if form.is_valid(): # TODO(dcramer): move this to post to the internal API report = form.save(commit=False) report.project = key.project report.event_id = event_id try: event = Event.objects.filter(project_id=report.project.id, event_id=report.event_id)[0] except IndexError: try: report.group = Group.objects.from_event_id(report.project, report.event_id) except Group.DoesNotExist: pass else: report.environment = event.get_environment() report.group = event.group try: with transaction.atomic(): report.save() except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. UserReport.objects.filter( project=report.project, event_id=report.event_id, ).update( name=report.name, email=report.email, comments=report.comments, date_added=timezone.now(), ) else: if report.group: report.notify() user_feedback_received.send(project=report.project, group=report.group, sender=self) return self._smart_response(request) elif request.method == 'POST': return self._smart_response( request, { "errors": dict(form.errors), }, status=400 ) show_branding = ProjectOption.objects.get_value( project=key.project, key='feedback:branding', default='1' ) == '1' template = render_to_string( 'sentry/error-page-embed.html', { 'form': form, 'show_branding': show_branding, 'title': options['title'], 'subtitle': options['subtitle'], 'subtitle2': options['subtitle2'], 'name_label': options['labelName'], 'email_label': options['labelEmail'], 'comments_label': options['labelComments'], 'submit_label': options['labelSubmit'], 'close_label': options['labelClose'], } ) context = { 'endpoint': mark_safe('*/' + json.dumps(request.build_absolute_uri()) + ';/*'), 'template': mark_safe('*/' + json.dumps(template) + ';/*'), 'strings': json.dumps_htmlsafe({ 'generic_error': six.text_type(options['errorGeneric']), 'form_error': six.text_type(options['errorFormEntry']), 'sent_message': six.text_type(options['successMessage']), }), } return render_to_response( 'sentry/error-page-embed.js', context, request, content_type='text/javascript' )
def dispatch(self, request): try: event_id = request.GET['eventId'] except KeyError: return self._json_response(request, status=400) if not is_event_id(event_id): return self._json_response(request, status=400) key = self._get_project_key(request) if not key: return self._json_response(request, status=404) origin = self._get_origin(request) if not origin: return self._json_response(request, status=403) if not is_valid_origin(origin, key.project): return HttpResponse(status=403) if request.method == 'OPTIONS': return self._json_response(request) # TODO(dcramer): since we cant use a csrf cookie we should at the very # least sign the request / add some kind of nonce initial = { 'name': request.GET.get('name'), 'email': request.GET.get('email'), } form = UserReportForm(request.POST if request.method == 'POST' else None, initial=initial) if form.is_valid(): # TODO(dcramer): move this to post to the internal API report = form.save(commit=False) report.project = key.project report.event_id = event_id try: mapping = EventMapping.objects.get( event_id=report.event_id, project_id=key.project_id, ) except EventMapping.DoesNotExist: # XXX(dcramer): the system should fill this in later pass else: report.group = Group.objects.get(id=mapping.group_id) try: with transaction.atomic(): report.save() except IntegrityError: # There was a duplicate, so just overwrite the existing # row with the new one. The only way this ever happens is # if someone is messing around with the API, or doing # something wrong with the SDK, but this behavior is # more reasonable than just hard erroring and is more # expected. UserReport.objects.filter( project=report.project, event_id=report.event_id, ).update( name=report.name, email=report.email, comments=report.comments, date_added=timezone.now(), ) user_feedback_received.send(project=report.project, group=report.group, sender=self) return self._json_response(request) elif request.method == 'POST': return self._json_response(request, { "errors": dict(form.errors), }, status=400) show_branding = ProjectOption.objects.get_value( project=key.project, key='feedback:branding', default='1' ) == '1' template = render_to_string('sentry/error-page-embed.html', { 'form': form, 'show_branding': show_branding, }) context = { 'endpoint': mark_safe('*/' + json.dumps(request.build_absolute_uri()) + ';/*'), 'template': mark_safe('*/' + json.dumps(template) + ';/*'), 'strings': json.dumps_htmlsafe({ 'generic_error': six.text_type(GENERIC_ERROR), 'form_error': six.text_type(FORM_ERROR), 'sent_message': six.text_type(SENT_MESSAGE), }), } return render_to_response('sentry/error-page-embed.js', context, request, content_type='text/javascript')