def test_raises_specific_error_for_the_literal_string_undefined_when_compressed( self): rf = RequestFactory() post_request = rf.post("/s/?compression=gzip-js", "undefined", "text/plain") with self.assertRaises(RequestParsingError) as ctx: load_data_from_request(post_request) self.assertEqual( "data being loaded from the request body for decompression is the literal string 'undefined'", str(ctx.exception), )
def test_pushes_request_origin_into_sentry_scope_even_when_not_available( self, patched_scope): mock_set_tag = mock_sentry_context_for_tagging(patched_scope) rf = RequestFactory() post_request = rf.post("/s/", "content", "text/plain") with self.assertRaises(RequestParsingError): load_data_from_request(post_request) patched_scope.assert_called_once() mock_set_tag.assert_has_calls( [call("origin", "unknown"), call("referer", "unknown")])
def feature_flags(request: HttpRequest) -> Dict[str, Any]: feature_flags_data = {"flags_enabled": [], "has_malformed_json": False} try: data_from_request = load_data_from_request(request) data = data_from_request["data"] except (json.decoder.JSONDecodeError, TypeError): feature_flags_data["has_malformed_json"] = True return feature_flags_data if not data: return feature_flags_data token = _get_token(data, request) is_personal_api_key = False if not token: token = PersonalAPIKeyAuthentication.find_key( request, data_from_request["body"], data if isinstance(data, dict) else None ) is_personal_api_key = True if not token: return feature_flags_data team = Team.objects.get_cached_from_token(token, is_personal_api_key) flags_enabled = [] feature_flags = FeatureFlag.objects.filter(team=team, active=True, deleted=False) for feature_flag in feature_flags: # distinct_id will always be a string, but data can have non-string values ("Any") if feature_flag.distinct_id_matches(data["distinct_id"]): flags_enabled.append(feature_flag.key) feature_flags_data["flags_enabled"] = flags_enabled return feature_flags_data
def get_data(request): data = None try: data = load_data_from_request(request) except RequestParsingError as error: capture_exception( error ) # We still capture this on Sentry to identify actual potential bugs return ( None, cors_response( request, generate_exception_response("capture", f"Malformed request data: {error}", code="invalid_payload"), ), ) if not data: return ( None, cors_response( request, generate_exception_response( "capture", "No data found. Make sure to use a POST request when sending the payload in the body of the request.", code="no_data", ), ), ) return data, None
def test_fails_to_JSON_parse_the_literal_string_undefined_when_not_compressed( self): """ load_data_from_request assumes that any data that has been received (and possibly decompressed) from the body can be parsed as JSON this test maintains the default (and possibly undesirable) behaviour for the uncompressed case """ rf = RequestFactory() post_request = rf.post("/s/", "undefined", "text/plain") with self.assertRaises(RequestParsingError) as ctx: load_data_from_request(post_request) self.assertEqual( "Invalid JSON: Expecting value: line 1 column 1 (char 0)", str(ctx.exception))
def test_pushes_request_origin_into_sentry_scope(self, patched_scope): origin = "potato.io" referer = "https://" + origin mock_set_tag = mock_sentry_context_for_tagging(patched_scope) rf = RequestFactory() post_request = rf.post("/s/", "content", "text/plain") post_request.META["REMOTE_HOST"] = origin post_request.META["HTTP_REFERER"] = referer with self.assertRaises(RequestParsingError) as ctx: load_data_from_request(post_request) patched_scope.assert_called_once() mock_set_tag.assert_has_calls( [call("origin", origin), call("referer", referer)])
def get_decide(request: HttpRequest): response = { "config": { "enable_collect_everything": True }, "editorParams": {}, "isAuthenticated": False, "supportedCompression": ["gzip", "lz64"], } if request.COOKIES.get(settings.TOOLBAR_COOKIE_NAME): response["isAuthenticated"] = True if settings.JS_URL: response["editorParams"] = { "jsURL": settings.JS_URL, "toolbarVersion": "toolbar" } if request.user.is_authenticated: r, update_user_token = decide_editor_params(request) response.update(r) if update_user_token: request.user.temporary_token = secrets.token_urlsafe(32) request.user.save() response["featureFlags"] = [] response["sessionRecording"] = False if request.method == "POST": try: data_from_request = load_data_from_request(request) except (json.decoder.JSONDecodeError, TypeError): return cors_response( request, JsonResponse( { "code": "validation", "message": "Malformed request data. Make sure you're sending valid JSON.", }, status=400, ), ) team = get_team_from_token(request, data_from_request) if team: response["featureFlags"] = feature_flags(request, team, data_from_request["data"]) if team.session_recording_opt_in and (on_permitted_domain( team, request) or len(team.app_urls) == 0): response["sessionRecording"] = {"endpoint": "/s"} return cors_response(request, JsonResponse(response))
def get_event(request): timer = statsd.Timer("%s_posthog_cloud" % (settings.STATSD_PREFIX, )) timer.start() now = timezone.now() try: data_from_request = load_data_from_request(request) data = data_from_request["data"] except TypeError: return cors_response( request, JsonResponse( { "code": "validation", "message": "Malformed request data. Make sure you're sending valid JSON.", }, status=400, ), ) if not data: return cors_response( request, JsonResponse( { "code": "validation", "message": "No data found. Make sure to use a POST request when sending the payload in the body of the request.", }, status=400, ), ) sent_at = _get_sent_at(data, request) token = _get_token(data, request) if not token: return cors_response( request, JsonResponse( { "code": "validation", "message": "API key not provided. You can find your project API key in PostHog project settings.", }, status=401, ), ) team = Team.objects.get_team_from_token(token) if team is None: try: project_id = _get_project_id(data, request) except: return cors_response( request, JsonResponse( { "code": "validation", "message": "Invalid project ID.", }, status=400, ), ) if not project_id: return cors_response( request, JsonResponse( { "code": "validation", "message": "Project API key invalid. You can find your project API key in PostHog project settings.", }, status=401, ), ) user = User.objects.get_from_personal_api_key(token) if user is None: return cors_response( request, JsonResponse( { "code": "validation", "message": "Personal API key invalid.", }, status=401, ), ) team = user.teams.get(id=project_id) if isinstance(data, dict): if data.get("batch"): # posthog-python and posthog-ruby data = data["batch"] assert data is not None elif "engage" in request.path_info: # JS identify call data["event"] = "$identify" # make sure it has an event name if isinstance(data, list): events = data else: events = [data] for event in events: try: distinct_id = _get_distinct_id(event) except KeyError: return cors_response( request, JsonResponse( { "code": "validation", "message": "You need to set user distinct ID field `distinct_id`.", "item": event, }, status=400, ), ) if not event.get("event"): return cors_response( request, JsonResponse( { "code": "validation", "message": "You need to set event name field `event`.", "item": event, }, status=400, ), ) if not event.get("properties"): event["properties"] = {} _ensure_web_feature_flags_in_properties(event, team, distinct_id) event_uuid = UUIDT() if is_ee_enabled(): log_topics = [KAFKA_EVENTS_WAL] if settings.PLUGIN_SERVER_INGESTION: log_topics.append(KAFKA_EVENTS_PLUGIN_INGESTION) statsd.Counter("%s_posthog_cloud_plugin_server_ingestion" % (settings.STATSD_PREFIX, )).increment() log_event( distinct_id=distinct_id, ip=get_ip_address(request), site_url=request.build_absolute_uri("/")[:-1], data=event, team_id=team.id, now=now, sent_at=sent_at, event_uuid=event_uuid, topics=log_topics, ) # must done after logging because process_event_ee modifies the event, e.g. by removing $elements if not settings.PLUGIN_SERVER_INGESTION: process_event_ee( distinct_id=distinct_id, ip=get_ip_address(request), site_url=request.build_absolute_uri("/")[:-1], data=event, team_id=team.id, now=now, sent_at=sent_at, event_uuid=event_uuid, ) else: task_name = "posthog.tasks.process_event.process_event" if settings.PLUGIN_SERVER_INGESTION or team.plugins_opt_in: task_name += "_with_plugins" celery_queue = settings.PLUGINS_CELERY_QUEUE else: celery_queue = settings.CELERY_DEFAULT_QUEUE celery_app.send_task( name=task_name, queue=celery_queue, args=[ distinct_id, get_ip_address(request), request.build_absolute_uri("/")[:-1], event, team.id, now.isoformat(), sent_at, ], ) timer.stop("event_endpoint") return cors_response(request, JsonResponse({"status": 1}))
def get_event(request): timer = statsd.Timer("%s_posthog_cloud" % (settings.STATSD_PREFIX,)) timer.start() now = timezone.now() try: data = load_data_from_request(request) except RequestParsingError as error: capture_exception(error) # We still capture this on Sentry to identify actual potential bugs return cors_response( request, generate_exception_response(f"Malformed request data: {error}", code="invalid_payload"), ) if not data: return cors_response( request, generate_exception_response( "No data found. Make sure to use a POST request when sending the payload in the body of the request.", code="no_data", ), ) sent_at = _get_sent_at(data, request) token = _get_token(data, request) if not token: return cors_response( request, generate_exception_response( "API key not provided. You can find your project API key in PostHog project settings.", type="authentication_error", code="missing_api_key", status_code=status.HTTP_401_UNAUTHORIZED, ), ) team = Team.objects.get_team_from_token(token) if team is None: try: project_id = _get_project_id(data, request) except ValueError: return cors_response( request, generate_exception_response("Invalid Project ID.", code="invalid_project", attr="project_id"), ) if not project_id: return cors_response( request, generate_exception_response( "Project API key invalid. You can find your project API key in PostHog project settings.", type="authentication_error", code="invalid_api_key", status_code=status.HTTP_401_UNAUTHORIZED, ), ) user = User.objects.get_from_personal_api_key(token) if user is None: return cors_response( request, generate_exception_response( "Invalid Personal API key.", type="authentication_error", code="invalid_personal_api_key", status_code=status.HTTP_401_UNAUTHORIZED, ), ) team = user.teams.get(id=project_id) if isinstance(data, dict): if data.get("batch"): # posthog-python and posthog-ruby data = data["batch"] assert data is not None elif "engage" in request.path_info: # JS identify call data["event"] = "$identify" # make sure it has an event name if isinstance(data, list): events = data else: events = [data] try: events = preprocess_session_recording_events(events) except ValueError as e: return cors_response(request, generate_exception_response(f"Invalid payload: {e}", code="invalid_payload")) for event in events: try: distinct_id = _get_distinct_id(event) except KeyError: return cors_response( request, generate_exception_response( "You need to set user distinct ID field `distinct_id`.", code="required", attr="distinct_id" ), ) if not event.get("event"): return cors_response( request, generate_exception_response( "You need to set user event name, field `event`.", code="required", attr="event" ), ) if not event.get("properties"): event["properties"] = {} _ensure_web_feature_flags_in_properties(event, team, distinct_id) event_uuid = UUIDT() ip = None if team.anonymize_ips else get_ip_address(request) if is_ee_enabled(): log_topics = [KAFKA_EVENTS_WAL] if settings.PLUGIN_SERVER_INGESTION: log_topics.append(KAFKA_EVENTS_PLUGIN_INGESTION) statsd.Counter("%s_posthog_cloud_plugin_server_ingestion" % (settings.STATSD_PREFIX,)).increment() log_event( distinct_id=distinct_id, ip=ip, site_url=request.build_absolute_uri("/")[:-1], data=event, team_id=team.id, now=now, sent_at=sent_at, event_uuid=event_uuid, topics=log_topics, ) # must done after logging because process_event_ee modifies the event, e.g. by removing $elements if not settings.PLUGIN_SERVER_INGESTION: process_event_ee( distinct_id=distinct_id, ip=ip, site_url=request.build_absolute_uri("/")[:-1], data=event, team_id=team.id, now=now, sent_at=sent_at, event_uuid=event_uuid, ) else: task_name = "posthog.tasks.process_event.process_event_with_plugins" celery_queue = settings.PLUGINS_CELERY_QUEUE celery_app.send_task( name=task_name, queue=celery_queue, args=[distinct_id, ip, request.build_absolute_uri("/")[:-1], event, team.id, now.isoformat(), sent_at,], ) timer.stop("event_endpoint") return cors_response(request, JsonResponse({"status": 1}))
def _load_data(request) -> Optional[Union[Dict[str, Any], List]]: # JS Integration reloadFeatureFlags call if request.content_type == "application/x-www-form-urlencoded": return base64_to_json(request.POST["data"]) return load_data_from_request(request)
def get_decide(request: HttpRequest): response = { "config": { "enable_collect_everything": True }, "editorParams": {}, "isAuthenticated": False, "supportedCompression": ["gzip", "gzip-js", "lz64"], } if request.COOKIES.get(settings.TOOLBAR_COOKIE_NAME): response["isAuthenticated"] = True if settings.JS_URL: response["editorParams"] = { "jsURL": settings.JS_URL, "toolbarVersion": "toolbar" } if request.user.is_authenticated: r, update_user_token = decide_editor_params(request) response.update(r) if update_user_token: request.user.temporary_token = secrets.token_urlsafe(32) request.user.save() response["featureFlags"] = [] response["sessionRecording"] = False if request.method == "POST": try: data = load_data_from_request(request) except RequestParsingError as error: capture_exception( error ) # We still capture this on Sentry to identify actual potential bugs return cors_response( request, generate_exception_response(f"Malformed request data: {error}", code="malformed_data"), ) token = _get_token(data, request) team = Team.objects.get_team_from_token(token) if team is None and token: project_id = _get_project_id(data, request) if not project_id: return cors_response( request, generate_exception_response( "Project API key invalid. You can find your project API key in PostHog project settings.", code="invalid_api_key", type="authentication_error", status_code=status.HTTP_401_UNAUTHORIZED, ), ) user = User.objects.get_from_personal_api_key(token) if user is None: return cors_response( request, generate_exception_response( "Invalid Personal API key.", code="invalid_personal_key", type="authentication_error", status_code=status.HTTP_401_UNAUTHORIZED, ), ) team = user.teams.get(id=project_id) if team: response["featureFlags"] = get_active_feature_flags( team, data["distinct_id"]) if team.session_recording_opt_in and (on_permitted_domain( team, request) or len(team.app_urls) == 0): response["sessionRecording"] = {"endpoint": "/s/"} return cors_response(request, JsonResponse(response))
def get_event(request): timer = statsd.timer("posthog_cloud_event_endpoint").start() now = timezone.now() try: data = load_data_from_request(request) except RequestParsingError as error: capture_exception( error ) # We still capture this on Sentry to identify actual potential bugs return cors_response( request, generate_exception_response("capture", f"Malformed request data: {error}", code="invalid_payload"), ) if not data: return cors_response( request, generate_exception_response( "capture", "No data found. Make sure to use a POST request when sending the payload in the body of the request.", code="no_data", ), ) sent_at = _get_sent_at(data, request) token = _get_token(data, request) if not token: return cors_response( request, generate_exception_response( "capture", "API key not provided. You can find your project API key in PostHog project settings.", type="authentication_error", code="missing_api_key", status_code=status.HTTP_401_UNAUTHORIZED, ), ) token, is_test_environment = _clean_token(token) assert token is not None team = Team.objects.get_team_from_token(token) if team is None: try: project_id = _get_project_id(data, request) except ValueError: return cors_response( request, generate_exception_response("capture", "Invalid Project ID.", code="invalid_project", attr="project_id"), ) if not project_id: return cors_response( request, generate_exception_response( "capture", "Project API key invalid. You can find your project API key in PostHog project settings.", type="authentication_error", code="invalid_api_key", status_code=status.HTTP_401_UNAUTHORIZED, ), ) user = User.objects.get_from_personal_api_key(token) if user is None: return cors_response( request, generate_exception_response( "capture", "Invalid Personal API key.", type="authentication_error", code="invalid_personal_api_key", status_code=status.HTTP_401_UNAUTHORIZED, ), ) team = user.teams.get(id=project_id) if isinstance(data, dict): if data.get("batch"): # posthog-python and posthog-ruby data = data["batch"] assert data is not None elif "engage" in request.path_info: # JS identify call data["event"] = "$identify" # make sure it has an event name if isinstance(data, list): events = data else: events = [data] try: events = preprocess_session_recording_events(events) except ValueError as e: return cors_response( request, generate_exception_response("capture", f"Invalid payload: {e}", code="invalid_payload")) for event in events: try: distinct_id = _get_distinct_id(event) except KeyError: return cors_response( request, generate_exception_response( "capture", "You need to set user distinct ID field `distinct_id`.", code="required", attr="distinct_id", ), ) except ValueError: return cors_response( request, generate_exception_response( "capture", "Distinct ID field `distinct_id` must have a non-empty value.", code="required", attr="distinct_id", ), ) if not event.get("event"): return cors_response( request, generate_exception_response( "capture", "You need to set user event name, field `event`.", code="required", attr="event"), ) site_url = request.build_absolute_uri("/")[:-1] ip = None if team.anonymize_ips else get_ip_address(request) if not event.get("properties"): event["properties"] = {} # Support test_[apiKey] for users with multiple environments if event["properties"].get( "$environment") is None and is_test_environment: event["properties"]["$environment"] = ENVIRONMENT_TEST _ensure_web_feature_flags_in_properties(event, team, distinct_id) statsd.incr("posthog_cloud_plugin_server_ingestion") capture_internal(event, distinct_id, ip, site_url, now, sent_at, team.pk) timer.stop() statsd.incr(f"posthog_cloud_raw_endpoint_success", tags={ "endpoint": "capture", }) return cors_response(request, JsonResponse({"status": 1}))
def get_event(request): now = timezone.now() try: data_from_request = load_data_from_request(request) data = data_from_request["data"] except TypeError: return cors_response( request, JsonResponse( { "code": "validation", "message": "Malformed request data. Make sure you're sending valid JSON.", }, status=400, ), ) if not data: return cors_response( request, JsonResponse( { "code": "validation", "message": "No data found. Make sure to use a POST request when sending the payload in the body of the request.", }, status=400, ), ) sent_at = _get_sent_at(data, request) token = _get_token(data, request) is_personal_api_key = False if not token: token = PersonalAPIKeyAuthentication.find_key( request, data_from_request["body"], data if isinstance(data, dict) else None) is_personal_api_key = True if not token: return cors_response( request, JsonResponse( { "code": "validation", "message": "Neither api_key nor personal_api_key set. You can find your project API key in PostHog project settings.", }, status=400, ), ) team = Team.objects.get_team_from_token(token, is_personal_api_key) if team is None: return cors_response( request, JsonResponse( { "code": "validation", "message": "Project or personal API key invalid. You can find your project API key in PostHog project settings.", }, status=400, ), ) if isinstance(data, dict): if data.get("batch"): # posthog-python and posthog-ruby data = data["batch"] assert data is not None elif "engage" in request.path_info: # JS identify call data["event"] = "$identify" # make sure it has an event name if isinstance(data, list): events = data else: events = [data] for event in events: try: distinct_id = _get_distinct_id(event) except KeyError: return cors_response( request, JsonResponse( { "code": "validation", "message": "You need to set user distinct ID field `distinct_id`.", "item": event, }, status=400, ), ) if "event" not in event: return cors_response( request, JsonResponse( { "code": "validation", "message": "You need to set event name field `event`.", "item": event, }, status=400, ), ) if check_ee_enabled(): process_event_ee.delay( distinct_id=distinct_id, ip=get_ip_address(request), site_url=request.build_absolute_uri("/")[:-1], data=event, team_id=team.id, now=now, sent_at=sent_at, ) # log the event to kafka write ahead log for processing log_event( distinct_id=distinct_id, ip=get_ip_address(request), site_url=request.build_absolute_uri("/")[:-1], data=event, team_id=team.id, now=now, sent_at=sent_at, ) else: process_event.delay( distinct_id=distinct_id, ip=get_ip_address(request), site_url=request.build_absolute_uri("/")[:-1], data=event, team_id=team.id, now=now, sent_at=sent_at, ) return cors_response(request, JsonResponse({"status": 1}))
def get_decide(request: HttpRequest): response = { "config": { "enable_collect_everything": True }, "editorParams": {}, "isAuthenticated": False, "supportedCompression": ["gzip", "gzip-js", "lz64"], } if request.COOKIES.get( settings.TOOLBAR_COOKIE_NAME) and request.user.is_authenticated: response["isAuthenticated"] = True if settings.JS_URL and request.user.toolbar_mode == User.TOOLBAR: response["editorParams"] = { "jsURL": settings.JS_URL, "toolbarVersion": "toolbar" } if request.user.is_authenticated: r, update_user_token = decide_editor_params(request) response.update(r) if update_user_token: request.user.temporary_token = secrets.token_urlsafe(32) request.user.save() response["featureFlags"] = [] response["sessionRecording"] = False if request.method == "POST": try: data = load_data_from_request(request) api_version_string = request.GET.get("v") # NOTE: This does not support semantic versioning e.g. 2.1.0 api_version = int(api_version_string) if api_version_string else 1 except ValueError: # default value added because of bug in posthog-js 1.19.0 # see https://sentry.io/organizations/posthog2/issues/2738865125/?project=1899813 # as a tombstone if the below statsd counter hasn't seen errors for N days # then it is likely that no clients are running posthog-js 1.19.0 # and this defaulting could be removed statsd.incr( f"posthog_cloud_decide_defaulted_api_version_on_value_error", tags={ "endpoint": "decide", "api_version_string": api_version_string }, ) api_version = 2 except RequestParsingError as error: capture_exception( error ) # We still capture this on Sentry to identify actual potential bugs return cors_response( request, generate_exception_response("decide", f"Malformed request data: {error}", code="malformed_data"), ) token = get_token(data, request) team = Team.objects.get_team_from_token(token) if team is None and token: project_id = get_project_id(data, request) if not project_id: return cors_response( request, generate_exception_response( "decide", "Project API key invalid. You can find your project API key in PostHog project settings.", code="invalid_api_key", type="authentication_error", status_code=status.HTTP_401_UNAUTHORIZED, ), ) user = User.objects.get_from_personal_api_key(token) if user is None: return cors_response( request, generate_exception_response( "decide", "Invalid Personal API key.", code="invalid_personal_key", type="authentication_error", status_code=status.HTTP_401_UNAUTHORIZED, ), ) team = user.teams.get(id=project_id) if team: feature_flags = get_overridden_feature_flags( team.pk, data["distinct_id"], data.get("groups", {})) response[ "featureFlags"] = feature_flags if api_version >= 2 else list( feature_flags.keys()) if team.session_recording_opt_in and (on_permitted_domain( team, request) or len(team.app_urls) == 0): response["sessionRecording"] = {"endpoint": "/s/"} statsd.incr( f"posthog_cloud_raw_endpoint_success", tags={ "endpoint": "decide", }, ) return cors_response(request, JsonResponse(response))
def get_event(request): timer = statsd.Timer("%s_posthog_cloud" % (settings.STATSD_PREFIX,)) timer.start() now = timezone.now() try: data_from_request = load_data_from_request(request) data = data_from_request["data"] except TypeError: return cors_response( request, JsonResponse( {"code": "validation", "message": "Malformed request data. Make sure you're sending valid JSON.",}, status=400, ), ) if not data: return cors_response( request, JsonResponse( { "code": "validation", "message": "No data found. Make sure to use a POST request when sending the payload in the body of the request.", }, status=400, ), ) sent_at = _get_sent_at(data, request) token = _get_token(data, request) if not token: return cors_response( request, JsonResponse( { "code": "validation", "message": "API key not provided. You can find your project API key in PostHog project settings.", }, status=400, ), ) team = Team.objects.get_team_from_token(token) if team is None: try: project_id = _get_project_id(data, request) except: return cors_response( request, JsonResponse({"code": "validation", "message": "Invalid project ID.",}, status=400,), ) if not project_id: return cors_response( request, JsonResponse( { "code": "validation", "message": "Project API key invalid. You can find your project API key in PostHog project settings.", }, status=400, ), ) user = User.objects.get_from_personal_api_key(token) if user is None: return cors_response( request, JsonResponse({"code": "validation", "message": "Personal API key invalid.",}, status=400,), ) team = user.teams.get(id=project_id) if isinstance(data, dict): if data.get("batch"): # posthog-python and posthog-ruby data = data["batch"] assert data is not None elif "engage" in request.path_info: # JS identify call data["event"] = "$identify" # make sure it has an event name if isinstance(data, list): events = data else: events = [data] for event in events: try: distinct_id = _get_distinct_id(event) except KeyError: return cors_response( request, JsonResponse( { "code": "validation", "message": "You need to set user distinct ID field `distinct_id`.", "item": event, }, status=400, ), ) if "event" not in event: return cors_response( request, JsonResponse( {"code": "validation", "message": "You need to set event name field `event`.", "item": event,}, status=400, ), ) if is_ee_enabled(): process_event_ee( distinct_id=distinct_id, ip=get_ip_address(request), site_url=request.build_absolute_uri("/")[:-1], data=event, team_id=team.id, now=now, sent_at=sent_at, ) else: task_name = "posthog.tasks.process_event.process_event" celery_queue = settings.CELERY_DEFAULT_QUEUE if team.plugins_opt_in: task_name += "_with_plugins" celery_queue = settings.PLUGINS_CELERY_QUEUE celery_app.send_task( name=task_name, queue=celery_queue, args=[ distinct_id, get_ip_address(request), request.build_absolute_uri("/")[:-1], event, team.id, now.isoformat(), sent_at, ], ) if is_ee_enabled() and settings.LOG_TO_WAL: # log the event to kafka write ahead log for processing log_event( distinct_id=distinct_id, ip=get_ip_address(request), site_url=request.build_absolute_uri("/")[:-1], data=event, team_id=team.id, now=now, sent_at=sent_at, ) timer.stop("event_endpoint") return cors_response(request, JsonResponse({"status": 1}))
def get_decide(request: HttpRequest): response = { "config": { "enable_collect_everything": True }, "editorParams": {}, "isAuthenticated": False, "supportedCompression": ["gzip", "gzip-js", "lz64"], } if request.COOKIES.get(settings.TOOLBAR_COOKIE_NAME): response["isAuthenticated"] = True if settings.JS_URL: response["editorParams"] = { "jsURL": settings.JS_URL, "toolbarVersion": "toolbar" } if request.user.is_authenticated: r, update_user_token = decide_editor_params(request) response.update(r) if update_user_token: request.user.temporary_token = secrets.token_urlsafe(32) request.user.save() response["featureFlags"] = [] response["sessionRecording"] = False if request.method == "POST": try: data_from_request = load_data_from_request(request) data = data_from_request["data"] except (json.decoder.JSONDecodeError, TypeError): return cors_response( request, JsonResponse( { "code": "validation", "message": "Malformed request data. Make sure you're sending valid JSON.", }, status=400, ), ) token = _get_token(data, request) team = Team.objects.get_team_from_token(token) if team is None and token: project_id = _get_project_id(data, request) if not project_id: return cors_response( request, JsonResponse( { "code": "validation", "message": "Project API key invalid. You can find your project API key in PostHog project settings.", }, status=401, ), ) user = User.objects.get_from_personal_api_key(token) if user is None: return cors_response( request, JsonResponse( { "code": "validation", "message": "Personal API key invalid.", }, status=401, ), ) team = user.teams.get(id=project_id) if team: response["featureFlags"] = get_active_feature_flags( team, data_from_request["data"]["distinct_id"]) if team.session_recording_opt_in and (on_permitted_domain( team, request) or len(team.app_urls) == 0): response["sessionRecording"] = {"endpoint": "/s/"} return cors_response(request, JsonResponse(response))