def issue_state_change(self, group, identity, data): event_write_key = ApiKey( organization=group.project.organization, scope_list=["event:write"] ) # undoing the enum structure of ACTION_TYPE to # get a more sensible analytics_event action_types = { ACTION_TYPE.RESOLVE: "resolve", ACTION_TYPE.IGNORE: "ignore", ACTION_TYPE.ASSIGN: "assign", ACTION_TYPE.UNRESOLVE: "unresolve", ACTION_TYPE.UNASSIGN: "unassign", } action_data = self.make_action_data(data, identity.user_id) status = action_types[data["payload"]["actionType"]] analytics_event = "integrations.msteams.%s" % status analytics.record( analytics_event, actor_id=identity.user_id, organization_id=group.project.organization.id, ) return client.put( path=u"/projects/{}/{}/issues/".format( group.project.organization.slug, group.project.slug ), params={"id": group.id}, data=action_data, user=identity.user, auth=event_write_key, )
def _handle_builtin(self, request, project): endpoint = "/projects/{}/{}/releases/".format( project.organization.slug, project.slug) try: data = json.loads(request.body) except json.JSONDecodeError as exc: return HttpResponse( status=400, content=json.dumps({"error": six.text_type(exc)}), content_type="application/json", ) try: # Ideally the API client would support some kind of god-mode here # as we've already confirmed credentials and simply want to execute # the view code. Instead we hack around it with an ApiKey instance god = ApiKey(organization=project.organization, scope_list=["project:write"]) resp = client.post(endpoint, data=data, auth=god) except client.ApiError as exc: return HttpResponse( status=exc.status_code, content=json.dumps(exc.body), content_type="application/json", ) return HttpResponse(status=resp.status_code, content=json.dumps(resp.data), content_type="application/json")
def set_refs(self, release, **values): # check if user exists, and then try to get refs based on version if values.get('owner', None): repo_project_option = ProjectOption.objects.get_value( project=self.project, key='heroku:repository', ) deploy_project_option = ProjectOption.objects.get_value( project=self.project, key='heroku:environment', default='production', ) or 'production' if repo_project_option: try: repository = Repository.objects.get( organization_id=self.project.organization_id, name=repo_project_option ) except Repository.DoesNotExist: logger.info( 'repository.missing', extra={ 'organization_id': self.project.organization_id, 'project_id': self.project.id, 'repository': repo_project_option, } ) else: release.set_refs( refs=[{ 'commit': release.version, 'repository': repository.name }], user=values['owner'], fetch=True, ) # create deploy associated with release via ReleaseDeploysEndpoint endpoint = '/organizations/{}/releases/{}/deploys/'.format( self.project.organization.slug, release.version, ) auth = ApiKey( organization=self.project.organization, scope_list=['project:write'], ) client.post( endpoint, data={'environment': deploy_project_option}, auth=auth, ) else: logger.info( 'owner.missing', extra={ 'organization_id': self.project.organization_id, 'project_id': self.project.id, } )
def update_group(self, group, identity, data): event_write_key = ApiKey(organization=group.project.organization, scope_list=["event:write"]) return client.put( path=u"/projects/{}/{}/issues/".format( group.project.organization.slug, group.project.slug), params={"id": group.id}, data=data, user=identity.user, auth=event_write_key, )
def update_group(self, group: Group, identity: Identity, data: Mapping[str, str]) -> Response: event_write_key = ApiKey( organization=group.project.organization, scope_list=["event:write"] ) return client.put( path=f"/projects/{group.project.organization.slug}/{group.project.slug}/issues/", params={"id": group.id}, data=data, user=identity.user, auth=event_write_key, )
def set_refs(self, release, **values): # check if user exists, and then try to get refs based on version if values.get("owner", None): repo_project_option = ProjectOption.objects.get_value( project=self.project, key="heroku:repository") deploy_project_option = (ProjectOption.objects.get_value( project=self.project, key="heroku:environment", default="production") or "production") if repo_project_option: try: repository = Repository.objects.get( organization_id=self.project.organization_id, name=repo_project_option) except Repository.DoesNotExist: logger.info( "repository.missing", extra={ "organization_id": self.project.organization_id, "project_id": self.project.id, "repository": repo_project_option, }, ) else: release.set_refs( refs=[{ "commit": release.version, "repository": repository.name }], user=values["owner"], fetch=True, ) # create deploy associated with release via ReleaseDeploysEndpoint endpoint = "/organizations/{}/releases/{}/deploys/".format( self.project.organization.slug, release.version) auth = ApiKey(organization=self.project.organization, scope_list=["project:write"]) client.post(endpoint, data={"environment": deploy_project_option}, auth=auth) else: logger.info( "owner.missing", extra={ "organization_id": self.project.organization_id, "project_id": self.project.id, }, )
def get_auth(self): try: return ApiKey(organization=self.project.organization, scope_list=["project:write"]) except ApiKey.DoesNotExist: return None
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, 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
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