def _send_webhook(self): safe_urlread( safe_urlopen( url=self.sentry_app.webhook_url, data=self.request.body, headers=self.request.headers, timeout=5, ))
def _send_webhook(self): safe_urlread( safe_urlopen( url=self.sentry_app.webhook_url, data=self.request.body, headers=self.request.headers, timeout=5, ) )
def _make_request(self): try: req = send_and_save_sentry_app_request( self._build_url(), self.sentry_app, self.install.organization_id, "alert_rule_action.requested", headers=self._build_headers(), method=self.http_method, data=self.body, ) body = safe_urlread(req) response = { "success": True, "message": "", "body": json.loads(body) } except Exception as e: logger.info( "alert_rule_action.error", extra={ "sentry_app_slug": self.sentry_app.slug, "install_uuid": self.install.uuid, "uri": self.uri, "error_message": str(e), }, ) # Bubble up error message from Sentry App to the UI for the user. response = { "success": False, "message": str(e.response.text), "body": {} } return response
def exchange_token(self, request, pipeline, code): from urllib.parse import parse_qsl from sentry.http import safe_urlopen, safe_urlread from sentry.utils import json from sentry.utils.http import absolute_uri req = safe_urlopen( url=self.access_token_url, headers={ "Content-Type": "application/x-www-form-urlencoded", "Content-Length": "1322" }, data={ "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", "client_assertion": self.client_secret, "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": code, "redirect_uri": absolute_uri(pipeline.redirect_url()), }, ) body = safe_urlread(req) if req.headers["Content-Type"].startswith( "application/x-www-form-urlencoded"): return dict(parse_qsl(body)) return json.loads(body)
def refresh_identity(self, identity, *args, **kwargs): refresh_token = identity.data.get('refresh_token') refresh_token_url = kwargs.get('refresh_token_url') if not refresh_token: raise IdentityNotValid('Missing refresh token') if not refresh_token_url: raise IdentityNotValid('Missing refresh token url') data = self.get_refresh_token_params(refresh_token, *args, **kwargs) req = safe_urlopen( url=refresh_token_url, headers={}, data=data, ) try: body = safe_urlread(req) payload = json.loads(body) except Exception: payload = {} self.handle_refresh_error(req, payload) identity.data.update(get_oauth_data(payload)) return identity.update(data=identity.data)
def create_issue(self, request, group, form_data, **kwargs): json_data = { 'story_type': 'bug', 'name': force_text(form_data['title'], encoding='utf-8', errors='replace'), 'description': force_text(form_data['description'], encoding='utf-8', errors='replace'), 'labels': ['sentry'], } try: _url = self.build_api_url(group, 'stories') req = self.make_api_request(group.project, _url, json_data=json_data) body = safe_urlread(req) except requests.RequestException as e: msg = six.text_type(e) raise PluginError('Error communicating with Pivotal: %s' % (msg, )) try: json_resp = json.loads(body) except ValueError as e: msg = six.text_type(e) raise PluginError('Error communicating with Pivotal: %s' % (msg, )) if req.status_code > 399: raise PluginError(json_resp['error']) return json_resp['id']
def exchange_token(self, request, pipeline, code): # TODO: this needs the auth yet data = self.get_token_params( code=code, redirect_uri=absolute_uri(pipeline.redirect_url()), ) verify_ssl = pipeline.config.get('verify_ssl', True) try: req = safe_urlopen(self.access_token_url, data=data, verify_ssl=verify_ssl) body = safe_urlread(req) if req.headers.get('Content-Type', '').startswith('application/x-www-form-urlencoded'): return dict(parse_qsl(body)) return json.loads(body) except SSLError: logger.info('identity.oauth2.ssl-error', extra={ 'url': self.access_token_url, 'verify_ssl': verify_ssl, }) url = self.access_token_url return { 'error': 'Could not verify SSL certificate', 'error_description': u'Ensure that {} has a valid SSL certificate'.format(url) } except JSONDecodeError: logger.info('identity.oauth2.json-error', extra={ 'url': self.access_token_url, }) return { 'error': 'Could not decode a JSON Response', 'error_description': u'We were not able to parse a JSON response, please try again.' }
def view_autocomplete(self, request, group, **kwargs): field = request.GET.get('autocomplete_field') query = request.GET.get('autocomplete_query') if field != 'issue_id' or not query: return Response({'issue_id': []}) query = query.encode('utf-8') _url = '%s?%s' % (self.build_api_url( group, 'search'), urlencode({'query': query})) try: req = self.make_api_request(group.project, _url) body = safe_urlread(req) except (requests.RequestException, PluginError) as e: return self.handle_api_error(e) try: json_resp = json.loads(body) except ValueError as e: return self.handle_api_error(e) resp = json_resp.get('stories', {}) stories = resp.get('stories', []) issues = [{ 'text': '(#%s) %s' % (i['id'], i['name']), 'id': i['id'] } for i in stories] return Response({field: issues})
def get_issue_title_by_id(self, request, group, issue_id): _url = "{}/{}".format(self.build_api_url(group, "stories"), issue_id) req = self.make_api_request(group.project, _url) body = safe_urlread(req) json_resp = json.loads(body) return json_resp["name"]
def exchange_token(self, request, helper, code): # TODO: this needs the auth yet data = self.get_token_params(code=code, redirect_uri=absolute_uri(helper.get_redirect_url())) req = safe_urlopen(self.access_token_url, data=data) body = safe_urlread(req) return json.loads(body)
def create_issue(self, request, group, form_data, **kwargs): json_data = { "story_type": "bug", "name": force_text(form_data["title"], encoding="utf-8", errors="replace"), "description": force_text(form_data["description"], encoding="utf-8", errors="replace"), "labels": ["sentry"], } try: _url = self.build_api_url(group, "stories") req = self.make_api_request(group.project, _url, json_data=json_data) body = safe_urlread(req) except requests.RequestException as e: msg = str(e) raise PluginError(f"Error communicating with Pivotal: {msg}") try: json_resp = json.loads(body) except ValueError as e: msg = str(e) raise PluginError(f"Error communicating with Pivotal: {msg}") if req.status_code > 399: raise PluginError(json_resp["error"]) return json_resp["id"]
def exchange_token(self, request, pipeline, code): from sentry.http import safe_urlopen, safe_urlread from sentry.utils.http import absolute_uri from six.moves.urllib.parse import parse_qsl from sentry.utils import json req = safe_urlopen( url=self.access_token_url, headers={ 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': '1322', }, data={ 'client_assertion_type': 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer', 'client_assertion': self.client_secret, 'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion': code, 'redirect_uri': absolute_uri(pipeline.redirect_url()), }, ) body = safe_urlread(req) if req.headers['Content-Type'].startswith( 'application/x-www-form-urlencoded'): return dict(parse_qsl(body)) return json.loads(body)
def _make_request(self): req = safe_urlopen(url=self._build_url(), headers=self._build_headers(), method="POST", data=self.body) try: body = safe_urlread(req) response = json.loads(body) except Exception: logger.info( "issue-link-requester.error", extra={ "sentry_app": self.sentry_app.slug, "install": self.install.uuid, "project": self.group.project.slug, "group": self.group.id, "uri": self.uri, }, ) response = {} if not self._validate_response(response): raise APIError() return response
def dispatch(self, request, helper): access_token = helper.fetch_state('data')['access_token'] req = safe_urlopen('{0}?{1}&alt=json'.format( USER_DETAILS_ENDPOINT, urlencode({ 'access_token': access_token, }))) body = safe_urlread(req) data = json.loads(body) if not data.get('data'): logger.error('Invalid response: %s' % body) return helper.error(ERR_INVALID_RESPONSE) if not data.get('data').get('email'): logger.error('Invalid response: %s' % body) return helper.error(ERR_INVALID_RESPONSE) domain = extract_domain(data.get('data').get('email')) if domain in DOMAIN_BLOCKLIST: return helper.error(ERR_INVALID_DOMAIN % (domain, )) if self.domain and self.domain != domain: return helper.error(ERR_INVALID_DOMAIN % (domain, )) helper.bind_state('domain', domain) helper.bind_state('user', data.get('data')) return helper.next_step()
def _make_request(self): try: req = send_and_save_sentry_app_request( self._build_url(), self.sentry_app, self.install.organization_id, "alert_rule_action.requested", headers=self._build_headers(), method=self.http_method, data=self.body, ) body = safe_urlread(req) response = json.loads(body) except Exception as e: logger.info( "alert_rule_action.error", extra={ "sentry_app_slug": self.sentry_app.slug, "install_uuid": self.install.uuid, "uri": self.uri, "error_message": str(e), }, ) response = {} return response
def refresh_identity(self, identity, *args, **kwargs): refresh_token = identity.data.get('refresh_token') refresh_token_url = kwargs.get('refresh_token_url') if not refresh_token: raise IdentityNotValid('Missing refresh token') if not refresh_token_url: raise IdentityNotValid('Missing refresh token url') data = self.get_refresh_token_params(refresh_token, *args, **kwargs) req = safe_urlopen( url=refresh_token_url, headers={}, data=data, ) try: body = safe_urlread(req) payload = json.loads(body) except Exception as e: self.logger('gitlab.refresh-identity-failure', extra={ 'identity_id': identity.id, 'error_status': e.code, 'error_message': e.message, }) payload = {} self.handle_refresh_error(req, payload) identity.data.update(get_oauth_data(payload)) return identity.update(data=identity.data)
def refresh_identity(self, auth_identity): refresh_token = auth_identity.data.get("refresh_token") if not refresh_token: raise IdentityNotValid("Missing refresh token") data = self.get_refresh_token_params(refresh_token=refresh_token) req = safe_urlopen(self.get_refresh_token_url(), data=data) try: body = safe_urlread(req) payload = json.loads(body) except Exception: payload = {} error = payload.get("error", "unknown_error") error_description = payload.get("error_description", "no description available") formatted_error = "HTTP {} ({}): {}".format(req.status_code, error, error_description) if req.status_code == 401: raise IdentityNotValid(formatted_error) if req.status_code == 400: # this may not be common, but at the very least Google will return # an invalid grant when a user is suspended if error == "invalid_grant": raise IdentityNotValid(formatted_error) if req.status_code != 200: raise Exception(formatted_error) auth_identity.data.update(self.get_oauth_data(payload)) auth_identity.update(data=auth_identity.data)
def _make_request(self): try: body = safe_urlread( safe_urlopen( url=self._build_url(), headers=self._build_headers(), ) ) response = json.loads(body) except Exception as e: logger.info( 'select-requester.error', extra={ 'sentry_app': self.sentry_app.slug, 'install': self.install.uuid, 'project': self.project and self.project.slug, 'uri': self.uri, 'error_message': e.message, } ) response = {} if not self._validate_response(response): raise APIError() return self._format_response(response)
def refresh_identity(self, identity, *args, **kwargs): refresh_token = identity.data.get("refresh_token") refresh_token_url = kwargs.get("refresh_token_url") if not refresh_token: raise IdentityNotValid("Missing refresh token") if not refresh_token_url: raise IdentityNotValid("Missing refresh token url") data = self.get_refresh_token_params(refresh_token, *args, **kwargs) req = safe_urlopen(url=refresh_token_url, headers={}, data=data) try: body = safe_urlread(req) payload = json.loads(body) except Exception as e: self.logger( "gitlab.refresh-identity-failure", extra={ "identity_id": identity.id, "error_status": e.code, "error_message": str(e), }, ) payload = {} self.handle_refresh_error(req, payload) identity.data.update(get_oauth_data(payload)) return identity.update(data=identity.data)
def view(self, request, group, **kwargs): if request.GET.get('autocomplete_query'): query = request.GET.get('q') if not query: return JSONResponse({'issues': []}) repo = self.get_option('repo', group.project) query = 'repo:%s %s' % (repo, query) url = 'https://api.github.com/search/issues?%s' % (urlencode({'q': query}),) try: req = self.make_api_request(request.user, url) body = safe_urlread(req) except requests.RequestException as e: msg = unicode(e) self.handle_api_error(request, msg) return JSONResponse({}, status=502) try: json_resp = json.loads(body) except ValueError as e: msg = unicode(e) self.handle_api_error(request, msg) return JSONResponse({}, status=502) issues = [{ 'text': '(#%s) %s' % (i['number'], i['title']), 'id': i['number'] } for i in json_resp.get('items', [])] return JSONResponse({'issues': issues}) return super(GitHubPlugin, self).view(request, group, **kwargs)
def _make_request(self): req = safe_urlopen( url=self._build_url(), headers=self._build_headers(), method='POST', data=self.body, ) try: body = safe_urlread(req) response = json.loads(body) except Exception: logger.info('issue-link-requester.error', extra={ 'sentry_app': self.sentry_app.slug, 'install': self.install.uuid, 'project': self.group.project.slug, 'group': self.group.id, 'uri': self.uri, }) response = {} if not self._validate_response(response): raise APIError() return response
def get_issue_title_by_id(self, request, group, issue_id): url = '%s/%s' % (self.build_api_url(group, 'issues'), issue_id) req = self.make_api_request(request.user, url) body = safe_urlread(req) json_resp = json.loads(body) return json_resp['title']
def create_issue(self, request, group, form_data, **kwargs): # TODO: support multiple identities via a selection input in the form? json_data = { "title": form_data['title'], "body": form_data['description'], "assignee": form_data.get('assignee'), } try: url = self.build_api_url(group, 'issues') req = self.make_api_request(request.user, url, json_data=json_data) body = safe_urlread(req) except requests.RequestException as e: msg = unicode(e) raise forms.ValidationError(_('Error communicating with GitHub: %s') % (msg,)) try: json_resp = json.loads(body) except ValueError as e: msg = unicode(e) raise forms.ValidationError(_('Error communicating with GitHub: %s') % (msg,)) if req.status_code > 399: raise forms.ValidationError(json_resp['message']) return json_resp['number']
def _make_request(self) -> Mapping[str, Union[bool, str]]: try: req = send_and_save_sentry_app_request( self._build_url(), self.sentry_app, self.install.organization_id, "alert_rule_action.requested", headers=self._build_headers(), method=self.http_method, data=self.body, ) except Exception as e: logger.info( "alert_rule_action.error", extra={ "sentry_app_slug": self.sentry_app.slug, "install_uuid": self.install.uuid, "uri": self.uri, "error_message": str(e), }, ) message = f"{self.sentry_app.name}: {str(e.response.text) or DEFAULT_ERROR_MESSAGE}" # Bubble up error message from Sentry App to the UI for the user. return {"success": False, "message": message} body_raw = safe_urlread(req) body = body_raw.decode() if body_raw else None message = f"{self.sentry_app.name}: {body or DEFAULT_SUCCESS_MESSAGE}" return {"success": True, "message": message}
def view_autocomplete(self, request, group, **kwargs): field = request.GET.get("autocomplete_field") query = request.GET.get("autocomplete_query") if field != "issue_id" or not query: return Response({"issue_id": []}) query = query.encode("utf-8") _url = "{}?{}".format(self.build_api_url(group, "search"), urlencode({"query": query})) try: req = self.make_api_request(group.project, _url) body = safe_urlread(req) except (requests.RequestException, PluginError) as e: return self.handle_api_error(e) try: json_resp = json.loads(body) except ValueError as e: return self.handle_api_error(e) resp = json_resp.get("stories", {}) stories = resp.get("stories", []) issues = [{ "text": "(#{}) {}".format(i["id"], i["name"]), "id": i["id"] } for i in stories] return Response({field: issues})
def _make_request(self): action_to_past_tense = {"create": "created", "link": "linked"} try: req = send_and_save_sentry_app_request( self._build_url(), self.sentry_app, self.install.organization_id, "external_issue.{}".format(action_to_past_tense[self.action]), headers=self._build_headers(), method="POST", data=self.body, ) body = safe_urlread(req) response = json.loads(body) except Exception as e: logger.info( "issue-link-requester.error", extra={ "sentry_app": self.sentry_app.slug, "install": self.install.uuid, "project": self.group.project.slug, "group": self.group.id, "uri": self.uri, "error_message": str(e), }, ) response = {} if not self._validate_response(response): raise APIError() return response
def get_issue_title_by_id(self, request, group, issue_id): _url = '%s/%s' % (self.build_api_url(group, 'stories'), issue_id) req = self.make_api_request(group.project, _url) body = safe_urlread(req) json_resp = json.loads(body) return json_resp['name']
def github_request(self, request, url, **kwargs): """ Make a GitHub request on behalf of the logged in user. Return JSON response on success or raise forms.ValidationError on any exception """ auth = self.get_auth_for_user(user=request.user) if auth is None: raise forms.ValidationError(_("You have not yet associated GitHub with your account.")) headers = kwargs.pop("headers", None) or {} headers["Authorization"] = "token %s" % auth.tokens["access_token"] try: req = safe_urlopen(url, headers=headers, **kwargs) body = safe_urlread(req) except requests.RequestException as e: msg = unicode(e) raise forms.ValidationError(_("Error communicating with GitHub: %s") % (msg,)) try: json_resp = json.loads(body) except ValueError as e: msg = unicode(e) raise forms.ValidationError(_("Error communicating with GitHub: %s") % (msg,)) if req.status_code > 399: raise forms.ValidationError(json_resp["message"]) return json_resp
def exchange_token(self, request, pipeline, code): # TODO: this needs the auth yet data = self.get_token_params(code=code, redirect_uri=absolute_uri(pipeline.redirect_url())) verify_ssl = pipeline.config.get("verify_ssl", True) try: req = safe_urlopen(self.access_token_url, data=data, verify_ssl=verify_ssl) body = safe_urlread(req) if req.headers.get("Content-Type", "").startswith("application/x-www-form-urlencoded"): return dict(parse_qsl(body)) return json.loads(body) except SSLError: logger.info( "identity.oauth2.ssl-error", extra={"url": self.access_token_url, "verify_ssl": verify_ssl}, ) url = self.access_token_url return { "error": "Could not verify SSL certificate", "error_description": u"Ensure that {} has a valid SSL certificate".format(url), } except JSONDecodeError: logger.info("identity.oauth2.json-error", extra={"url": self.access_token_url}) return { "error": "Could not decode a JSON Response", "error_description": u"We were not able to parse a JSON response, please try again.", }
def _make_request(self): try: body = safe_urlread( send_and_save_sentry_app_request( self._build_url(), self.sentry_app, self.install.organization_id, "select_options.requested", headers=self._build_headers(), )) response = json.loads(body) except Exception as e: logger.info( "select-requester.error", extra={ "sentry_app": self.sentry_app.slug, "install": self.install.uuid, "project": self.project and self.project.slug, "uri": self.uri, "error_message": six.text_type(e), }, ) response = {} if not self._validate_response(response): raise APIError() return self._format_response(response)
def refresh_identity(self, auth_identity): refresh_token = auth_identity.data.get("refresh_token") if not refresh_token: raise IdentityNotValid("Missing refresh token") data = self.get_refresh_token_params(refresh_token=refresh_token) req = safe_urlopen(self.get_refresh_token_url(), data=data) try: body = safe_urlread(req) payload = json.loads(body) except Exception: payload = {} error = payload.get("error", "unknown_error") error_description = payload.get("error_description", "no description available") formatted_error = f"HTTP {req.status_code} ({error}): {error_description}" if req.status_code == 401: raise IdentityNotValid(formatted_error) if req.status_code == 400: # this may not be common, but at the very least Google will return # an invalid grant when a user is suspended if error == "invalid_grant": raise IdentityNotValid(formatted_error) if req.status_code != 200: raise Exception(formatted_error) auth_identity.data.update(self.get_oauth_data(payload)) auth_identity.update(data=auth_identity.data)
def _make_request(self): req = safe_urlopen( url=self._build_url(), headers=self._build_headers(), method='POST', data=self.body, ) try: body = safe_urlread(req) response = json.loads(body) except Exception: logger.info( 'issue-link-requester.error', extra={ 'sentry_app': self.sentry_app.slug, 'install': self.install.uuid, 'project': self.group.project.slug, 'group': self.group.id, 'uri': self.uri, } ) response = {} if not self._validate_response(response): raise APIError() return response
def _make_request(self): req = safe_urlopen( url=self._build_url(), headers=self._build_headers(), ) try: body = safe_urlread(req) response = json.loads(body) except Exception: logger.info( 'select-requester.error', extra={ 'sentry_app': self.sentry_app.slug, 'install': self.install.uuid, 'project': self.project.slug, 'uri': self.uri, } ) response = {} if not self._validate_response(response): raise APIError() return self._format_response(response)
def dispatch(self, request, helper): access_token = helper.fetch_state('data')['access_token'] req = safe_urlopen('{0}?{1}&alt=json'.format( USER_DETAILS_ENDPOINT, urlencode({ 'access_token': access_token, }) )) body = safe_urlread(req) data = json.loads(body) if not data.get('data'): logger.error('Invalid response: %s' % body) return helper.error(ERR_INVALID_RESPONSE) if not data.get('data').get('email'): logger.error('Invalid response: %s' % body) return helper.error(ERR_INVALID_RESPONSE) domain = extract_domain(data.get('data').get('email')) if domain in DOMAIN_BLOCKLIST: return helper.error(ERR_INVALID_DOMAIN % (domain,)) if self.domain and self.domain != domain: return helper.error(ERR_INVALID_DOMAIN % (domain,)) helper.bind_state('domain', domain) helper.bind_state('user', data.get('data')) return helper.next_step()
def exchange_token(self, request, helper, code): # TODO: this needs the auth yet data = self.get_token_params(code=code, redirect_uri=absolute_uri(helper.get_redirect_url())) req = safe_urlopen(self.access_token_url, data=data) body = safe_urlread(req) if req.headers["Content-Type"].startswith("application/x-www-form-urlencoded"): return dict(parse_qsl(body)) return json.loads(body)
def exchange_token(self, request, helper, code): # TODO: this needs the auth yet data = self.get_token_params(code=code, redirect_uri=helper.get_redirect_url()) req = safe_urlopen(self.access_token_url, data=data) body = safe_urlread(req) if req.headers["Content-Type"].startswith("application/x-www-form-urlencoded"): return dict(parse_qsl(body)) return json.loads(body)
def exchange_token(self, request, helper, code): # TODO: this needs the auth yet data = self.get_token_params( code=code, redirect_uri=absolute_uri(helper.get_redirect_url()), ) req = safe_urlopen(self.access_token_url, data=data) body = safe_urlread(req) return json.loads(body)
def test_simple(self): responses.add(responses.GET, 'http://example.com', body='foo bar') resp = safe_urlopen('http://example.com') data = safe_urlread(resp) assert data == 'foo bar' request = responses.calls[0].request assert 'User-Agent' in request.headers assert 'gzip' in request.headers.get('Accept-Encoding', '')
def test_simple(self, mock_getaddrinfo): mock_getaddrinfo.return_value = [(2, 1, 6, '', ('81.0.0.1', 0))] responses.add(responses.GET, 'http://example.com', body='foo bar') resp = http.safe_urlopen('http://example.com') data = http.safe_urlread(resp) assert data.decode('utf-8') == 'foo bar' request = responses.calls[0].request assert 'User-Agent' in request.headers assert 'gzip' in request.headers.get('Accept-Encoding', '')
def fetch_url(url, project=None): """ Pull down a URL, returning a UrlResult object. Attempts to fetch from the cache. """ cache_key = 'source:%s' % ( hashlib.md5(url.encode('utf-8')).hexdigest(),) result = cache.get(cache_key) if result is None: # lock down domains that are problematic domain = urlparse(url).netloc domain_key = 'source:%s' % (hashlib.md5(domain.encode('utf-8')).hexdigest(),) domain_result = cache.get(domain_key) if domain_result: return BAD_SOURCE headers = [] if project and is_valid_origin(url, project=project): token = project.get_option('sentry:token') if token: headers.append(('X-Sentry-Token', token)) try: request = safe_urlopen( url, allow_redirects=True, headers=headers, timeout=settings.SENTRY_SOURCE_FETCH_TIMEOUT, ) except HTTPError: result = BAD_SOURCE except Exception: # it's likely we've failed due to a timeout, dns, etc so let's # ensure we can't cascade the failure by pinning this for 5 minutes cache.set(domain_key, 1, 300) logger.warning('Disabling sources to %s for %ss', domain, 300, exc_info=True) return BAD_SOURCE else: try: body = safe_urlread(request) except Exception: result = BAD_SOURCE else: result = (dict(request.headers), body) cache.set(cache_key, result, 60) if result == BAD_SOURCE: return result return UrlResult(url, *result)
def test_simple(self, mock_gethostbyname): mock_gethostbyname.return_value = '81.0.0.1' responses.add(responses.GET, 'http://example.com', body='foo bar') resp = http.safe_urlopen('http://example.com') data = http.safe_urlread(resp) assert data == 'foo bar' request = responses.calls[0].request assert 'User-Agent' in request.headers assert 'gzip' in request.headers.get('Accept-Encoding', '')
def exchange_token(self, request, pipeline, code): # TODO: this needs the auth yet data = self.get_token_params( code=code, redirect_uri=absolute_uri(pipeline.redirect_url()), ) verify_ssl = pipeline.config.get('verify_ssl', True) req = safe_urlopen(self.access_token_url, data=data, verify_ssl=verify_ssl) body = safe_urlread(req) if req.headers['Content-Type'].startswith('application/x-www-form-urlencoded'): return dict(parse_qsl(body)) return json.loads(body)
def send_beacon(): """ Send a Beacon to a remote server operated by the Sentry team. See the documentation for more details. """ from sentry import options from sentry.models import Organization, Project, Team, User if not settings.SENTRY_BEACON: logger.info('Not sending beacon (disabled)') return # TODO(dcramer): move version code off of PyPi and into beacon install_id = options.get('sentry:install-id') if not install_id: logger.info('Generated installation ID: %s', install_id) install_id = sha1(uuid4().hex).hexdigest() options.set('sentry:install-id', install_id) internal_project_ids = filter(bool, [ settings.SENTRY_PROJECT, settings.SENTRY_FRONTEND_PROJECT, ]) platform_list = list(set(Project.objects.exclude( id__in=internal_project_ids, ).values_list('platform', flat=True))) payload = { 'install_id': install_id, 'version': sentry.get_version(), 'admin_email': settings.SENTRY_ADMIN_EMAIL, 'data': { # TODO(dcramer): we'd also like to get an idea about the throughput # of the system (i.e. events in 24h) 'platforms': platform_list, 'users': User.objects.count(), 'projects': Project.objects.count(), 'teams': Team.objects.count(), 'organizations': Organization.objects.count(), } } # TODO(dcramer): relay the response 'notices' as admin broadcasts try: request = safe_urlopen(BEACON_URL, json=payload, timeout=5) response = safe_urlread(request) except Exception: logger.warning('Failed sending beacon', exc_info=True) return data = json.loads(response) if 'version' in data: options.set('sentry:latest_version', data['version']['stable'])
def send_beacon(): """ Send a Beacon to a remote server operated by the Sentry team. See the documentation for more details. """ from sentry import options from sentry.models import Organization, Project, Team, User if not settings.SENTRY_BEACON: logger.info('Not sending beacon (disabled)') return install_id = options.get('sentry:install-id') if not install_id: logger.info('Generated installation ID: %s', install_id) install_id = sha1(uuid4().hex).hexdigest() options.set('sentry:install-id', install_id) end = timezone.now() events_24h = tsdb.get_sums( model=tsdb.models.internal, keys=['events.total'], start=end - timedelta(hours=24), end=end, )['events.total'] payload = { 'install_id': install_id, 'version': sentry.get_version(), 'admin_email': settings.SENTRY_ADMIN_EMAIL, 'data': { # TODO(dcramer): we'd also like to get an idea about the throughput # of the system (i.e. events in 24h) 'users': User.objects.count(), 'projects': Project.objects.count(), 'teams': Team.objects.count(), 'organizations': Organization.objects.count(), 'events.24h': events_24h, } } # TODO(dcramer): relay the response 'notices' as admin broadcasts try: request = safe_urlopen(BEACON_URL, json=payload, timeout=5) response = safe_urlread(request) except Exception: logger.warning('Failed sending beacon', exc_info=True) return data = json.loads(response) if 'version' in data: options.set('sentry:latest_version', data['version']['stable'])
def test_simple(self, mock_gethostbyname): responses.add(responses.GET, 'http://example.com', body='foo bar') # this test fails if you dont have working DNS as it resolves it to # localhost, so we patch gethostbyname mock_gethostbyname.return_value = '208.1.41.1' resp = safe_urlopen('http://example.com') data = safe_urlread(resp) assert data == 'foo bar' request = responses.calls[0].request assert 'User-Agent' in request.headers assert 'gzip' in request.headers.get('Accept-Encoding', '')
def dispatch(self, request, helper): access_token = helper.fetch_state('data')['access_token'] req = safe_urlopen('{0}?{1}'.format( USER_DETAILS_ENDPOINT, urlencode({ 'access_token': access_token, }), )) body = safe_urlread(req) data = json.loads(body) helper.bind_state('user', data) return helper.next_step()
def create_issue(self, request, group, form_data, **kwargs): # TODO: support multiple identities via a selection input in the form? auth = self.get_auth_for_user(user=request.user) if auth is None: raise forms.ValidationError(_('You have not yet associated GitHub with your account.')) repo = self.get_option('repo', group.project) endpoint = self.get_option('endpoint', group.project) or 'https://api.github.com' url = '%s/repos/%s/issues' % (endpoint, repo,) json_data = { "title": form_data['title'], "body": form_data['description'], # "assignee": form_data['asignee'], # "milestone": 1, # "labels": [ # "Label1", # "Label2" # ] } req_headers = { 'Authorization': 'token %s' % auth.tokens['access_token'], } try: req = safe_urlopen(url, json=json_data, headers=req_headers) body = safe_urlread(req) except requests.RequestException as e: msg = unicode(e) raise forms.ValidationError(_('Error communicating with GitHub: %s') % (msg,)) try: json_resp = json.loads(body) except ValueError as e: msg = unicode(e) raise forms.ValidationError(_('Error communicating with GitHub: %s') % (msg,)) if req.status_code > 399: raise forms.ValidationError(json_resp['message']) return json_resp['number']
def check_update(): """ Daily retrieving latest available Sentry version from PyPI """ from sentry.receivers import set_sentry_version try: request = safe_urlopen(PYPI_URL) result = safe_urlread(request) except Exception: logger.warning('Failed update info of latest version Sentry', exc_info=True) return try: version = json.loads(result)['info']['version'] set_sentry_version(version) except JSONDecodeError: logger.warning('Failed parsing data json from PYPI') except Exception: logger.warning('Failed update info of latest version Sentry', exc_info=True)
def link_issue(self, request, group, form_data, **kwargs): comment = form_data.get('comment') if not comment: return url = '%s/%s/comments' % (self.build_api_url(group, 'issues'), form_data['issue_id']) try: req = self.make_api_request(request.user, url, json_data={'body': comment}) body = safe_urlread(req) except requests.RequestException as e: msg = unicode(e) raise forms.ValidationError(_('Error communicating with GitHub: %s') % (msg,)) try: json_resp = json.loads(body) except ValueError as e: msg = unicode(e) raise forms.ValidationError(_('Error communicating with GitHub: %s') % (msg,)) if req.status_code > 399: raise forms.ValidationError(json_resp['message'])
def link_issue(self, request, group, form_data, **kwargs): comment = form_data.get('comment') if not comment: return _url = '%s/%s/comments' % (self.build_api_url(group, 'stories'), form_data['issue_id']) try: req = self.make_api_request(group.project, _url, json_data={"text": comment}) body = safe_urlread(req) except requests.RequestException as e: msg = six.text_type(e) raise PluginError('Error communicating with Pivotal: %s' % (msg, )) try: json_resp = json.loads(body) except ValueError as e: msg = six.text_type(e) raise PluginError('Error communicating with Pivotal: %s' % (msg, )) if req.status_code > 399: raise PluginError(json_resp['error'])
def dispatch(self, request, helper): access_token = helper.fetch_state('data')['access_token'] req = safe_urlopen('{0}?{1}'.format( USER_DETAILS_ENDPOINT, urlencode({ 'access_token': access_token, }), )) body = safe_urlread(req) data = json.loads(body) if not data.get('domain'): return helper.error(ERR_INVALID_DOMAIN) # a domain may not yet be configured as this could be the setup flow if self.domain and self.domain != data['domain']: return helper.error(ERR_INVALID_DOMAIN) helper.bind_state('user', data) return helper.next_step()
def exchange_token(self, request, pipeline, code): from sentry.http import safe_urlopen, safe_urlread from sentry.utils.http import absolute_uri from six.moves.urllib.parse import parse_qsl from sentry.utils import json req = safe_urlopen( url=self.access_token_url, headers={ 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': '1322', }, data={ 'client_assertion_type': 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer', 'client_assertion': self.client_secret, 'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion': code, 'redirect_uri': absolute_uri(pipeline.redirect_url()), }, ) body = safe_urlread(req) if req.headers['Content-Type'].startswith('application/x-www-form-urlencoded'): return dict(parse_qsl(body)) return json.loads(body)
def refresh_identity(self, identity, *args, **kwargs): refresh_token = identity.data.get('refresh_token') if not refresh_token: raise IdentityNotValid('Missing refresh token') data = self.get_refresh_token_params(refresh_token, *args, **kwargs) req = safe_urlopen( url=self.get_refresh_token_url(), headers=self.get_refresh_token_headers(), data=data, ) try: body = safe_urlread(req) payload = json.loads(body) except Exception: payload = {} self.handle_refresh_error(req, payload) identity.data.update(self.get_oauth_data(payload)) return identity.update(data=identity.data)