Esempio n. 1
0
 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
     })
Esempio n. 2
0
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
Esempio n. 3
0
 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,
         },
     )
Esempio n. 4
0
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))