Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Updated remote config to include domain restrictions #26875

Merged
merged 21 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 2 additions & 21 deletions posthog/api/decide.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
from posthog.api.utils import (
get_project_id,
get_token,
hostname_in_allowed_url_list,
parse_domain,
on_permitted_recording_domain,
)
from posthog.database_healthcheck import DATABASE_FOR_FLAG_MATCHING
from posthog.exceptions import (
Expand Down Expand Up @@ -47,24 +46,6 @@
)


def on_permitted_recording_domain(team: Team, request: HttpRequest) -> bool:
origin = parse_domain(request.headers.get("Origin"))
referer = parse_domain(request.headers.get("Referer"))
user_agent = request.META.get("HTTP_USER_AGENT")

is_authorized_web_client: bool = hostname_in_allowed_url_list(
team.recording_domains, origin
) or hostname_in_allowed_url_list(team.recording_domains, referer)
# TODO this is a short term fix for beta testers
# TODO we will match on the app identifier in the origin instead and allow users to auth those
is_authorized_mobile_client: bool = user_agent is not None and any(
keyword in user_agent
for keyword in ["posthog-android", "posthog-ios", "posthog-react-native", "posthog-flutter"]
)

return is_authorized_web_client or is_authorized_mobile_client


def get_base_config(token: str, team: Team, request: HttpRequest, skip_db: bool = False) -> dict:
# Check for query param "use_remote_config"
use_remote_config = request.GET.get("use_remote_config") == "true" or token in (
Expand Down Expand Up @@ -361,7 +342,7 @@ def get_decide(request: HttpRequest):


def _session_recording_domain_not_allowed(team: Team, request: HttpRequest) -> bool:
return team.recording_domains and not on_permitted_recording_domain(team, request)
return team.recording_domains and not on_permitted_recording_domain(team.recording_domains, request)


def _session_recording_config_response(request: HttpRequest, team: Team) -> bool | dict:
Expand Down
20 changes: 14 additions & 6 deletions posthog/api/remote_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
from posthog.models.remote_config import RemoteConfig


def add_vary_headers(response):
"""
Add Vary headers for Origin and Referer to responses.
"""
response["Vary"] = "Origin, Referer"
return response


class BaseRemoteConfigAPIView(APIView):
"""
Base class for RemoteConfig API views.
Expand All @@ -23,28 +31,28 @@ def check_token(self, token: str):
class RemoteConfigAPIView(BaseRemoteConfigAPIView):
def get(self, request, token: str, *args, **kwargs):
try:
resource = RemoteConfig.get_config_via_token(self.check_token(token))
resource = RemoteConfig.get_config_via_token(self.check_token(token), request=request)
except RemoteConfig.DoesNotExist:
raise Http404()

return JsonResponse(resource)
return add_vary_headers(JsonResponse(resource))


class RemoteConfigJSAPIView(BaseRemoteConfigAPIView):
def get(self, request, token: str, *args, **kwargs):
try:
script_content = RemoteConfig.get_config_js_via_token(self.check_token(token))
script_content = RemoteConfig.get_config_js_via_token(self.check_token(token), request=request)
except RemoteConfig.DoesNotExist:
raise Http404()

return HttpResponse(script_content, content_type="application/javascript")
return add_vary_headers(HttpResponse(script_content, content_type="application/javascript"))


class RemoteConfigArrayJSAPIView(BaseRemoteConfigAPIView):
def get(self, request, token: str, *args, **kwargs):
try:
script_content = RemoteConfig.get_array_js_via_token(self.check_token(token))
script_content = RemoteConfig.get_array_js_via_token(self.check_token(token), request=request)
except RemoteConfig.DoesNotExist:
raise Http404()

return HttpResponse(script_content, content_type="application/javascript")
return add_vary_headers(HttpResponse(script_content, content_type="application/javascript"))
Loading
Loading