<s> from __future__ import absolute_import , print_function <EOL> import logging <EOL> import traceback <EOL> from django . conf import settings <EOL> from django . contrib . auth . models import AnonymousUser <EOL> from django . core . cache import cache <EOL> from django . core . urlresolvers import reverse <EOL> from django . http import HttpResponse , HttpResponseRedirect , HttpResponseNotAllowed <EOL> from django . utils . encoding import force_bytes <EOL> from django . views . decorators . cache import never_cache , cache_control <EOL> from django . views . decorators . csrf import csrf_exempt <EOL> from django . views . generic . base import View as BaseView <EOL> from functools import wraps <EOL> from raven . contrib . django . models import client as Raven <EOL> from sentry import app <EOL> from sentry . coreapi import ( <EOL> APIError , APIForbidden , APIRateLimited , ClientApiHelper , CspApiHelper <EOL> ) <EOL> from sentry . event_manager import EventManager <EOL> from sentry . models import Project , OrganizationOption <EOL> from sentry . signals import event_received <EOL> from sentry . quotas . base import RateLimit <EOL> from sentry . utils import json , metrics <EOL> from sentry . utils . csp import is_valid_csp_report <EOL> from sentry . utils . data_scrubber import SensitiveDataFilter <EOL> from sentry . utils . http import ( <EOL> is_valid_origin , get_origins , is_same_domain , is_valid_ip , <EOL> ) <EOL> from sentry . utils . safe import safe_execute <EOL> from sentry . web . helpers import render_to_response <EOL> logger = logging . getLogger ( '<STR_LIT>' ) <EOL> PIXEL = '<STR_LIT>' . decode ( '<STR_LIT>' ) <EOL> PROTOCOL_VERSIONS = frozenset ( ( '<STR_LIT>' , '<STR_LIT:3>' , '<STR_LIT:4>' , '<STR_LIT:5>' , '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> def api ( func ) : <EOL> @ wraps ( func ) <EOL> def wrapped ( request , * args , ** kwargs ) : <EOL> data = func ( request , * args , ** kwargs ) <EOL> if request . is_ajax ( ) : <EOL> response = HttpResponse ( data ) <EOL> response [ '<STR_LIT:Content-Type>' ] = '<STR_LIT:application/json>' <EOL> else : <EOL> ref = request . META . get ( '<STR_LIT>' ) <EOL> if ref is None or not is_same_domain ( ref , request . build_absolute_uri ( ) ) : <EOL> ref = reverse ( '<STR_LIT>' ) <EOL> return HttpResponseRedirect ( ref ) <EOL> return response <EOL> return wrapped <EOL> class APIView ( BaseView ) : <EOL> helper_cls = ClientApiHelper <EOL> def _get_project_from_id ( self , project_id ) : <EOL> if not project_id : <EOL> return <EOL> if not project_id . isdigit ( ) : <EOL> raise APIError ( '<STR_LIT>' % project_id ) <EOL> try : <EOL> return Project . objects . get_from_cache ( id = project_id ) <EOL> except Project . DoesNotExist : <EOL> raise APIError ( '<STR_LIT>' % project_id ) <EOL> def _parse_header ( self , request , helper , project ) : <EOL> auth = helper . auth_from_request ( request ) <EOL> if auth . version not in PROTOCOL_VERSIONS : <EOL> raise APIError ( '<STR_LIT>' % str ( auth . version or '<STR_LIT>' ) ) <EOL> if not auth . client : <EOL> raise APIError ( "<STR_LIT>" ) <EOL> return auth <EOL> @ csrf_exempt <EOL> @ never_cache <EOL> def dispatch ( self , request , project_id = None , * args , ** kwargs ) : <EOL> helper = self . helper_cls ( <EOL> agent = request . META . get ( '<STR_LIT>' ) , <EOL> project_id = project_id , <EOL> ip_address = request . META [ '<STR_LIT>' ] , <EOL> ) <EOL> origin = None <EOL> try : <EOL> origin = helper . origin_from_request ( request ) <EOL> response = self . _dispatch ( request , helper , project_id = project_id , <EOL> origin = origin , <EOL> * args , ** kwargs ) <EOL> except APIError as e : <EOL> context = { <EOL> '<STR_LIT:error>' : force_bytes ( e . msg , errors = '<STR_LIT:replace>' ) , <EOL> } <EOL> if e . name : <EOL> context [ '<STR_LIT>' ] = e . name <EOL> response = HttpResponse ( json . dumps ( context ) , <EOL> content_type = '<STR_LIT:application/json>' , <EOL> status = e . http_status ) <EOL> response [ '<STR_LIT>' ] = context [ '<STR_LIT:error>' ] <EOL> if isinstance ( e , APIRateLimited ) and e . retry_after is not None : <EOL> response [ '<STR_LIT>' ] = str ( e . retry_after ) <EOL> except Exception as e : <EOL> if settings . DEBUG : <EOL> content = traceback . format_exc ( ) <EOL> else : <EOL> content = '<STR_LIT>' <EOL> logger . exception ( e ) <EOL> response = HttpResponse ( content , <EOL> content_type = '<STR_LIT>' , <EOL> status = <NUM_LIT> ) <EOL> metrics . incr ( '<STR_LIT>' ) <EOL> metrics . incr ( '<STR_LIT>' % ( <EOL> response . status_code , <EOL> ) ) <EOL> metrics . incr ( '<STR_LIT>' % ( <EOL> str ( response . status_code ) [ <NUM_LIT:0> ] , <EOL> ) ) <EOL> if helper . context . version : <EOL> metrics . incr ( '<STR_LIT>' % ( <EOL> helper . context . version , <EOL> ) ) <EOL> metrics . incr ( '<STR_LIT>' % ( <EOL> helper . context . version , response . status_code <EOL> ) ) <EOL> metrics . incr ( '<STR_LIT>' % ( <EOL> helper . context . version , str ( response . status_code ) [ <NUM_LIT:0> ] <EOL> ) ) <EOL> if response . status_code != <NUM_LIT:200> and origin : <EOL> response [ '<STR_LIT>' ] = '<STR_LIT:*>' <EOL> if origin : <EOL> response [ '<STR_LIT>' ] = '<STR_LIT>' '<STR_LIT>' <EOL> response [ '<STR_LIT>' ] = '<STR_LIT:U+002CU+0020>' . join ( self . _allowed_methods ( ) ) <EOL> return response <EOL> def _dispatch ( self , request , helper , project_id = None , origin = None , <EOL> * args , ** kwargs ) : <EOL> request . user = AnonymousUser ( ) <EOL> project = self . _get_project_from_id ( project_id ) <EOL> if project : <EOL> helper . context . bind_project ( project ) <EOL> Raven . tags_context ( helper . context . get_tags_context ( ) ) <EOL> if origin is not None : <EOL> if not project : <EOL> raise APIError ( '<STR_LIT>' ) <EOL> if not is_valid_origin ( origin , project ) : <EOL> raise APIForbidden ( '<STR_LIT>' % ( origin , ) ) <EOL> if request . method == '<STR_LIT>' : <EOL> response = self . options ( request , project ) <EOL> else : <EOL> auth = self . _parse_header ( request , helper , project ) <EOL> project_ = helper . project_from_auth ( auth ) <EOL> if not project : <EOL> if not project_ : <EOL> raise APIError ( '<STR_LIT>' ) <EOL> project = project_ <EOL> helper . context . bind_project ( project ) <EOL> elif project_ != project : <EOL> raise APIError ( '<STR_LIT>' ) <EOL> helper . context . bind_auth ( auth ) <EOL> Raven . tags_context ( helper . context . get_tags_context ( ) ) <EOL> if auth . version != '<STR_LIT>' : <EOL> if not auth . secret_key : <EOL> if origin is None and request . method != '<STR_LIT:GET>' : <EOL> raise APIForbidden ( '<STR_LIT>' ) <EOL> if not is_valid_origin ( origin , project ) : <EOL> raise APIForbidden ( '<STR_LIT>' ) <EOL> response = super ( APIView , self ) . dispatch ( <EOL> request = request , <EOL> project = project , <EOL> auth = auth , <EOL> helper = helper , <EOL> ** kwargs <EOL> ) <EOL> if origin : <EOL> response [ '<STR_LIT>' ] = origin <EOL> return response <EOL> def _allowed_methods ( self ) : <EOL> return [ m . upper ( ) for m in self . http_method_names if hasattr ( self , m ) ] <EOL> def options ( self , request , * args , ** kwargs ) : <EOL> response = HttpResponse ( ) <EOL> response [ '<STR_LIT>' ] = '<STR_LIT:U+002CU+0020>' . join ( self . _allowed_methods ( ) ) <EOL> response [ '<STR_LIT>' ] = '<STR_LIT:0>' <EOL> return response <EOL> class StoreView ( APIView ) : <EOL> """<STR_LIT>""" <EOL> def post ( self , request , ** kwargs ) : <EOL> data = request . body <EOL> response_or_event_id = self . process ( request , data = data , ** kwargs ) <EOL> if isinstance ( response_or_event_id , HttpResponse ) : <EOL> return response_or_event_id <EOL> return HttpResponse ( json . dumps ( { <EOL> '<STR_LIT:id>' : response_or_event_id , <EOL> } ) , content_type = '<STR_LIT:application/json>' ) <EOL> def get ( self , request , ** kwargs ) : <EOL> data = request . GET . get ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> response_or_event_id = self . process ( request , data = data , ** kwargs ) <EOL> response = HttpResponse ( PIXEL , '<STR_LIT>' ) <EOL> if not isinstance ( response_or_event_id , HttpResponse ) : <EOL> response [ '<STR_LIT>' ] = response_or_event_id <EOL> return response <EOL> def process ( self , request , project , auth , helper , data , ** kwargs ) : <EOL> metrics . incr ( '<STR_LIT>' ) <EOL> remote_addr = request . META [ '<STR_LIT>' ] <EOL> event_received . send_robust ( ip = remote_addr , sender = type ( self ) ) <EOL> if not is_valid_ip ( remote_addr , project ) : <EOL> app . tsdb . incr_multi ( [ <EOL> ( app . tsdb . models . project_total_received , project . id ) , <EOL> ( app . tsdb . models . project_total_blacklisted , project . id ) , <EOL> ( app . tsdb . models . organization_total_received , project . organization_id ) , <EOL> ( app . tsdb . models . organization_total_blacklisted , project . organization_id ) , <EOL> ] ) <EOL> metrics . incr ( '<STR_LIT>' ) <EOL> raise APIForbidden ( '<STR_LIT>' % ( remote_addr , ) ) <EOL> rate_limit = safe_execute ( app . quotas . is_rate_limited , project = project , <EOL> _with_transaction = False ) <EOL> if isinstance ( rate_limit , bool ) : <EOL> rate_limit = RateLimit ( is_limited = rate_limit , retry_after = None ) <EOL> if rate_limit is None or rate_limit . is_limited : <EOL> if rate_limit is None : <EOL> helper . log . debug ( '<STR_LIT>' ) <EOL> app . tsdb . incr_multi ( [ <EOL> ( app . tsdb . models . project_total_received , project . id ) , <EOL> ( app . tsdb . models . project_total_rejected , project . id ) , <EOL> ( app . tsdb . models . organization_total_received , project . organization_id ) , <EOL> ( app . tsdb . models . organization_total_rejected , project . organization_id ) , <EOL> ] ) <EOL> metrics . incr ( '<STR_LIT>' ) <EOL> if rate_limit is not None : <EOL> raise APIRateLimited ( rate_limit . retry_after ) <EOL> else : <EOL> app . tsdb . incr_multi ( [ <EOL> ( app . tsdb . models . project_total_received , project . id ) , <EOL> ( app . tsdb . models . organization_total_received , project . organization_id ) , <EOL> ] ) <EOL> content_encoding = request . META . get ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> if isinstance ( data , basestring ) : <EOL> if content_encoding == '<STR_LIT>' : <EOL> data = helper . decompress_gzip ( data ) <EOL> elif content_encoding == '<STR_LIT>' : <EOL> data = helper . decompress_deflate ( data ) <EOL> elif not data . startswith ( '<STR_LIT:{>' ) : <EOL> data = helper . decode_and_decompress_data ( data ) <EOL> data = helper . safely_load_json_string ( data ) <EOL> data = helper . validate_data ( project , data ) <EOL> if '<STR_LIT>' not in data : <EOL> sdk = helper . parse_client_as_sdk ( auth . client ) <EOL> if sdk : <EOL> data [ '<STR_LIT>' ] = sdk <EOL> manager = EventManager ( data , version = auth . version ) <EOL> data = manager . normalize ( ) <EOL> org_options = OrganizationOption . objects . get_all_values ( project . organization_id ) <EOL> if org_options . get ( '<STR_LIT>' , False ) : <EOL> scrub_ip_address = True <EOL> else : <EOL> scrub_ip_address = project . get_option ( '<STR_LIT>' , False ) <EOL> if auth . is_public and not scrub_ip_address : <EOL> helper . ensure_has_ip ( data , remote_addr ) <EOL> event_id = data [ '<STR_LIT>' ] <EOL> cache_key = '<STR_LIT>' % ( project . id , event_id , ) <EOL> if cache . get ( cache_key ) is not None : <EOL> raise APIForbidden ( '<STR_LIT>' % ( event_id , ) ) <EOL> if org_options . get ( '<STR_LIT>' , False ) : <EOL> scrub_data = True <EOL> else : <EOL> scrub_data = project . get_option ( '<STR_LIT>' , True ) <EOL> if scrub_data : <EOL> sensitive_fields_key = '<STR_LIT>' <EOL> sensitive_fields = ( <EOL> org_options . get ( sensitive_fields_key , [ ] ) + <EOL> project . get_option ( sensitive_fields_key , [ ] ) <EOL> ) <EOL> if org_options . get ( '<STR_LIT>' , False ) : <EOL> scrub_defaults = True <EOL> else : <EOL> scrub_defaults = project . get_option ( '<STR_LIT>' , True ) <EOL> inst = SensitiveDataFilter ( <EOL> fields = sensitive_fields , <EOL> include_defaults = scrub_defaults , <EOL> ) <EOL> inst . apply ( data ) <EOL> if scrub_ip_address : <EOL> helper . ensure_does_not_have_ip ( data ) <EOL> helper . insert_data_to_database ( data ) <EOL> cache . set ( cache_key , '<STR_LIT>' , <NUM_LIT> * <NUM_LIT:5> ) <EOL> helper . log . debug ( '<STR_LIT>' , event_id ) <EOL> return event_id <EOL> class CspReportView ( StoreView ) : <EOL> helper_cls = CspApiHelper <EOL> content_types = ( '<STR_LIT>' , '<STR_LIT:application/json>' ) <EOL> def _dispatch ( self , request , helper , project_id = None , origin = None , <EOL> * args , ** kwargs ) : <EOL> if request . method != '<STR_LIT:POST>' : <EOL> return HttpResponseNotAllowed ( [ '<STR_LIT:POST>' ] ) <EOL> if request . META . get ( '<STR_LIT>' ) not in self . content_types : <EOL> raise APIError ( '<STR_LIT>' ) <EOL> request . user = AnonymousUser ( ) <EOL> project = self . _get_project_from_id ( project_id ) <EOL> helper . context . bind_project ( project ) <EOL> Raven . tags_context ( helper . context . get_tags_context ( ) ) <EOL> auth = helper . auth_from_request ( request ) <EOL> project_ = helper . project_from_auth ( auth ) <EOL> if project_ != project : <EOL> raise APIError ( '<STR_LIT>' ) <EOL> helper . context . bind_auth ( auth ) <EOL> Raven . tags_context ( helper . context . get_tags_context ( ) ) <EOL> return super ( APIView , self ) . dispatch ( <EOL> request = request , <EOL> project = project , <EOL> auth = auth , <EOL> helper = helper , <EOL> ** kwargs <EOL> ) <EOL> def post ( self , request , project , auth , helper , ** kwargs ) : <EOL> data = helper . safely_load_json_string ( request . body ) <EOL> try : <EOL> report = data [ '<STR_LIT>' ] <EOL> except KeyError : <EOL> raise APIError ( '<STR_LIT>' ) <EOL> origin = report . get ( '<STR_LIT>' ) <EOL> if origin == '<STR_LIT>' : <EOL> raise APIForbidden ( '<STR_LIT>' ) <EOL> if not is_valid_origin ( origin , project ) : <EOL> raise APIForbidden ( '<STR_LIT>' ) <EOL> if not is_valid_csp_report ( report , project ) : <EOL> app . tsdb . incr_multi ( [ <EOL> ( app . tsdb . models . project_total_received , project . id ) , <EOL> ( app . tsdb . models . project_total_blacklisted , project . id ) , <EOL> ( app . tsdb . models . organization_total_received , project . organization_id ) , <EOL> ( app . tsdb . models . organization_total_blacklisted , project . organization_id ) , <EOL> ] ) <EOL> metrics . incr ( '<STR_LIT>' ) <EOL> raise APIForbidden ( '<STR_LIT>' ) <EOL> response_or_event_id = self . process ( <EOL> request , <EOL> project = project , <EOL> auth = auth , <EOL> helper = helper , <EOL> data = report , <EOL> ** kwargs <EOL> ) <EOL> if isinstance ( response_or_event_id , HttpResponse ) : <EOL> return response_or_event_id <EOL> return HttpResponse ( status = <NUM_LIT> ) <EOL> @ cache_control ( max_age = <NUM_LIT> , public = True ) <EOL> def robots_txt ( request ) : <EOL> return HttpResponse ( "<STR_LIT>" , content_type = '<STR_LIT>' ) <EOL> @ cache_control ( max_age = <NUM_LIT> , public = True ) <EOL> def crossdomain_xml_index ( request ) : <EOL> response = render_to_response ( '<STR_LIT>' ) <EOL> response [ '<STR_LIT:Content-Type>' ] = '<STR_LIT>' <EOL> return response <EOL> @ cache_control ( max_age = <NUM_LIT> ) <EOL> def crossdomain_xml ( request , project_id ) : <EOL> if not project_id . isdigit ( ) : <EOL> return HttpResponse ( status = <NUM_LIT> ) <EOL> try : <EOL> project = Project . objects . get_from_cache ( id = project_id ) <EOL> except Project . DoesNotExist : <EOL> return HttpResponse ( status = <NUM_LIT> ) <EOL> origin_list = get_origins ( project ) <EOL> response = render_to_response ( '<STR_LIT>' , { <EOL> '<STR_LIT>' : origin_list <EOL> } ) <EOL> response [ '<STR_LIT:Content-Type>' ] = '<STR_LIT>' <EOL> return response </s>
