def get(self, request, wizard_hash): """ This opens a page where with an active session fill stuff into the cache Redirects to organization whenever cache has been deleted """ context = { 'hash': wizard_hash } key = '%s%s' % (SETUP_WIZARD_CACHE_KEY, wizard_hash) wizard_data = default_cache.get(key) if wizard_data is None: return self.redirect_to_org(request) orgs = client.get( reverse('sentry-api-0-organizations'), request=request) filled_projects = [] for org in orgs.data: projects = client.get(reverse('sentry-api-0-organization-projects', kwargs={ 'organization_slug': org.get('slug') }), request=request) for project in projects.data: if project.get('status') == 'deleted': continue # skip if project has been deleted enriched_project = project enriched_project['organization'] = org keys = client.get(reverse('sentry-api-0-project-keys', kwargs={ 'organization_slug': org.get('slug'), 'project_slug': project.get('slug') }), request=request) enriched_project['keys'] = keys.data filled_projects.append(enriched_project) # Fetching or creating a token token = None tokens = [ x for x in ApiToken.objects.filter(user=request.user).all() if 'project:releases' in x.get_scopes() ] if not tokens: token = ApiToken.objects.create( user=request.user, scope_list=['project:releases'], refresh_token=None, expires_at=None, ) else: token = tokens[0] result = { 'apiKeys': serialize(token), 'projects': filled_projects } key = '%s%s' % (SETUP_WIZARD_CACHE_KEY, wizard_hash) default_cache.set(key, result, SETUP_WIZARD_CACHE_TIMEOUT) return render_to_response('sentry/setup-wizard.html', context, request)
def react_plugin_config(plugin, project, request): response = client.get( u"/projects/{}/{}/plugins/{}/".format(project.organization.slug, project.slug, plugin.slug), request=request, ) return mark_safe( """ <div id="ref-plugin-config"></div> <script> $(function(){ ReactDOM.render(React.createFactory(SentryApp.PluginConfig)({ project: %s, organization: %s, data: %s }), document.getElementById('ref-plugin-config')); }); </script> """ % ( json.dumps_htmlsafe(serialize(project, request.user)), json.dumps_htmlsafe(serialize(project.organization, request.user)), json.dumps_htmlsafe(response.data), ) )
def handle(self, request, organization, team, project, slug): try: plugin = plugins.get(slug) except KeyError: return self.redirect(reverse('sentry-manage-project', args=[project.organization.slug, project.slug])) if not plugin.can_configure_for_project(project): return self.redirect(reverse('sentry-manage-project', args=[project.organization.slug, project.slug])) react_plugin = None is_enabled = plugin.is_enabled(project) if isinstance(plugin, IssueTrackingPlugin2) or isinstance(plugin, NotificationPlugin): view = None response = client.get('/projects/{}/{}/plugins/{}/'.format( organization.slug, project.slug, slug, ), request=request) react_plugin = response.data else: view = plugin.configure(request=request, project=project) if isinstance(view, HttpResponse): return view context = { 'page': 'plugin', 'title': plugin.get_title(), 'view': view, 'plugin': plugin, 'plugin_is_enabled': is_enabled, 'react_plugin': react_plugin, } return self.respond('sentry/projects/plugins/configure.html', context)
def get(self, request: Request, group) -> Response: """ Retrieve the Oldest Event for an Issue `````````````````````````````````````` Retrieves the details of the oldest event for an issue. :pparam string group_id: the ID of the issue """ environments = [e.name for e in get_environments(request, group.project.organization)] event = group.get_oldest_event_for_environments(environments) if not event: return Response({"detail": "No events found for group"}, status=404) try: return client.get( f"/projects/{event.organization.slug}/{event.project.slug}/events/{event.event_id}/", request=request, data={"environment": environments, "group_id": event.group_id}, ) except client.ApiError as e: return Response(e.body, status=e.status_code)
def react_plugin_config(plugin, project, request): response = client.get( f"/projects/{project.organization.slug}/{project.slug}/plugins/{plugin.slug}/", request=request, ) nonce = "" if hasattr(request, "csp_nonce"): nonce = f' nonce="{request.csp_nonce}"' # Pretty sure this is not in use, and if it is, it has been broken since # https://github.com/getsentry/sentry/pull/13578/files#diff-d17d91cc629f5f2e4582adb6e52d426f654452b751da97bafa25160b78566438L206 return mark_safe(""" <div id="ref-plugin-config"></div> <script%s> window.__onSentryInit = window.__onSentryInit || []; window.__onSentryInit.push({ name: 'renderReact', component: 'PluginConfig', container: '#ref-plugin-config', props: { project: %s, organization: %s, data: %s }, }); </script> """ % ( nonce, json.dumps_htmlsafe(serialize(project, request.user)), json.dumps_htmlsafe(serialize(project.organization, request.user)), json.dumps_htmlsafe(response.data), ))
def react_plugin_config(plugin, project, request): response = client.get( f"/projects/{project.organization.slug}/{project.slug}/plugins/{plugin.slug}/", request=request, ) nonce = "" if hasattr(request, "csp_nonce"): nonce = f' nonce="{request.csp_nonce}"' return mark_safe(""" <div id="ref-plugin-config"></div> <script%s> $(function(){ ReactDOM.render(React.createFactory(SentryApp.PluginConfig)({ project: %s, organization: %s, data: %s }), document.getElementById('ref-plugin-config')); }); </script> """ % ( nonce, json.dumps_htmlsafe(serialize(project, request.user)), json.dumps_htmlsafe(serialize(project.organization, request.user)), json.dumps_htmlsafe(response.data), ))
def get(self, request: Request, group) -> Response: """ Retrieve the Latest Event for an Issue `````````````````````````````````````` Retrieves the details of the latest event for an issue. :pparam string group_id: the ID of the issue """ environments = [ e.name for e in get_environments(request, group.project.organization) ] event = group.get_latest_event_for_environments(environments) if not event: return Response({"detail": "No events found for group"}, status=404) collapse = request.GET.getlist("collapse", []) if "stacktraceOnly" in collapse: return Response(serialize(event, request.user, EventSerializer())) try: return client.get( f"/projects/{event.organization.slug}/{event.project.slug}/events/{event.event_id}/", request=request, data={ "environment": environments, "group_id": event.group_id }, ) except client.ApiError as e: return Response(e.body, status=e.status_code)
def get(self, request, group): """ Retrieve the Latest Event for an Issue `````````````````````````````````````` Retrieves the details of the latest event for an issue. :pparam string group_id: the ID of the issue """ environments = [ e.name for e in get_environments(request, group.project.organization) ] event = group.get_latest_event_for_environments(environments) if not event: return Response({"detail": "No events found for group"}, status=404) try: return client.get( u"/projects/{}/{}/events/{}/".format(event.organization.slug, event.project.slug, event.event_id), request=request, ) except client.ApiError as e: return Response(e.body, status=e.status_code)
def get(self, request, group): """ Retrieve the Oldest Event for an Issue `````````````````````````````````````` Retrieves the details of the oldest event for an issue. :pparam string group_id: the ID of the issue """ environments = [e.name for e in get_environments(request, group.project.organization)] event = group.get_oldest_event_for_environments(environments) if not event: return Response({'detail': 'No events found for group'}, status=404) try: return client.get(u'/projects/{}/{}/events/{}/'.format( event.organization.slug, event.project.slug, event.event_id ), request=request) except client.ApiError as e: return Response(e.body, status=e.status_code)
def react_plugin_config(plugin, project, request): response = client.get( '/projects/{}/{}/plugins/{}/'.format( project.organization.slug, project.slug, plugin.slug, ), request=request ) return mark_safe( """ <div id="ref-plugin-config"></div> <script> $(function(){ ReactDOM.render(React.createFactory(Sentry.PluginConfig)({ project: %s, organization: %s, data: %s }), document.getElementById('ref-plugin-config')); }); </script> """ % ( json.dumps_htmlsafe(serialize(project, request.user)), json.dumps_htmlsafe(serialize(project.organization, request.user)), json.dumps_htmlsafe(response.data) ) )
def get(self, request, group): """ Retrieve the latest event Return details on the latest event for this group. {method} {path} """ event = group.get_latest_event() return client.get("/events/{}/".format(event.id), request.user, request.auth)
def get(self, request, group): """ Retrieve the latest sample for an aggregate Return details on the latest sample for this aggregate. {method} {path} """ event = group.get_latest_event() return client.get('/events/{}/'.format(event.id), request.user, request.auth)
def get(self, request, group): """ Retrieve the latest sample for an aggregate Return details on the latest sample for this aggregate. {method} {path} """ event = group.get_latest_event() try: return client.get('/events/{}/'.format(event.id), request.user, request.auth) except client.ApiError as e: return Response(e.body, status=e.status)
def get(self, request, group): """ Retrieve the latest sample for an aggregate Return details on the latest sample for this aggregate. {method} {path} """ event = group.get_latest_event() try: return client.get('/events/{}/'.format(event.id), request.user, request.auth) except client.ApiError as e: return Response(e.body, status=e.status_code)
def post(self, request): """ Authenticate a user Authenticate a user using the provided credentials. curl -X {method} -u PUBLIC_KEY:SECRET_KEY {path} """ if not request.user.is_authenticated(): return Response(status=400) # Must use the real request object that Django knows about login(request._request, request.user) return client.get('/users/me/', request.user, request.auth)
def get(self, request, group): """ Latest Sample ````````````` Retrieves the details of the latest sample for an aggregate. :pparam string group_id: the ID of the group to get the latest sample of. """ event = group.get_latest_event() if not event: return Response({'detail': 'No events found for group'}, status=404) try: return client.get('/events/{}/'.format(event.id), request=request) except client.ApiError as e: return Response(e.body, status=e.status_code)
def get(self, request, group): """ Retrieve Latest Event ````````````````````` Retrieves the details of the latest event for an issue. :pparam string group_id: the ID of the issue """ event = group.get_latest_event() if not event: return Response({'detail': 'No events found for group'}, status=404) try: return client.get(u'/events/{}/'.format(event.id), request=request) except client.ApiError as e: return Response(e.body, status=e.status_code)
def get(self, request, group): """ Retrieve the Latest Event for an Issue `````````````````````````````````````` Retrieves the details of the latest event for an issue. :pparam string group_id: the ID of the issue """ event = group.get_latest_event() if not event: return Response({'detail': 'No events found for group'}, status=404) try: return client.get(u'/events/{}/'.format(event.id), request=request) except client.ApiError as e: return Response(e.body, status=e.status_code)
def handle(self, request, organization, team, project, slug): try: plugin = plugins.get(slug) except KeyError: return self.redirect( reverse('sentry-manage-project', args=[project.organization.slug, project.slug])) if not plugin.can_configure_for_project(project): return self.redirect( reverse('sentry-manage-project', args=[project.organization.slug, project.slug])) react_plugin = None is_enabled = plugin.is_enabled(project) if isinstance(plugin, IssueTrackingPlugin2) or isinstance( plugin, NotificationPlugin): view = None response = client.get('/projects/{}/{}/plugins/{}/'.format( organization.slug, project.slug, slug, ), request=request) react_plugin = response.data else: view = plugin.configure(request=request, project=project) if isinstance(view, HttpResponse): return view context = { 'page': 'plugin', 'title': plugin.get_title(), 'view': view, 'plugin': plugin, 'plugin_is_enabled': is_enabled, 'react_plugin': react_plugin, } return self.respond('sentry/projects/plugins/configure.html', context)
def get(self, request): """ Retrieve an aggregate Return details on an individual aggregate specified by query parameters. {method} {path}?shareId=mnIX """ share_id = request.GET.get('shareId') if share_id: try: group = Group.from_share_id(share_id) except Group.DoesNotExist: group = None else: group = None if not group: return Response({'detail': 'No groups found'}, status=404) return client.get('/groups/{}/'.format(group.id), request.user, request.auth)
def post(self, request): """ Authenticate a User ``````````````````` This endpoint authenticates a user using the provided credentials through a regular HTTP basic auth system. The response contains cookies that need to be sent with further requests that require authentication. This is primarily used internally in Sentry. Common example:: curl -X ###METHOD### -u username:password ###URL### """ if not request.user.is_authenticated(): return Response(status=400) # Must use the real request object that Django knows about login(request._request, request.user) return client.get('/users/me/', request.user, request.auth)
def post(self, request): """ Authenticate a User ``````````````````` This endpoint authenticates a user using the provided credentials through a regular HTTP basic auth system. The response contains cookies that need to be sent with further requests that require authentication. This is primarily used internally in Sentry. Common example:: curl -X ###METHOD### -u username:password ###URL### """ if not request.user.is_authenticated(): return Response(status=400) # Must use the real request object that Django knows about login(request._request, request.user) return client.get('/users/me/', request=request)
def get(self, request, group): event = group.get_latest_event() return client.get('/events/{}/'.format(event.id), request.user, request.auth)
def unfurl_discover(data, integration, links: List[UnfurlableUrl]) -> UnfurledUrl: orgs_by_slug = {org.slug: org for org in integration.organizations.all()} unfurls = {} for link in links: org_slug = link.args["org_slug"] org = orgs_by_slug.get(org_slug) # If the link shared is an org w/o the slack integration do not unfurl if not org: continue if not features.has("organizations:chart-unfurls", org): continue params = link.args["query"] query_id = params.get("id", None) saved_query = {} if query_id: try: response = client.get( auth=ApiKey(organization=org, scope_list=["org:read"]), path= f"/organizations/{org_slug}/discover/saved/{query_id}/", ) except Exception as exc: logger.error( "Failed to load saved query for unfurl: %s", str(exc), exc_info=True, ) else: saved_query = response.data # Override params from Discover Saved Query if they aren't in the URL params.setlist( "order", params.getlist("sort") or to_list(saved_query.get("orderby"))) params.setlist( "name", params.getlist("name") or to_list(saved_query.get("name"))) params.setlist( "yAxis", params.getlist("yAxis") or to_list(saved_query.get("yAxis", "count()"))) params.setlist( "field", params.getlist("field") or to_list(saved_query.get("fields"))) # Only override if key doesn't exist since we want to account for # an intermediate state where the query could have been cleared if "query" not in params: params.setlist( "query", params.getlist("query") or to_list(saved_query.get("query"))) display_mode = str( params.get("display") or saved_query.get("display", "default")) if "daily" in display_mode: params.setlist("interval", ["1d"]) if "top5" in display_mode: params.setlist("topEvents", [f"{TOP_N}"]) try: resp = client.get( auth=ApiKey(organization=org, scope_list=["org:read"]), path=f"/organizations/{org_slug}/events-stats/", params=params, ) except Exception as exc: logger.error( "Failed to load events-stats for unfurl: %s", str(exc), exc_info=True, ) continue chart_data = {"seriesName": params.get("yAxis"), "stats": resp.data} style = display_modes.get(display_mode, display_modes["default"]) try: url = generate_chart(style, chart_data) except RuntimeError as exc: logger.error( "Failed to generate chat for discover unfurl: %s", str(exc), exc_info=True, ) continue unfurls[link.url] = build_discover_attachment( title=link.args["query"].get("name", "Dashboards query"), chart_url=url, ) return unfurls
def unfurl_discover( data: HttpRequest, integration: Integration, links: List[UnfurlableUrl], user: Optional["User"], ) -> UnfurledUrl: orgs_by_slug = {org.slug: org for org in integration.organizations.all()} unfurls = {} for link in links: org_slug = link.args["org_slug"] org = orgs_by_slug.get(org_slug) # If the link shared is an org w/o the slack integration do not unfurl if not org: continue if not features.has("organizations:discover-basic", org): continue params = link.args["query"] query_id = params.get("id", None) saved_query = {} if query_id: try: response = client.get( auth=ApiKey(organization=org, scope_list=["org:read"]), path=f"/organizations/{org_slug}/discover/saved/{query_id}/", ) except Exception as exc: logger.error( f"Failed to load saved query for unfurl: {exc}", exc_info=True, ) else: saved_query = response.data # Override params from Discover Saved Query if they aren't in the URL params.setlist( "order", params.getlist("sort") or (to_list(saved_query.get("orderby")) if saved_query.get("orderby") else []), ) params.setlist("name", params.getlist("name") or to_list(saved_query.get("name"))) fields = params.getlist("field") or to_list(saved_query.get("fields")) # Mimic Discover to pick the first aggregate as the yAxis option if # one isn't specified. axis_options = [field for field in fields if is_aggregate(field)] + [DEFAULT_AXIS_OPTION] params.setlist( "yAxis", params.getlist("yAxis") or to_list(saved_query.get("yAxis", axis_options[0])) ) params.setlist("field", params.getlist("field") or to_list(saved_query.get("fields"))) params.setlist( "project", params.getlist("project") or (to_list(saved_query.get("project")) if saved_query.get("project") else []), ) # Only override if key doesn't exist since we want to account for # an intermediate state where the query could have been cleared if "query" not in params: params.setlist( "query", params.getlist("query") or to_list(saved_query.get("query", "")) ) display_mode = str(params.get("display") or saved_query.get("display", "default")) if "daily" in display_mode: params.setlist("interval", ["1d"]) if "top5" in display_mode: params.setlist( "topEvents", params.getlist("topEvents") or to_list(saved_query.get("topEvents", f"{TOP_N}")), ) y_axis = params.getlist("yAxis")[0] if display_mode != "dailytop5": display_mode = get_top5_display_mode(y_axis) else: # topEvents param persists in the URL in some cases, we want to discard # it if it's not a top n display type. params.pop("topEvents", None) if "previous" in display_mode: stats_period = params.getlist("statsPeriod", [DEFAULT_PERIOD])[0] parsed_period = parse_stats_period(stats_period) if parsed_period and parsed_period <= timedelta(days=MAX_PERIOD_DAYS_INCLUDE_PREVIOUS): stats_period = get_double_period(stats_period) params.setlist("statsPeriod", [stats_period]) endpoint = "events-stats/" if "worldmap" in display_mode: endpoint = "events-geo/" params.setlist("field", params.getlist("yAxis")) params.pop("sort", None) try: resp = client.get( auth=ApiKey(organization=org, scope_list=["org:read"]), user=user, path=f"/organizations/{org_slug}/{endpoint}", params=params, ) except Exception as exc: logger.error( f"Failed to load {endpoint} for unfurl: {exc}", exc_info=True, ) continue chart_data = {"seriesName": params.get("yAxis"), "stats": resp.data} style = display_modes.get(display_mode, display_modes["default"]) try: url = generate_chart(style, chart_data) except RuntimeError as exc: logger.error( f"Failed to generate chart for discover unfurl: {exc}", exc_info=True, ) continue unfurls[link.url] = SlackDiscoverMessageBuilder( title=link.args["query"].get("name", "Dashboards query"), chart_url=url, ).build() analytics.record( "integrations.slack.chart_unfurl", organization_id=integration.organizations.all()[0].id, user_id=user.id if user else None, unfurls_count=len(unfurls), ) return unfurls
def unfurl_discover(data, integration, links: List[UnfurlableUrl]) -> UnfurledUrl: orgs_by_slug = {org.slug: org for org in integration.organizations.all()} unfurls = {} for link in links: org_slug = link.args["org_slug"] org = orgs_by_slug.get(org_slug) # If the link shared is an org w/o the slack integration do not unfurl if not org: continue if not features.has("organizations:chart-unfurls", org): continue params = link.args["query"] params.setlist("order", params.get("sort")) display_mode = str(link.args["query"].get("display", "default")) if "daily" in display_mode: params.setlist("interval", ["1d"]) if "top5" in display_mode: params.setlist("topEvents", [f"{TOP_N}"]) try: resp = client.get( auth=ApiKey(organization=org, scope_list=["org:read"]), path=f"/organizations/{org_slug}/events-stats/", params=params, ) except Exception as exc: logger.error( "Failed to load events-stats for unfurl: %s", str(exc), exc_info=True, ) continue chart_data = { "seriesName": link.args["query"].get("yAxis", "count()"), "stats": resp.data } style = display_modes.get(display_mode, display_modes["default"]) try: url = generate_chart(style, chart_data) except RuntimeError as exc: logger.error( "Failed to generate chat for discover unfurl: %s", str(exc), exc_info=True, ) continue unfurls[link.url] = build_discover_attachment( title=link.args["query"].get("name", "Dashboards query"), chart_url=url, ) return unfurls