def test_person_flags_with_overrides(self): flags = get_overridden_feature_flags(self.team.pk, "distinct_id") self.assertEqual(flags, { "feature-all": True, "feature-posthog": True, "feature-disabled": True })
def _ensure_web_feature_flags_in_properties( event: Dict[str, Any], ingestion_context: EventIngestionContext, distinct_id: str ): """If the event comes from web, ensure that it contains property $active_feature_flags.""" if event["properties"].get("$lib") == "web" and "$active_feature_flags" not in event["properties"]: flags = get_overridden_feature_flags(team_id=ingestion_context.team_id, distinct_id=distinct_id) event["properties"]["$active_feature_flags"] = list(flags.keys()) for k, v in flags.items(): event["properties"][f"$feature/{k}"] = v
def test_group_flags_with_overrides(self): flags = get_overridden_feature_flags(self.team.pk, "distinct_id", {"organization": "PostHog"}) self.assertEqual( flags, { "feature-all": True, "feature-posthog": True, "feature-disabled": True, "feature-groups": True, "feature-groups-all": True, }, )
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))