From e3db08a2cb70901dd8a488b9f72bf92e1750e4e9 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Fri, 12 Jul 2024 22:41:37 +0200 Subject: [PATCH 01/32] Refactor away legacy "Clickhouse" viewset prefix --- ee/clickhouse/views/experiments.py | 2 +- ee/clickhouse/views/groups.py | 4 ++-- ee/clickhouse/views/insights.py | 2 +- posthog/api/__init__.py | 24 +++++++++--------------- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/ee/clickhouse/views/experiments.py b/ee/clickhouse/views/experiments.py index ffdbfcc16e428..7aed519d29ee6 100644 --- a/ee/clickhouse/views/experiments.py +++ b/ee/clickhouse/views/experiments.py @@ -333,7 +333,7 @@ def update(self, instance: Experiment, validated_data: dict, *args: Any, **kwarg return super().update(instance, validated_data) -class ClickhouseExperimentsViewSet(TeamAndOrgViewSetMixin, viewsets.ModelViewSet): +class EnterpriseExperimentsViewSet(TeamAndOrgViewSetMixin, viewsets.ModelViewSet): scope_object = "experiment" serializer_class = ExperimentSerializer queryset = Experiment.objects.prefetch_related("feature_flag", "created_by").all() diff --git a/ee/clickhouse/views/groups.py b/ee/clickhouse/views/groups.py index 3c20275b2de7b..bfbb375e70990 100644 --- a/ee/clickhouse/views/groups.py +++ b/ee/clickhouse/views/groups.py @@ -25,7 +25,7 @@ class Meta: read_only_fields = ["group_type", "group_type_index"] -class ClickhouseGroupsTypesView(TeamAndOrgViewSetMixin, mixins.ListModelMixin, viewsets.GenericViewSet): +class GroupsTypesViewSet(TeamAndOrgViewSetMixin, mixins.ListModelMixin, viewsets.GenericViewSet): scope_object = "group" serializer_class = GroupTypeSerializer queryset = GroupTypeMapping.objects.all().order_by("group_type_index") @@ -54,7 +54,7 @@ class Meta: fields = ["group_type_index", "group_key", "group_properties", "created_at"] -class ClickhouseGroupsView(TeamAndOrgViewSetMixin, mixins.ListModelMixin, viewsets.GenericViewSet): +class GroupsViewSet(TeamAndOrgViewSetMixin, mixins.ListModelMixin, viewsets.GenericViewSet): scope_object = "group" serializer_class = GroupSerializer queryset = Group.objects.all() diff --git a/ee/clickhouse/views/insights.py b/ee/clickhouse/views/insights.py index 6072ab2957bb1..933928428ab50 100644 --- a/ee/clickhouse/views/insights.py +++ b/ee/clickhouse/views/insights.py @@ -26,7 +26,7 @@ def has_object_permission(self, request: Request, view, insight: Insight) -> boo return view.user_permissions.insight(insight).effective_privilege_level == Dashboard.PrivilegeLevel.CAN_EDIT -class ClickhouseInsightsViewSet(InsightViewSet): +class EnterpriseInsightsViewSet(InsightViewSet): permission_classes = [CanEditInsight] retention_query_class = ClickhouseRetention stickiness_query_class = ClickhouseStickiness diff --git a/posthog/api/__init__.py b/posthog/api/__init__.py index c6fd6851da9c7..65ba4be315c3d 100644 --- a/posthog/api/__init__.py +++ b/posthog/api/__init__.py @@ -359,22 +359,16 @@ def api_not_found(request): projects_router.register(r"sessions", SessionViewSet, "environment_sessions", ["team_id"]) if EE_AVAILABLE: - from ee.clickhouse.views.experiments import ClickhouseExperimentsViewSet - from ee.clickhouse.views.groups import ( - ClickhouseGroupsTypesView, - ClickhouseGroupsView, - ) - from ee.clickhouse.views.insights import ClickhouseInsightsViewSet - from ee.clickhouse.views.person import ( - EnterprisePersonViewSet, - LegacyEnterprisePersonViewSet, - ) - - projects_router.register(r"experiments", ClickhouseExperimentsViewSet, "project_experiments", ["project_id"]) - projects_router.register(r"groups", ClickhouseGroupsView, "environment_groups", ["team_id"]) - projects_router.register(r"groups_types", ClickhouseGroupsTypesView, "project_groups_types", ["project_id"]) + from ee.clickhouse.views.experiments import EnterpriseExperimentsViewSet + from ee.clickhouse.views.groups import GroupsTypesViewSet, GroupsViewSet + from ee.clickhouse.views.insights import EnterpriseInsightsViewSet + from ee.clickhouse.views.person import EnterprisePersonViewSet, LegacyEnterprisePersonViewSet + + projects_router.register(r"experiments", EnterpriseExperimentsViewSet, "project_experiments", ["project_id"]) + projects_router.register(r"groups", GroupsViewSet, "environment_groups", ["team_id"]) + projects_router.register(r"groups_types", GroupsTypesViewSet, "project_groups_types", ["project_id"]) project_insights_router = projects_router.register( - r"insights", ClickhouseInsightsViewSet, "project_insights", ["project_id"] + r"insights", EnterpriseInsightsViewSet, "project_insights", ["project_id"] ) projects_router.register(r"persons", EnterprisePersonViewSet, "environment_persons", ["team_id"]) router.register(r"person", LegacyEnterprisePersonViewSet, basename="person") From 453b02d955859570fc3a8b354bffe827ff9370fd Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Fri, 12 Jul 2024 22:42:23 +0200 Subject: [PATCH 02/32] Disambiguate API endpoints basenames --- posthog/api/__init__.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/posthog/api/__init__.py b/posthog/api/__init__.py index 65ba4be315c3d..09d4187d570fa 100644 --- a/posthog/api/__init__.py +++ b/posthog/api/__init__.py @@ -252,7 +252,7 @@ def api_not_found(request): # Organizations nested endpoints organizations_router = router.register(r"organizations", organization.OrganizationViewSet, "organizations") -organizations_router.register(r"projects", team.TeamViewSet, "projects", ["organization_id"]) +organizations_router.register(r"projects", team.TeamViewSet, "organization_projects", ["organization_id"]) organizations_router.register( r"batch_exports", batch_exports.BatchExportOrganizationViewSet, "batch_exports", ["organization_id"] ) @@ -316,10 +316,10 @@ def api_not_found(request): # General endpoints (shared across CH & PG) router.register(r"login", authentication.LoginViewSet, "login") -router.register(r"login/token", authentication.TwoFactorViewSet) -router.register(r"login/precheck", authentication.LoginPrecheckViewSet) +router.register(r"login/token", authentication.TwoFactorViewSet, "login_token") +router.register(r"login/precheck", authentication.LoginPrecheckViewSet, "login_precheck") router.register(r"reset", authentication.PasswordResetViewSet, "password_reset") -router.register(r"users", user.UserViewSet) +router.register(r"users", user.UserViewSet, "users") router.register(r"personal_api_keys", personal_api_key.PersonalAPIKeyViewSet, "personal_api_keys") router.register(r"instance_status", instance_status.InstanceStatusViewSet, "instance_status") router.register(r"dead_letter_queue", dead_letter_queue.DeadLetterQueueViewSet, "dead_letter_queue") @@ -347,7 +347,6 @@ def api_not_found(request): projects_router.register(r"events", EventViewSet, "environment_events", ["team_id"]) projects_router.register(r"actions", ActionViewSet, "project_actions", ["project_id"]) projects_router.register(r"cohorts", CohortViewSet, "project_cohorts", ["project_id"]) -projects_router.register(r"persons", PersonViewSet, "environment_persons", ["team_id"]) projects_router.register(r"elements", ElementViewSet, "environment_elements", ["team_id"]) # TODO: Can be removed? project_session_recordings_router = projects_router.register( r"session_recordings", @@ -371,11 +370,11 @@ def api_not_found(request): r"insights", EnterpriseInsightsViewSet, "project_insights", ["project_id"] ) projects_router.register(r"persons", EnterprisePersonViewSet, "environment_persons", ["team_id"]) - router.register(r"person", LegacyEnterprisePersonViewSet, basename="person") + router.register(r"person", LegacyEnterprisePersonViewSet, "persons") else: project_insights_router = projects_router.register(r"insights", InsightViewSet, "project_insights", ["project_id"]) projects_router.register(r"persons", PersonViewSet, "environment_persons", ["team_id"]) - router.register(r"person", LegacyPersonViewSet, basename="person") + router.register(r"person", LegacyPersonViewSet, "persons") project_dashboards_router.register( From 7291d9806f15bcfbe6c7eea4935ec848b5f792e6 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Fri, 12 Jul 2024 22:42:47 +0200 Subject: [PATCH 03/32] Remove router `_register` override hack --- posthog/api/routing.py | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/posthog/api/routing.py b/posthog/api/routing.py index d2f902e30b5b4..b357ccf9ffa89 100644 --- a/posthog/api/routing.py +++ b/posthog/api/routing.py @@ -38,32 +38,6 @@ class DefaultRouterPlusPlus(ExtendedDefaultRouter): """DefaultRouter with optional trailing slash and drf-extensions nesting.""" - # This is an override because of changes in djangorestframework 3.15, which is required for python 3.11 - # changes taken from and explained here: https://github.com/nautobot/nautobot/pull/5546/files#diff-81850a2ccad5814aab4f477d447f85cc0a82e9c10fd88fd72327cda51a750471R30 - def _register(self, prefix, viewset, basename=None): - """ - Override DRF's BaseRouter.register() to bypass an unnecessary restriction added in version 3.15.0. - (Reference: https://github.com/encode/django-rest-framework/pull/8438) - """ - if basename is None: - basename = self.get_default_basename(viewset) - - # DRF: - # if self.is_already_registered(basename): - # msg = (f'Router with basename "{basename}" is already registered. ' - # f'Please provide a unique basename for viewset "{viewset}"') - # raise ImproperlyConfigured(msg) - # - # We bypass this because we have at least one use case (/api/extras/jobs/) where we are *intentionally* - # registering two viewsets with the same basename, but have carefully defined them so as not to conflict. - - # resuming standard DRF code... - self.registry.append((prefix, viewset, basename)) - - # invalidate the urls cache - if hasattr(self, "_urls"): - del self._urls - def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.trailing_slash = r"/?" From 64719f88b332083f72250711ba80c12758633b46 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Mon, 15 Jul 2024 12:08:18 +0200 Subject: [PATCH 04/32] Add `register_grandfathered_environment_nested_viewset` --- ee/urls.py | 26 ++++---- frontend/src/types.ts | 7 ++ posthog/api/__init__.py | 132 +++++++++++++++++++++++++++----------- posthog/api/project.py | 0 posthog/models/project.py | 4 +- posthog/urls.py | 12 +--- posthog/utils.py | 2 + 7 files changed, 119 insertions(+), 64 deletions(-) create mode 100644 posthog/api/project.py diff --git a/ee/urls.py b/ee/urls.py index 68ede5f20126c..633766add1439 100644 --- a/ee/urls.py +++ b/ee/urls.py @@ -4,10 +4,8 @@ from django.contrib import admin from django.urls import include from django.urls.conf import path -from rest_framework_extensions.routers import NestedRegistryItem from ee.api import integration -from posthog.api.routing import DefaultRouterPlusPlus from .api import ( authentication, @@ -25,14 +23,16 @@ from .session_recordings import session_recording_playlist -def extend_api_router( - root_router: DefaultRouterPlusPlus, - *, - projects_router: NestedRegistryItem, - organizations_router: NestedRegistryItem, - project_dashboards_router: NestedRegistryItem, - project_feature_flags_router: NestedRegistryItem, -) -> None: +def extend_api_router() -> None: + from posthog.api import ( + router as root_router, + register_grandfathered_environment_nested_viewset, + projects_router, + organizations_router, + project_feature_flags_router, + project_dashboards_router, + ) + root_router.register(r"billing", billing.BillingViewset, "billing") root_router.register(r"license", license.LicenseViewSet) root_router.register(r"integrations", integration.PublicIntegrationViewSet) @@ -60,8 +60,8 @@ def extend_api_router( "organization_resource_access", ["organization_id"], ) - projects_router.register(r"hooks", hooks.HookViewSet, "environment_hooks", ["team_id"]) - projects_router.register( + register_grandfathered_environment_nested_viewset(r"hooks", hooks.HookViewSet, "environment_hooks", ["team_id"]) + register_grandfathered_environment_nested_viewset( r"explicit_members", explicit_team_member.ExplicitTeamMemberViewSet, "environment_explicit_members", @@ -74,7 +74,7 @@ def extend_api_router( ["project_id", "dashboard_id"], ) - projects_router.register( + register_grandfathered_environment_nested_viewset( r"subscriptions", subscription.SubscriptionViewSet, "environment_subscriptions", ["team_id"] ) projects_router.register( diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 0e32117d3688e..d9e13888e4f96 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -466,6 +466,12 @@ export interface SessionRecordingAIConfig { important_user_properties: string[] } +export interface ProjectType { + id: number + name: string + organization_id: number + created_at: string +} export interface TeamType extends TeamBasicType { created_at: string updated_at: string @@ -3268,6 +3274,7 @@ export type EventOrPropType = EventDefinition & PropertyDefinition export interface AppContext { current_user: UserType | null + current_project: ProjectType | null current_team: TeamType | TeamPublicType | null preflight: PreflightStatus default_event_name: string diff --git a/posthog/api/__init__.py b/posthog/api/__init__.py index 09d4187d570fa..d8d13c87d8113 100644 --- a/posthog/api/__init__.py +++ b/posthog/api/__init__.py @@ -1,4 +1,6 @@ -from rest_framework import decorators, exceptions +from rest_framework import decorators, exceptions, viewsets +from rest_framework_extensions.routers import NestedRegistryItem + from posthog.api.routing import DefaultRouterPlusPlus from posthog.batch_exports import http as batch_exports @@ -82,34 +84,56 @@ def api_not_found(request): # Nested endpoints shared projects_router = router.register(r"projects", team.RootTeamViewSet, "projects") -project_plugins_configs_router = projects_router.register( +environments_router = router.register(r"environments", team.RootTeamViewSet, "environments") + + +def register_grandfathered_environment_nested_viewset( + prefix: str, viewset: viewsets.GenericViewSet, basename: str, parents_query_lookups: list[str] +) -> tuple[NestedRegistryItem, NestedRegistryItem]: + """ + Register the environment-specific viewset under both /environments/:team_id/ (correct endpoint) + and /projects/:team_id/ (legacy, but supported for backward compatibility endpoint). + DO NOT USE ON ANY NEW ENDPOINT YOU'RE ADDING! + """ + if parents_query_lookups[0] != "team_id": + raise ValueError("Only endpoints with team_id as the first parent query lookup can be environment-nested") + if not basename.startswith("environment_"): + raise ValueError("Only endpoints with a basename starting with `environment_` can be environment-nested") + environment_nested = environments_router.register(prefix, viewset, basename, parents_query_lookups) + legacy_project_nested = projects_router.register( + prefix, viewset, basename.replace("environment_", "project_"), parents_query_lookups + ) + return environment_nested, legacy_project_nested + + +register_grandfathered_environment_nested_viewset( r"plugin_configs", plugin.PluginConfigViewSet, "environment_plugin_configs", ["team_id"] ) -project_plugins_configs_router.register( +register_grandfathered_environment_nested_viewset( r"logs", plugin_log_entry.PluginLogEntryViewSet, "environment_plugin_config_logs", ["team_id", "plugin_config_id"], ) -projects_router.register( +register_grandfathered_environment_nested_viewset( r"pipeline_transformation_configs", plugin.PipelineTransformationsConfigsViewSet, "environment_pipeline_transformation_configs", ["team_id"], ) -projects_router.register( +register_grandfathered_environment_nested_viewset( r"pipeline_destination_configs", plugin.PipelineDestinationsConfigsViewSet, "environment_pipeline_destination_configs", ["team_id"], ) -projects_router.register( +register_grandfathered_environment_nested_viewset( r"pipeline_frontend_apps_configs", plugin.PipelineFrontendAppsConfigsViewSet, "environment_pipeline_frontend_apps_configs", ["team_id"], ) -projects_router.register( +register_grandfathered_environment_nested_viewset( r"pipeline_import_apps_configs", plugin.PipelineImportAppsConfigsViewSet, "environment_pipeline_import_apps_configs", @@ -147,9 +171,13 @@ def api_not_found(request): r"dashboards", dashboard.DashboardsViewSet, "project_dashboards", ["project_id"] ) -projects_router.register(r"exports", exports.ExportedAssetViewSet, "environment_exports", ["team_id"]) -projects_router.register(r"integrations", integration.IntegrationViewSet, "environment_integrations", ["team_id"]) -projects_router.register( +register_grandfathered_environment_nested_viewset( + r"exports", exports.ExportedAssetViewSet, "environment_exports", ["team_id"] +) +register_grandfathered_environment_nested_viewset( + r"integrations", integration.IntegrationViewSet, "environment_integrations", ["team_id"] +) +register_grandfathered_environment_nested_viewset( r"ingestion_warnings", ingestion_warnings.IngestionWarningsViewSet, "environment_ingestion_warnings", @@ -170,37 +198,50 @@ def api_not_found(request): ["project_id"], ) -app_metrics_router = projects_router.register( +environment_app_metrics_router, legacy_project_app_metrics_router = register_grandfathered_environment_nested_viewset( r"app_metrics", app_metrics.AppMetricsViewSet, "environment_app_metrics", ["team_id"] ) -app_metrics_router.register( +environment_app_metrics_router.register( r"historical_exports", app_metrics.HistoricalExportsAppMetricsViewSet, "environment_app_metrics_historical_exports", ["team_id", "plugin_config_id"], ) +legacy_project_app_metrics_router.register( + r"historical_exports", + app_metrics.HistoricalExportsAppMetricsViewSet, + "project_app_metrics_historical_exports", + ["team_id", "plugin_config_id"], +) -batch_exports_router = projects_router.register( - r"batch_exports", batch_exports.BatchExportViewSet, "environment_batch_exports", ["team_id"] +environment_batch_exports_router, legacy_project_batch_exports_router = ( + register_grandfathered_environment_nested_viewset( + r"batch_exports", batch_exports.BatchExportViewSet, "environment_batch_exports", ["team_id"] + ) ) -batch_export_runs_router = batch_exports_router.register( +environment_batch_exports_router.register( r"runs", batch_exports.BatchExportRunViewSet, "environment_batch_export_runs", ["team_id", "batch_export_id"] ) +legacy_project_batch_exports_router.register( + r"runs", batch_exports.BatchExportRunViewSet, "project_batch_export_runs", ["team_id", "batch_export_id"] +) -projects_router.register(r"warehouse_tables", table.TableViewSet, "environment_warehouse_tables", ["team_id"]) -projects_router.register( +register_grandfathered_environment_nested_viewset( + r"warehouse_tables", table.TableViewSet, "environment_warehouse_tables", ["team_id"] +) +register_grandfathered_environment_nested_viewset( r"warehouse_saved_queries", saved_query.DataWarehouseSavedQueryViewSet, "environment_warehouse_saved_queries", ["team_id"], ) -projects_router.register( +register_grandfathered_environment_nested_viewset( r"warehouse_view_links", view_link.ViewLinkViewSet, "environment_warehouse_view_links", ["team_id"], ) -projects_router.register( +register_grandfathered_environment_nested_viewset( r"warehouse_view_link", view_link.ViewLinkViewSet, "environment_warehouse_view_link", ["team_id"] ) @@ -220,10 +261,10 @@ def api_not_found(request): projects_router.register(r"uploaded_media", uploaded_media.MediaViewSet, "project_media", ["project_id"]) projects_router.register(r"tags", tagged_item.TaggedItemViewSet, "project_tags", ["project_id"]) -projects_router.register(r"query", query.QueryViewSet, "environment_query", ["team_id"]) +register_grandfathered_environment_nested_viewset(r"query", query.QueryViewSet, "environment_query", ["team_id"]) # External data resources -projects_router.register( +register_grandfathered_environment_nested_viewset( r"external_data_sources", external_data_source.ExternalDataSourceViewSet, "environment_external_data_sources", @@ -243,10 +284,10 @@ def api_not_found(request): ) -projects_router.register( +register_grandfathered_environment_nested_viewset( r"external_data_schemas", external_data_schema.ExternalDataSchemaViewset, - "project_external_data_schemas", + "environment_external_data_schemas", ["team_id"], ) @@ -344,18 +385,25 @@ def api_not_found(request): router.register(r"event", LegacyEventViewSet, basename="event") # Nested endpoints CH -projects_router.register(r"events", EventViewSet, "environment_events", ["team_id"]) +register_grandfathered_environment_nested_viewset(r"events", EventViewSet, "environment_events", ["team_id"]) projects_router.register(r"actions", ActionViewSet, "project_actions", ["project_id"]) projects_router.register(r"cohorts", CohortViewSet, "project_cohorts", ["project_id"]) -projects_router.register(r"elements", ElementViewSet, "environment_elements", ["team_id"]) # TODO: Can be removed? -project_session_recordings_router = projects_router.register( - r"session_recordings", - SessionRecordingViewSet, - "environment_session_recordings", - ["team_id"], +register_grandfathered_environment_nested_viewset( + r"elements", + ElementViewSet, + "environment_elements", + ["team_id"], # TODO: Can be removed? +) +environment_sessions_recordings_router, legacy_project_session_recordings_router = ( + register_grandfathered_environment_nested_viewset( + r"session_recordings", + SessionRecordingViewSet, + "environment_session_recordings", + ["team_id"], + ) ) -projects_router.register(r"heatmaps", HeatmapViewSet, "environment_heatmaps", ["team_id"]) -projects_router.register(r"sessions", SessionViewSet, "environment_sessions", ["team_id"]) +register_grandfathered_environment_nested_viewset(r"heatmaps", HeatmapViewSet, "environment_heatmaps", ["team_id"]) +register_grandfathered_environment_nested_viewset(r"sessions", SessionViewSet, "environment_sessions", ["team_id"]) if EE_AVAILABLE: from ee.clickhouse.views.experiments import EnterpriseExperimentsViewSet @@ -364,16 +412,18 @@ def api_not_found(request): from ee.clickhouse.views.person import EnterprisePersonViewSet, LegacyEnterprisePersonViewSet projects_router.register(r"experiments", EnterpriseExperimentsViewSet, "project_experiments", ["project_id"]) - projects_router.register(r"groups", GroupsViewSet, "environment_groups", ["team_id"]) + register_grandfathered_environment_nested_viewset(r"groups", GroupsViewSet, "environment_groups", ["team_id"]) projects_router.register(r"groups_types", GroupsTypesViewSet, "project_groups_types", ["project_id"]) project_insights_router = projects_router.register( r"insights", EnterpriseInsightsViewSet, "project_insights", ["project_id"] ) - projects_router.register(r"persons", EnterprisePersonViewSet, "environment_persons", ["team_id"]) + register_grandfathered_environment_nested_viewset( + r"persons", EnterprisePersonViewSet, "environment_persons", ["team_id"] + ) router.register(r"person", LegacyEnterprisePersonViewSet, "persons") else: project_insights_router = projects_router.register(r"insights", InsightViewSet, "project_insights", ["project_id"]) - projects_router.register(r"persons", PersonViewSet, "environment_persons", ["team_id"]) + register_grandfathered_environment_nested_viewset(r"persons", PersonViewSet, "environment_persons", ["team_id"]) router.register(r"person", LegacyPersonViewSet, "persons") @@ -405,12 +455,18 @@ def api_not_found(request): ["team_id", "insight_id"], ) -project_session_recordings_router.register( +environment_sessions_recordings_router.register( r"sharing", sharing.SharingConfigurationViewSet, "environment_recording_sharing", ["team_id", "recording_id"], ) +legacy_project_session_recordings_router.register( + r"sharing", + sharing.SharingConfigurationViewSet, + "project_recording_sharing", + ["team_id", "recording_id"], +) projects_router.register( r"notebooks", @@ -433,7 +489,7 @@ def api_not_found(request): ["project_id"], ) -projects_router.register( +register_grandfathered_environment_nested_viewset( r"hog_functions", hog_function.HogFunctionViewSet, "environment_hog_functions", @@ -447,7 +503,7 @@ def api_not_found(request): ["project_id"], ) -projects_router.register( +register_grandfathered_environment_nested_viewset( r"alerts", alert.AlertViewSet, "environment_alerts", diff --git a/posthog/api/project.py b/posthog/api/project.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/posthog/models/project.py b/posthog/models/project.py index 5bf82245db590..71785a31ccea9 100644 --- a/posthog/models/project.py +++ b/posthog/models/project.py @@ -25,10 +25,10 @@ def create_with_team(self, team_fields: Optional[dict] = None, **kwargs) -> tupl class Project(models.Model): """DO NOT USE YET - you probably mean the `Team` model instead. - `Project` is part of the environemnts feature, which is a work in progress. + `Project` is part of the environments feature, which is a work in progress. """ - id = models.BigIntegerField(primary_key=True, verbose_name="ID") + id = models.BigIntegerField(primary_key=True, verbose_name="ID") # Same as Team.id field organization = models.ForeignKey( "posthog.Organization", on_delete=models.CASCADE, diff --git a/posthog/urls.py b/posthog/urls.py index c34956e8131b3..69eaddf1c9717 100644 --- a/posthog/urls.py +++ b/posthog/urls.py @@ -28,10 +28,6 @@ authentication, capture, decide, - organizations_router, - project_dashboards_router, - project_feature_flags_router, - projects_router, router, sharing, signup, @@ -71,13 +67,7 @@ logger.warn(f"Could not import ee.urls", exc_info=True) pass else: - extend_api_router( - router, - projects_router=projects_router, - organizations_router=organizations_router, - project_dashboards_router=project_dashboards_router, - project_feature_flags_router=project_feature_flags_router, - ) + extend_api_router() @requires_csrf_token diff --git a/posthog/utils.py b/posthog/utils.py index 39bf6d606982f..5c1e7a03156fc 100644 --- a/posthog/utils.py +++ b/posthog/utils.py @@ -354,6 +354,7 @@ def render_template( posthog_app_context = { "current_user": None, + "current_project": None, "current_team": None, "preflight": json.loads(preflight_check(request).getvalue()), "default_event_name": "$pageview", @@ -387,6 +388,7 @@ def render_template( posthog_app_context["current_team"] = team_serialized.data posthog_app_context["frontend_apps"] = get_frontend_apps(user.team.pk) posthog_app_context["default_event_name"] = get_default_event_name(user.team) + # project_serialized = ProjectSerializer context["posthog_app_context"] = json.dumps(posthog_app_context, default=json_uuid_convert) From 2f63d478d9ff0f977e42d1d750ede20da3c09067 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Fri, 2 Aug 2024 01:13:44 +0200 Subject: [PATCH 05/32] Add new ProjectViewSet --- posthog/api/__init__.py | 5 +- posthog/api/project.py | 553 ++++++++++++++++++++++++++++++++++ posthog/api/team.py | 115 +++---- posthog/api/test/test_team.py | 18 +- posthog/models/project.py | 14 +- 5 files changed, 622 insertions(+), 83 deletions(-) diff --git a/posthog/api/__init__.py b/posthog/api/__init__.py index d8d13c87d8113..9be6ef1dd00b9 100644 --- a/posthog/api/__init__.py +++ b/posthog/api/__init__.py @@ -2,6 +2,7 @@ from rest_framework_extensions.routers import NestedRegistryItem +from posthog.api import project from posthog.api.routing import DefaultRouterPlusPlus from posthog.batch_exports import http as batch_exports from posthog.settings import EE_AVAILABLE @@ -83,7 +84,7 @@ def api_not_found(request): router.register(r"feature_flag", feature_flag.LegacyFeatureFlagViewSet) # Used for library side feature flag evaluation # Nested endpoints shared -projects_router = router.register(r"projects", team.RootTeamViewSet, "projects") +projects_router = router.register(r"projects", project.RootProjectViewSet, "projects") environments_router = router.register(r"environments", team.RootTeamViewSet, "environments") @@ -293,7 +294,7 @@ def register_grandfathered_environment_nested_viewset( # Organizations nested endpoints organizations_router = router.register(r"organizations", organization.OrganizationViewSet, "organizations") -organizations_router.register(r"projects", team.TeamViewSet, "organization_projects", ["organization_id"]) +organizations_router.register(r"projects", project.ProjectViewSet, "organization_projects", ["organization_id"]) organizations_router.register( r"batch_exports", batch_exports.BatchExportOrganizationViewSet, "batch_exports", ["organization_id"] ) diff --git a/posthog/api/project.py b/posthog/api/project.py index e69de29bb2d1d..41fbfa3649ac1 100644 --- a/posthog/api/project.py +++ b/posthog/api/project.py @@ -0,0 +1,553 @@ +import copy +from datetime import timedelta +from functools import cached_property +from typing import Any, Optional, cast + +from django.core.cache import cache +from django.shortcuts import get_object_or_404 +from loginas.utils import is_impersonated_session +from rest_framework import exceptions, request, response, serializers, viewsets +from rest_framework.decorators import action +from rest_framework.fields import SkipField +from rest_framework.permissions import IsAuthenticated +from rest_framework.relations import PKOnlyObject +from rest_framework.utils import model_meta + +from posthog.api.geoip import get_geoip_properties +from posthog.api.routing import TeamAndOrgViewSetMixin +from posthog.api.shared import TeamBasicSerializer +from posthog.api.team import PremiumMultiProjectPermissions, TeamSerializer, validate_team_attrs +from posthog.event_usage import report_user_action +from posthog.jwt import PosthogJwtAudience, encode_jwt +from posthog.models import Team, User +from posthog.models.activity_logging.activity_log import ( + Change, + Detail, + dict_changes_between, + load_activity, + log_activity, +) +from posthog.models.activity_logging.activity_page import activity_page_response +from posthog.models.async_deletion import AsyncDeletion, DeletionType +from posthog.models.group_type_mapping import GroupTypeMapping +from posthog.models.organization import OrganizationMembership +from posthog.models.personal_api_key import APIScopeObjectOrNotSupported +from posthog.models.project import Project +from posthog.models.signals import mute_selected_signals +from posthog.models.team.team import set_team_in_cache +from posthog.models.team.util import delete_batch_exports, delete_bulky_postgres_data +from posthog.models.utils import UUIDT, generate_random_token_project +from posthog.permissions import ( + APIScopePermission, + OrganizationAdminWritePermissions, + OrganizationMemberPermissions, + TeamMemberLightManagementPermission, + TeamMemberStrictManagementPermission, +) +from posthog.user_permissions import UserPermissions, UserPermissionsSerializerMixin +from posthog.utils import get_ip_address, get_week_start_for_country_code + + +class ProjectSerializer(serializers.ModelSerializer, UserPermissionsSerializerMixin): + effective_membership_level = serializers.SerializerMethodField() # Compat with TeamSerializer + has_group_types = serializers.SerializerMethodField() # Compat with TeamSerializer + live_events_token = serializers.SerializerMethodField() # Compat with TeamSerializer + + class Meta: + model = Project + fields = ( + "id", + "organization", + "name", + "created_at", + "effective_membership_level", # Compat with TeamSerializer + "has_group_types", # Compat with TeamSerializer + "live_events_token", # Compat with TeamSerializer + "updated_at", + "uuid", # Compat with TeamSerializer + "api_token", # Compat with TeamSerializer + "app_urls", # Compat with TeamSerializer + "slack_incoming_webhook", # Compat with TeamSerializer + "anonymize_ips", # Compat with TeamSerializer + "completed_snippet_onboarding", # Compat with TeamSerializer + "ingested_event", # Compat with TeamSerializer + "test_account_filters", # Compat with TeamSerializer + "test_account_filters_default_checked", # Compat with TeamSerializer + "path_cleaning_filters", # Compat with TeamSerializer + "is_demo", # Compat with TeamSerializer + "timezone", # Compat with TeamSerializer + "data_attributes", # Compat with TeamSerializer + "person_display_name_properties", # Compat with TeamSerializer + "correlation_config", # Compat with TeamSerializer + "autocapture_opt_out", # Compat with TeamSerializer + "autocapture_exceptions_opt_in", # Compat with TeamSerializer + "autocapture_web_vitals_opt_in", # Compat with TeamSerializer + "autocapture_exceptions_errors_to_ignore", # Compat with TeamSerializer + "capture_console_log_opt_in", # Compat with TeamSerializer + "capture_performance_opt_in", # Compat with TeamSerializer + "session_recording_opt_in", # Compat with TeamSerializer + "session_recording_sample_rate", # Compat with TeamSerializer + "session_recording_minimum_duration_milliseconds", # Compat with TeamSerializer + "session_recording_linked_flag", # Compat with TeamSerializer + "session_recording_network_payload_capture_config", # Compat with TeamSerializer + "session_replay_config", # Compat with TeamSerializer + "access_control", # Compat with TeamSerializer + "week_start_day", # Compat with TeamSerializer + "primary_dashboard", # Compat with TeamSerializer + "live_events_columns", # Compat with TeamSerializer + "recording_domains", # Compat with TeamSerializer + "person_on_events_querying_enabled", # Compat with TeamSerializer + "inject_web_apps", # Compat with TeamSerializer + "extra_settings", # Compat with TeamSerializer + "modifiers", # Compat with TeamSerializer + "default_modifiers", # Compat with TeamSerializer + "has_completed_onboarding_for", # Compat with TeamSerializer + "surveys_opt_in", # Compat with TeamSerializer + "heatmaps_opt_in", # Compat with TeamSerializer + ) + read_only_fields = ( + "id", + "uuid", + "organization", + "effective_membership_level", + "has_group_types", + "live_events_token", + "created_at", + "api_token", + "updated_at", + "ingested_event", + "default_modifiers", + "person_on_events_querying_enabled", + ) + + team_passthrough_fields = { + "updated_at", + "uuid", # Compat with TeamSerializer + "api_token", # Compat with TeamSerializer + "app_urls", # Compat with TeamSerializer + "slack_incoming_webhook", # Compat with TeamSerializer + "anonymize_ips", # Compat with TeamSerializer + "completed_snippet_onboarding", # Compat with TeamSerializer + "ingested_event", # Compat with TeamSerializer + "test_account_filters", # Compat with TeamSerializer + "test_account_filters_default_checked", # Compat with TeamSerializer + "path_cleaning_filters", # Compat with TeamSerializer + "is_demo", # Compat with TeamSerializer + "timezone", # Compat with TeamSerializer + "data_attributes", # Compat with TeamSerializer + "person_display_name_properties", # Compat with TeamSerializer + "correlation_config", # Compat with TeamSerializer + "autocapture_opt_out", # Compat with TeamSerializer + "autocapture_exceptions_opt_in", # Compat with TeamSerializer + "autocapture_web_vitals_opt_in", # Compat with TeamSerializer + "autocapture_exceptions_errors_to_ignore", # Compat with TeamSerializer + "capture_console_log_opt_in", # Compat with TeamSerializer + "capture_performance_opt_in", # Compat with TeamSerializer + "session_recording_opt_in", # Compat with TeamSerializer + "session_recording_sample_rate", # Compat with TeamSerializer + "session_recording_minimum_duration_milliseconds", # Compat with TeamSerializer + "session_recording_linked_flag", # Compat with TeamSerializer + "session_recording_network_payload_capture_config", # Compat with TeamSerializer + "session_replay_config", # Compat with TeamSerializer + "access_control", # Compat with TeamSerializer + "week_start_day", # Compat with TeamSerializer + "primary_dashboard", # Compat with TeamSerializer + "live_events_columns", # Compat with TeamSerializer + "recording_domains", # Compat with TeamSerializer + "person_on_events_querying_enabled", # Compat with TeamSerializer + "inject_web_apps", # Compat with TeamSerializer + "extra_settings", # Compat with TeamSerializer + "modifiers", # Compat with TeamSerializer + "default_modifiers", # Compat with TeamSerializer + "has_completed_onboarding_for", # Compat with TeamSerializer + "surveys_opt_in", # Compat with TeamSerializer + "heatmaps_opt_in", # Compat with TeamSerializer + } + + def get_fields(self): + declared_fields = copy.deepcopy(self._declared_fields) + + info = model_meta.get_field_info(Project) + team_info = model_meta.get_field_info(Team) + for field_name, field in team_info.fields.items(): + if field_name in info.fields: + continue + info.fields[field_name] = field + info.fields_and_pk[field_name] = field + for field_name, relation in team_info.forward_relations.items(): + if field_name in info.forward_relations: + continue + info.forward_relations[field_name] = relation + info.relations[field_name] = relation + for accessor_name, relation in team_info.reverse_relations.items(): + if accessor_name in info.reverse_relations: + continue + info.reverse_relations[accessor_name] = relation + info.relations[accessor_name] = relation + + field_names = self.get_field_names(declared_fields, info) + + extra_kwargs = self.get_extra_kwargs() + extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs(field_names, declared_fields, extra_kwargs) + + fields = {} + for field_name in field_names: + if field_name in declared_fields: + fields[field_name] = declared_fields[field_name] + continue + extra_field_kwargs = extra_kwargs.get(field_name, {}) + source = extra_field_kwargs.get("source", "*") + if source == "*": + source = field_name + field_class, field_kwargs = self.build_field(source, info, model_class=Project, nested_depth=0) + field_kwargs = self.include_extra_kwargs(field_kwargs, extra_field_kwargs) + fields[field_name] = field_class(**field_kwargs) + fields.update(hidden_fields) + return fields + + def build_field(self, field_name, info, model_class, nested_depth): + if field_name in self.Meta.team_passthrough_fields: + model_class = Team + return super().build_field(field_name, info, model_class, nested_depth) + + def to_representation(self, instance): + """ + Object instance -> Dict of primitive datatypes. + """ + ret = {} + fields = self._readable_fields + + for field in fields: + try: + attribute_source = instance + if field.field_name in self.Meta.team_passthrough_fields: + attribute_source = instance.passthrough_team + attribute = field.get_attribute(attribute_source) + except SkipField: + continue + + check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute + if check_for_none is None: + ret[field.field_name] = None + else: + ret[field.field_name] = field.to_representation(attribute) + + return ret + + def get_effective_membership_level(self, project: Project) -> Optional[OrganizationMembership.Level]: + team = project.teams.get(pk=project.pk) + return self.user_permissions.team(team).effective_membership_level + + def get_has_group_types(self, project: Project) -> bool: + return GroupTypeMapping.objects.filter(team_id=project.id).exists() + + def get_live_events_token(self, project: Project) -> Optional[str]: + team = project.teams.get(pk=project.pk) + return encode_jwt( + {"team_id": team.id, "api_token": team.api_token}, + timedelta(days=7), + PosthogJwtAudience.LIVESTREAM, + ) + + @staticmethod + def validate_session_recording_linked_flag(value) -> dict | None: + return TeamSerializer.validate_session_recording_linked_flag(value) + + @staticmethod + def validate_session_recording_network_payload_capture_config(value) -> dict | None: + return TeamSerializer.validate_session_recording_network_payload_capture_config(value) + + @staticmethod + def validate_session_replay_config(value) -> dict | None: + return TeamSerializer.validate_session_replay_config(value) + + @staticmethod + def validate_session_replay_ai_summary_config(value: dict | None) -> dict | None: + return TeamSerializer.validate_session_replay_ai_summary_config(value) + + def validate(self, attrs: Any) -> Any: + attrs = validate_team_attrs(attrs, self.context["view"], self.context["request"], self.instance) + return super().validate(attrs) + + def create(self, validated_data: dict[str, Any], **kwargs) -> Project: + serializers.raise_errors_on_nested_writes("create", self, validated_data) + request = self.context["request"] + organization = self.context["view"].organization # Use the org we used to validate permissions + + if "week_start_day" not in validated_data: + country_code = get_geoip_properties(get_ip_address(request)).get("$geoip_country_code", None) + if country_code: + week_start_day_for_user_ip_location = get_week_start_for_country_code(country_code) + # get_week_start_for_country_code() also returns 6 for countries where the week starts on Saturday, + # but ClickHouse doesn't support Saturday as the first day of the week, so we fall back to Sunday + validated_data["week_start_day"] = 1 if week_start_day_for_user_ip_location == 1 else 0 + + team_fields: dict[str, Any] = {} + for field_name in validated_data.copy(): # Copy to avoid iterating over a changing dict + if field_name in self.Meta.team_passthrough_fields: + team_fields[field_name] = validated_data.pop(field_name) + project, team = Project.objects.create_with_team(**validated_data, team_fields=team_fields) + + request.user.current_team = team + request.user.team = request.user.current_team # Update cached property + request.user.save() + + log_activity( + organization_id=organization.id, + team_id=team.pk, + user=request.user, + was_impersonated=is_impersonated_session(request), + scope="Team", + item_id=team.pk, + activity="created", + detail=Detail(name=str(team.name)), + ) + + return project + + def update(self, instance: Project, validated_data: dict[str, Any]) -> Project: + team = instance.passthrough_team + team_before_update = team.__dict__.copy() + + if ( + "session_replay_config" in validated_data + and validated_data["session_replay_config"] is not None + and team.session_replay_config is not None + ): + # for session_replay_config and its top level keys we merge existing settings with new settings + # this way we don't always have to receive the entire settings object to change one setting + # so for each key in validated_data["session_replay_config"] we merge it with the existing settings + # and then merge any top level keys that weren't provided + + for key, value in validated_data["session_replay_config"].items(): + if key in team.session_replay_config: + # if they're both dicts then we merge them, otherwise, the new value overwrites the old + if isinstance(team.session_replay_config[key], dict) and isinstance( + validated_data["session_replay_config"][key], dict + ): + validated_data["session_replay_config"][key] = { + **team.session_replay_config[key], # existing values + **value, # and new values on top + } + + # then also add back in any keys that exist but are not in the provided data + validated_data["session_replay_config"] = { + **team.session_replay_config, + **validated_data["session_replay_config"], + } + + should_team_be_saved_too = False + for attr, value in validated_data.items(): + if attr in self.Meta.team_passthrough_fields: + should_team_be_saved_too = True + setattr(team, attr, value) + else: + setattr(instance, attr, value) + + instance.save() + if should_team_be_saved_too: + team.save() + + team_after_update = team.__dict__.copy() + changes = dict_changes_between("Team", team_before_update, team_after_update, use_field_exclusions=True) + + log_activity( + organization_id=cast(UUIDT, instance.organization_id), + team_id=instance.pk, + user=cast(User, self.context["request"].user), + was_impersonated=is_impersonated_session(request), + scope="Team", + item_id=instance.pk, + activity="updated", + detail=Detail( + name=str(instance.name), + changes=changes, + ), + ) + + return instance + + +class ProjectViewSet(TeamAndOrgViewSetMixin, viewsets.ModelViewSet): + """ + Projects for the current organization. + """ + + scope_object: APIScopeObjectOrNotSupported = "project" + serializer_class = ProjectSerializer + queryset = Project.objects.all().select_related("organization").prefetch_related("teams") + lookup_field = "id" + ordering = "-created_by" + + def safely_get_queryset(self, queryset): + # IMPORTANT: This is actually what ensures that a user cannot read/update a project for which they don't have permission + visible_teams_ids = UserPermissions(cast(User, self.request.user)).team_ids_visible_for_user + return queryset.filter(id__in=visible_teams_ids) + + def get_serializer_class(self) -> type[serializers.BaseSerializer]: + if self.action == "list": + return TeamBasicSerializer + return super().get_serializer_class() + + # NOTE: Team permissions are somewhat complex so we override the underlying viewset's get_permissions method + def dangerously_get_permissions(self) -> list: + """ + Special permissions handling for create requests as the organization is inferred from the current user. + """ + + permissions: list = [ + IsAuthenticated, + APIScopePermission, + PremiumMultiProjectPermissions, + *self.permission_classes, + ] + + # Return early for non-actions (e.g. OPTIONS) + if self.action: + if self.action == "create": + if "is_demo" not in self.request.data or not self.request.data["is_demo"]: + permissions.append(OrganizationAdminWritePermissions) + else: + permissions.append(OrganizationMemberPermissions) + elif self.action != "list": + # Skip TeamMemberAccessPermission for list action, as list is serialized with limited TeamBasicSerializer + permissions.append(TeamMemberLightManagementPermission) + + return [permission() for permission in permissions] + + def safely_get_object(self, queryset): + lookup_value = self.kwargs[self.lookup_field] + if lookup_value == "@current": + team = getattr(self.request.user, "team", None) + if team is None: + raise exceptions.NotFound() + return team.project + + filter_kwargs = {self.lookup_field: lookup_value} + try: + project = get_object_or_404(queryset, **filter_kwargs) + except ValueError as error: + raise exceptions.ValidationError(str(error)) + return project + + # :KLUDGE: Exposed for compatibility reasons for permission classes. + @property + def team(self): + project = self.get_object() + return project.teams.get(id=project.id) + + def perform_destroy(self, project: Project): + project_id = project.pk + organization_id = project.organization_id + project_name = project.name + + user = cast(User, self.request.user) + + teams = list(project.teams.all()) + delete_bulky_postgres_data(team_ids=[team.id for team in teams]) + delete_batch_exports(team_ids=[team.pk for team in teams]) + + with mute_selected_signals(): + super().perform_destroy(project) + + # Once the project is deleted, queue deletion of associated data + AsyncDeletion.objects.bulk_create( + [ + AsyncDeletion( + deletion_type=DeletionType.Team, + team_id=team.id, + key=str(team.id), + created_by=user, + ) + for team in teams + ], + ignore_conflicts=True, + ) + + log_activity( + organization_id=cast(UUIDT, organization_id), + team_id=project_id, + user=user, + was_impersonated=is_impersonated_session(self.request), + scope="Team", # TODO: Change to "Project" + item_id=project_id, + activity="deleted", + detail=Detail(name=str(project_name)), + ) + # TRICKY: We pass in Team here as otherwise the access to "current_team" can fail if it was deleted + report_user_action(user, f"team deleted", team=teams[0]) # TODO: Change to "project deleted" + + @action( + methods=["PATCH"], + detail=True, + # Only ADMIN or higher users are allowed to access this project + permission_classes=[TeamMemberStrictManagementPermission], + ) + def reset_token(self, request: request.Request, id: str, **kwargs) -> response.Response: + project = self.get_object() + team = project.passthrough_team + old_token = team.api_token + team.api_token = generate_random_token_project() + team.save() + + log_activity( + organization_id=team.organization_id, + team_id=team.pk, + user=cast(User, request.user), + was_impersonated=is_impersonated_session(request), + scope="Team", + item_id=team.pk, + activity="updated", + detail=Detail( + name=str(team.name), + changes=[ + Change( + type="Team", + action="changed", + field="api_token", + ) + ], + ), + ) + + set_team_in_cache(old_token, None) + return response.Response(ProjectSerializer(project, context=self.get_serializer_context()).data) + + @action( + methods=["GET"], + detail=True, + permission_classes=[IsAuthenticated], + ) + def is_generating_demo_data(self, request: request.Request, id: str, **kwargs) -> response.Response: + project = self.get_object() + cache_key = f"is_generating_demo_data_{project.pk}" + return response.Response({"is_generating_demo_data": cache.get(cache_key) == "True"}) + + @action(methods=["GET"], detail=True) + def activity(self, request: request.Request, **kwargs): + # TODO: Rework for Project scope + limit = int(request.query_params.get("limit", "10")) + page = int(request.query_params.get("page", "1")) + + project = self.get_object() + + activity_page = load_activity( + scope="Team", + team_id=project.pk, + item_ids=[str(project.pk)], + limit=limit, + page=page, + ) + return activity_page_response(activity_page, limit, page, request) + + @cached_property + def user_permissions(self): + project = self.get_object() if self.action == "reset_token" else None + team = project.passthrough_team if project else None + return UserPermissions(cast(User, self.request.user), team) + + +class RootProjectViewSet(ProjectViewSet): + # NOTE: We don't want people creating projects via the "current_organization" concept, but rather specify the org ID + # in the URL - hence this is hidden from the API docs, but used in the app + hide_api_docs = True diff --git a/posthog/api/team.py b/posthog/api/team.py index 9f4e04e007eaf..5a71d2ef72df6 100644 --- a/posthog/api/team.py +++ b/posthog/api/team.py @@ -8,15 +8,15 @@ from loginas.utils import is_impersonated_session from posthog.jwt import PosthogJwtAudience, encode_jwt from rest_framework.permissions import BasePermission, IsAuthenticated -from rest_framework import exceptions, request, response, serializers, viewsets from posthog.api.utils import action +from rest_framework import exceptions, request, response, serializers, viewsets, views from posthog.api.geoip import get_geoip_properties from posthog.api.routing import TeamAndOrgViewSetMixin from posthog.api.shared import TeamBasicSerializer from posthog.constants import AvailableFeature from posthog.event_usage import report_user_action -from posthog.models import InsightCachingState, Team, User +from posthog.models import Team, User from posthog.models.activity_logging.activity_log import ( Change, Detail, @@ -42,7 +42,6 @@ TeamMemberStrictManagementPermission, get_organization_from_view, ) -from posthog.tasks.demo_create_data import create_data_for_demo_team from posthog.user_permissions import UserPermissions, UserPermissionsSerializerMixin from posthog.utils import get_ip_address, get_week_start_for_country_code @@ -50,7 +49,7 @@ class PremiumMultiProjectPermissions(BasePermission): """Require user to have all necessary premium features on their plan for create access to the endpoint.""" - message = "You must upgrade your PostHog plan to be able to create and manage multiple projects." + message = "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments." def has_permission(self, request: request.Request, view) -> bool: if request.method in CREATE_METHODS: @@ -188,7 +187,7 @@ def get_effective_membership_level(self, team: Team) -> Optional[OrganizationMem return self.user_permissions.team(team).effective_membership_level def get_has_group_types(self, team: Team) -> bool: - return GroupTypeMapping.objects.filter(team=team).exists() + return GroupTypeMapping.objects.filter(team_id=team.id).exists() def get_live_events_token(self, team: Team) -> Optional[str]: return encode_jwt( @@ -197,7 +196,8 @@ def get_live_events_token(self, team: Team) -> Optional[str]: PosthogJwtAudience.LIVESTREAM, ) - def validate_session_recording_linked_flag(self, value) -> dict | None: + @staticmethod + def validate_session_recording_linked_flag(value) -> dict | None: if value is None: return None @@ -215,7 +215,8 @@ def validate_session_recording_linked_flag(self, value) -> dict | None: return value - def validate_session_recording_network_payload_capture_config(self, value) -> dict | None: + @staticmethod + def validate_session_recording_network_payload_capture_config(value) -> dict | None: if value is None: return None @@ -229,7 +230,8 @@ def validate_session_recording_network_payload_capture_config(self, value) -> di return value - def validate_session_replay_config(self, value) -> dict | None: + @staticmethod + def validate_session_replay_config(value) -> dict | None: if value is None: return None @@ -243,11 +245,12 @@ def validate_session_replay_config(self, value) -> dict | None: ) if "ai_config" in value: - self.validate_session_replay_ai_summary_config(value["ai_config"]) + TeamSerializer.validate_session_replay_ai_summary_config(value["ai_config"]) return value - def validate_session_replay_ai_summary_config(self, value: dict | None) -> dict | None: + @staticmethod + def validate_session_replay_ai_summary_config(value: dict | None) -> dict | None: if value is not None: if not isinstance(value, dict): raise exceptions.ValidationError("Must provide a dictionary or None.") @@ -267,38 +270,7 @@ def validate_session_replay_ai_summary_config(self, value: dict | None) -> dict return value def validate(self, attrs: Any) -> Any: - if "primary_dashboard" in attrs and attrs["primary_dashboard"].team != self.instance: - raise exceptions.PermissionDenied("Dashboard does not belong to this team.") - - if "access_control" in attrs: - # Only organization-wide admins and above should be allowed to switch the project between open and private - # If a project-only admin who is only an org member disabled this it, they wouldn't be able to reenable it - request = self.context["request"] - if isinstance(self.instance, Team): - organization_id = self.instance.organization_id - else: - organization_id = self.context["view"].organization - org_membership: OrganizationMembership = OrganizationMembership.objects.only("level").get( - organization_id=organization_id, user=request.user - ) - if org_membership.level < OrganizationMembership.Level.ADMIN: - raise exceptions.PermissionDenied("Your organization access level is insufficient.") - - if "autocapture_exceptions_errors_to_ignore" in attrs: - if not isinstance(attrs["autocapture_exceptions_errors_to_ignore"], list): - raise exceptions.ValidationError( - "Must provide a list for field: autocapture_exceptions_errors_to_ignore." - ) - for error in attrs["autocapture_exceptions_errors_to_ignore"]: - if not isinstance(error, str): - raise exceptions.ValidationError( - "Must provide a list of strings to field: autocapture_exceptions_errors_to_ignore." - ) - - if len(json.dumps(attrs["autocapture_exceptions_errors_to_ignore"])) > 300: - raise exceptions.ValidationError( - "Field autocapture_exceptions_errors_to_ignore must be less than 300 characters. Complex config should be provided in posthog-js initialization." - ) + attrs = validate_team_attrs(attrs, self.context["view"], self.context["request"], self.instance) return super().validate(attrs) def create(self, validated_data: dict[str, Any], **kwargs) -> Team: @@ -314,13 +286,7 @@ def create(self, validated_data: dict[str, Any], **kwargs) -> Team: # but ClickHouse doesn't support Saturday as the first day of the week, so we fall back to Sunday validated_data["week_start_day"] = 1 if week_start_day_for_user_ip_location == 1 else 0 - if validated_data.get("is_demo", False): - team = Team.objects.create(**validated_data, organization=organization) - cache_key = f"is_generating_demo_data_{team.pk}" - cache.set(cache_key, "True") # create an item in the cache that we can use to see if the demo data is ready - create_data_for_demo_team.delay(team.pk, request.user.pk, cache_key) - else: - team = Team.objects.create_with_data(**validated_data, organization=organization) + team = Team.objects.create_with_data(**validated_data) request.user.current_team = team request.user.team = request.user.current_team # Update cached property @@ -339,22 +305,9 @@ def create(self, validated_data: dict[str, Any], **kwargs) -> Team: return team - def _clear_team_insight_caching_states(self, team: Team) -> None: - # TODO: Remove this method: - # 1. It only clear the cache for saved insights, queries not linked to one are being ignored here - # 2. We should anyway 100% be relying on cache keys being different for materially different queries, instead of - # on remembering to call this method when project settings change. We probably already are in the clear here! - hashes = InsightCachingState.objects.filter(team=team).values_list("cache_key", flat=True) - cache.delete_many(hashes) - def update(self, instance: Team, validated_data: dict[str, Any]) -> Team: before_update = instance.__dict__.copy() - if ("timezone" in validated_data and validated_data["timezone"] != instance.timezone) or ( - "modifiers" in validated_data and validated_data["modifiers"] != instance.modifiers - ): - self._clear_team_insight_caching_states(instance) - if ( "session_replay_config" in validated_data and validated_data["session_replay_config"] is not None @@ -407,7 +360,7 @@ class TeamViewSet(TeamAndOrgViewSetMixin, viewsets.ModelViewSet): Projects for the current organization. """ - scope_object: APIScopeObjectOrNotSupported = "project" + scope_object: APIScopeObjectOrNotSupported = "project" # TODO: Change to `environment` on environments rollout serializer_class = TeamSerializer queryset = Team.objects.all().select_related("organization") lookup_field = "id" @@ -576,7 +529,37 @@ def user_permissions(self): class RootTeamViewSet(TeamViewSet): - # NOTE: We don't want people managing projects via the "current_organization" concept. - # Rather specifying the org ID at the top level - we still support it for backwards compat but don't document it anymore. - + # NOTE: We don't want people creating environments via the "current_organization"/"current_project" concept, but + # rather specify the org ID and project ID in the URL - hence this is hidden from the API docs, but used in the app hide_api_docs = True + + +def validate_team_attrs(attrs: dict[str, Any], view: views.View, request: request.Request, instance) -> dict[str, Any]: + attrs["organization_id"] = view.organization_id + + if "primary_dashboard" in attrs and attrs["primary_dashboard"].team_id != instance.id: + raise exceptions.PermissionDenied("Dashboard does not belong to this team.") + + if "access_control" in attrs: + # Only organization-wide admins and above should be allowed to switch the project between open and private + # If a project-only admin who is only an org member disabled this it, they wouldn't be able to reenable it + org_membership: OrganizationMembership = OrganizationMembership.objects.only("level").get( + organization_id=instance.organization_id, user=request.user + ) + if org_membership.level < OrganizationMembership.Level.ADMIN: + raise exceptions.PermissionDenied("Your organization access level is insufficient.") + + if "autocapture_exceptions_errors_to_ignore" in attrs: + if not isinstance(attrs["autocapture_exceptions_errors_to_ignore"], list): + raise exceptions.ValidationError("Must provide a list for field: autocapture_exceptions_errors_to_ignore.") + for error in attrs["autocapture_exceptions_errors_to_ignore"]: + if not isinstance(error, str): + raise exceptions.ValidationError( + "Must provide a list of strings to field: autocapture_exceptions_errors_to_ignore." + ) + + if len(json.dumps(attrs["autocapture_exceptions_errors_to_ignore"])) > 300: + raise exceptions.ValidationError( + "Field autocapture_exceptions_errors_to_ignore must be less than 300 characters. Complex config should be provided in posthog-js initialization." + ) + return attrs diff --git a/posthog/api/test/test_team.py b/posthog/api/test/test_team.py index 04c3787ad25a1..cfd8b125218cb 100644 --- a/posthog/api/test/test_team.py +++ b/posthog/api/test/test_team.py @@ -89,7 +89,7 @@ def test_cant_retrieve_project_from_another_org(self): self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) self.assertEqual(response.json(), self.not_found_response()) - @patch("posthog.api.team.get_geoip_properties") + @patch("posthog.api.project.get_geoip_properties") def test_ip_location_is_used_for_new_project_week_day_start(self, get_geoip_properties_mock: MagicMock): self.organization.available_product_features = [ {"key": AvailableFeature.ORGANIZATIONS_PROJECTS, "name": AvailableFeature.ORGANIZATIONS_PROJECTS} @@ -138,7 +138,7 @@ def test_cant_create_a_second_project_without_license(self): { "type": "authentication_error", "code": "permission_denied", - "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects.", + "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments.", }, response_data, ) @@ -152,7 +152,7 @@ def test_cant_create_a_second_project_without_license(self): { "type": "authentication_error", "code": "permission_denied", - "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects.", + "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments.", }, response_data, ) @@ -254,7 +254,7 @@ def test_filter_permission(self): ) @freeze_time("2022-02-08") - @patch("posthog.api.team.delete_bulky_postgres_data") + @patch("posthog.api.project.delete_bulky_postgres_data") @patch("posthoganalytics.capture") def test_delete_team_activity_log(self, mock_capture: MagicMock, mock_delete_bulky_postgres_data: MagicMock): self.organization_membership.level = OrganizationMembership.Level.ADMIN @@ -297,7 +297,7 @@ def test_delete_team_activity_log(self, mock_capture: MagicMock, mock_delete_bul }, ] - @patch("posthog.api.team.delete_bulky_postgres_data") + @patch("posthog.api.project.delete_bulky_postgres_data") @patch("posthoganalytics.capture") def test_delete_team_own_second(self, mock_capture: MagicMock, mock_delete_bulky_postgres_data: MagicMock): self.organization_membership.level = OrganizationMembership.Level.ADMIN @@ -512,14 +512,6 @@ def test_is_generating_demo_data(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.json(), {"is_generating_demo_data": False}) - @patch("posthog.api.team.create_data_for_demo_team.delay") - def test_org_member_can_create_demo_project(self, mock_create_data_for_demo_team: MagicMock): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - response = self.client.post("/api/projects/", {"name": "Hedgebox", "is_demo": True}) - mock_create_data_for_demo_team.assert_called_once() - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - @freeze_time("2022-02-08") def test_team_float_config_can_be_serialized_to_activity_log(self): # regression test since this isn't true by default diff --git a/posthog/models/project.py b/posthog/models/project.py index 71785a31ccea9..fc62bc6ef43fa 100644 --- a/posthog/models/project.py +++ b/posthog/models/project.py @@ -1,4 +1,5 @@ from typing import TYPE_CHECKING, Optional, cast +from functools import cached_property from django.db import models from django.db import transaction from django.core.validators import MinLengthValidator @@ -10,14 +11,19 @@ class ProjectManager(models.Manager): - def create_with_team(self, team_fields: Optional[dict] = None, **kwargs) -> tuple["Project", "Team"]: + def create_with_team(self, *, team_fields: Optional[dict] = None, **kwargs) -> tuple["Project", "Team"]: from .team import Team + if team_fields is None: + team_fields = {} + if "name" in kwargs and "name" not in team_fields: + team_fields["name"] = kwargs["name"] + with transaction.atomic(using=self.db): common_id = Team.objects.increment_id_sequence() project = cast("Project", self.create(id=common_id, **kwargs)) team = Team.objects.create( - id=common_id, organization=project.organization, project=project, **(team_fields or {}) + id=common_id, organization_id=project.organization_id, project=project, **team_fields ) return project, team @@ -44,6 +50,10 @@ class Project(models.Model): objects: ProjectManager = ProjectManager() + @cached_property + def passthrough_team(self) -> "Team": + return self.teams.get(pk=self.pk) + def __str__(self): if self.name: return self.name From 81815d75216adabf2e6dc055de8546656c5e3bd5 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Fri, 2 Aug 2024 01:14:15 +0200 Subject: [PATCH 06/32] Simplify `TeamMemberLightManagementPermission` --- posthog/permissions.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/posthog/permissions.py b/posthog/permissions.py index d7c6bd4cf81d9..6a2a3c14cb490 100644 --- a/posthog/permissions.py +++ b/posthog/permissions.py @@ -173,11 +173,7 @@ class TeamMemberLightManagementPermission(BasePermission): def has_permission(self, request, view) -> bool: try: - if request.resolver_match.url_name.startswith("team-"): - # /projects/ endpoint handling - team = view.get_object() - else: - team = view.team + team = view.team except Team.DoesNotExist: return True # This will be handled as a 404 in the viewset requesting_level = view.user_permissions.team(team).effective_membership_level From 9bab8b0dc3a2bfccc75ae36f0e9526e254a0dd18 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Fri, 2 Aug 2024 01:14:52 +0200 Subject: [PATCH 07/32] Add current project to app context --- posthog/utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/posthog/utils.py b/posthog/utils.py index 5c1e7a03156fc..9b2b322092778 100644 --- a/posthog/utils.py +++ b/posthog/utils.py @@ -348,6 +348,7 @@ def render_template( if not request.GET.get("no-preloaded-app-context"): from posthog.api.shared import TeamPublicSerializer from posthog.api.team import TeamSerializer + from posthog.api.project import ProjectSerializer from posthog.api.user import UserSerializer from posthog.user_permissions import UserPermissions from posthog.views import preflight_check @@ -386,9 +387,14 @@ def render_template( many=False, ) posthog_app_context["current_team"] = team_serialized.data + project_serialized = ProjectSerializer( + user.team.project, + context={"request": request, "user_permissions": user_permissions}, + many=False, + ) + posthog_app_context["current_project"] = project_serialized.data posthog_app_context["frontend_apps"] = get_frontend_apps(user.team.pk) posthog_app_context["default_event_name"] = get_default_event_name(user.team) - # project_serialized = ProjectSerializer context["posthog_app_context"] = json.dumps(posthog_app_context, default=json_uuid_convert) From 358ecb2be41ef75d91696db6bd3315ff1b6e0a19 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Sat, 3 Aug 2024 00:36:54 +0200 Subject: [PATCH 08/32] Fix minor issues --- ee/api/test/test_billing.py | 3 +- ee/api/test/test_team.py | 8 +- posthog/api/__init__.py | 2 +- posthog/api/project.py | 165 ++++++++-------------------- posthog/api/shared.py | 109 ++++++++++++++++++ posthog/models/test/test_project.py | 2 +- posthog/test/test_middleware.py | 2 +- 7 files changed, 165 insertions(+), 126 deletions(-) diff --git a/ee/api/test/test_billing.py b/ee/api/test/test_billing.py index 6062516c4ccef..00beee3f0a671 100644 --- a/ee/api/test/test_billing.py +++ b/ee/api/test/test_billing.py @@ -777,9 +777,10 @@ def mock_implementation(url: str, headers: Any = None, params: Any = None) -> Ma # Create a demo project self.organization_membership.level = OrganizationMembership.Level.ADMIN self.organization_membership.save() + self.assertEqual(Team.objects.count(), 1) response = self.client.post("/api/projects/", {"name": "Test", "is_demo": True}) self.assertEqual(response.status_code, 201) - self.assertEqual(Team.objects.count(), 3) + self.assertEqual(Team.objects.count(), 2) demo_team = Team.objects.filter(is_demo=True).first() diff --git a/ee/api/test/test_team.py b/ee/api/test/test_team.py index db9fb7efdbf37..9ace30a718798 100644 --- a/ee/api/test/test_team.py +++ b/ee/api/test/test_team.py @@ -51,7 +51,7 @@ def test_create_demo_project(self, *args): self.organization_membership.level = OrganizationMembership.Level.ADMIN self.organization_membership.save() response = self.client.post("/api/projects/", {"name": "Hedgebox", "is_demo": True}) - self.assertEqual(Team.objects.count(), 3) + self.assertEqual(Team.objects.count(), 2) self.assertEqual(response.status_code, 201) response_data = response.json() self.assertDictContainsSubset( @@ -68,7 +68,7 @@ def test_create_two_demo_projects(self, *args): self.organization_membership.level = OrganizationMembership.Level.ADMIN self.organization_membership.save() response = self.client.post("/api/projects/", {"name": "Hedgebox", "is_demo": True}) - self.assertEqual(Team.objects.count(), 3) + self.assertEqual(Team.objects.count(), 2) self.assertEqual(response.status_code, 201) response_data = response.json() self.assertDictContainsSubset( @@ -80,13 +80,13 @@ def test_create_two_demo_projects(self, *args): response_data, ) response_2 = self.client.post("/api/projects/", {"name": "Hedgebox", "is_demo": True}) - self.assertEqual(Team.objects.count(), 3) + self.assertEqual(Team.objects.count(), 2) response_2_data = response_2.json() self.assertDictContainsSubset( { "type": "authentication_error", "code": "permission_denied", - "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects.", + "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments.", }, response_2_data, ) diff --git a/posthog/api/__init__.py b/posthog/api/__init__.py index 9be6ef1dd00b9..3419e09b50209 100644 --- a/posthog/api/__init__.py +++ b/posthog/api/__init__.py @@ -89,7 +89,7 @@ def api_not_found(request): def register_grandfathered_environment_nested_viewset( - prefix: str, viewset: viewsets.GenericViewSet, basename: str, parents_query_lookups: list[str] + prefix: str, viewset: type[viewsets.GenericViewSet], basename: str, parents_query_lookups: list[str] ) -> tuple[NestedRegistryItem, NestedRegistryItem]: """ Register the environment-specific viewset under both /environments/:team_id/ (correct endpoint) diff --git a/posthog/api/project.py b/posthog/api/project.py index 41fbfa3649ac1..e08a35cac0838 100644 --- a/posthog/api/project.py +++ b/posthog/api/project.py @@ -1,4 +1,3 @@ -import copy from datetime import timedelta from functools import cached_property from typing import Any, Optional, cast @@ -8,18 +7,15 @@ from loginas.utils import is_impersonated_session from rest_framework import exceptions, request, response, serializers, viewsets from rest_framework.decorators import action -from rest_framework.fields import SkipField from rest_framework.permissions import IsAuthenticated -from rest_framework.relations import PKOnlyObject -from rest_framework.utils import model_meta from posthog.api.geoip import get_geoip_properties from posthog.api.routing import TeamAndOrgViewSetMixin -from posthog.api.shared import TeamBasicSerializer +from posthog.api.shared import ProjectBasicSerializer from posthog.api.team import PremiumMultiProjectPermissions, TeamSerializer, validate_team_attrs from posthog.event_usage import report_user_action from posthog.jwt import PosthogJwtAudience, encode_jwt -from posthog.models import Team, User +from posthog.models import User from posthog.models.activity_logging.activity_log import ( Change, Detail, @@ -48,7 +44,7 @@ from posthog.utils import get_ip_address, get_week_start_for_country_code -class ProjectSerializer(serializers.ModelSerializer, UserPermissionsSerializerMixin): +class ProjectSerializer(ProjectBasicSerializer, UserPermissionsSerializerMixin): effective_membership_level = serializers.SerializerMethodField() # Compat with TeamSerializer has_group_types = serializers.SerializerMethodField() # Compat with TeamSerializer live_events_token = serializers.SerializerMethodField() # Compat with TeamSerializer @@ -122,118 +118,48 @@ class Meta: team_passthrough_fields = { "updated_at", - "uuid", # Compat with TeamSerializer - "api_token", # Compat with TeamSerializer - "app_urls", # Compat with TeamSerializer - "slack_incoming_webhook", # Compat with TeamSerializer - "anonymize_ips", # Compat with TeamSerializer - "completed_snippet_onboarding", # Compat with TeamSerializer - "ingested_event", # Compat with TeamSerializer - "test_account_filters", # Compat with TeamSerializer - "test_account_filters_default_checked", # Compat with TeamSerializer - "path_cleaning_filters", # Compat with TeamSerializer - "is_demo", # Compat with TeamSerializer - "timezone", # Compat with TeamSerializer - "data_attributes", # Compat with TeamSerializer - "person_display_name_properties", # Compat with TeamSerializer - "correlation_config", # Compat with TeamSerializer - "autocapture_opt_out", # Compat with TeamSerializer - "autocapture_exceptions_opt_in", # Compat with TeamSerializer - "autocapture_web_vitals_opt_in", # Compat with TeamSerializer - "autocapture_exceptions_errors_to_ignore", # Compat with TeamSerializer - "capture_console_log_opt_in", # Compat with TeamSerializer - "capture_performance_opt_in", # Compat with TeamSerializer - "session_recording_opt_in", # Compat with TeamSerializer - "session_recording_sample_rate", # Compat with TeamSerializer - "session_recording_minimum_duration_milliseconds", # Compat with TeamSerializer - "session_recording_linked_flag", # Compat with TeamSerializer - "session_recording_network_payload_capture_config", # Compat with TeamSerializer - "session_replay_config", # Compat with TeamSerializer - "access_control", # Compat with TeamSerializer - "week_start_day", # Compat with TeamSerializer - "primary_dashboard", # Compat with TeamSerializer - "live_events_columns", # Compat with TeamSerializer - "recording_domains", # Compat with TeamSerializer - "person_on_events_querying_enabled", # Compat with TeamSerializer - "inject_web_apps", # Compat with TeamSerializer - "extra_settings", # Compat with TeamSerializer - "modifiers", # Compat with TeamSerializer - "default_modifiers", # Compat with TeamSerializer - "has_completed_onboarding_for", # Compat with TeamSerializer - "surveys_opt_in", # Compat with TeamSerializer - "heatmaps_opt_in", # Compat with TeamSerializer + "uuid", + "api_token", + "app_urls", + "slack_incoming_webhook", + "anonymize_ips", + "completed_snippet_onboarding", + "ingested_event", + "test_account_filters", + "test_account_filters_default_checked", + "path_cleaning_filters", + "is_demo", + "timezone", + "data_attributes", + "person_display_name_properties", + "correlation_config", + "autocapture_opt_out", + "autocapture_exceptions_opt_in", + "autocapture_web_vitals_opt_in", + "autocapture_exceptions_errors_to_ignore", + "capture_console_log_opt_in", + "capture_performance_opt_in", + "session_recording_opt_in", + "session_recording_sample_rate", + "session_recording_minimum_duration_milliseconds", + "session_recording_linked_flag", + "session_recording_network_payload_capture_config", + "session_replay_config", + "access_control", + "week_start_day", + "primary_dashboard", + "live_events_columns", + "recording_domains", + "person_on_events_querying_enabled", + "inject_web_apps", + "extra_settings", + "modifiers", + "default_modifiers", + "has_completed_onboarding_for", + "surveys_opt_in", + "heatmaps_opt_in", } - def get_fields(self): - declared_fields = copy.deepcopy(self._declared_fields) - - info = model_meta.get_field_info(Project) - team_info = model_meta.get_field_info(Team) - for field_name, field in team_info.fields.items(): - if field_name in info.fields: - continue - info.fields[field_name] = field - info.fields_and_pk[field_name] = field - for field_name, relation in team_info.forward_relations.items(): - if field_name in info.forward_relations: - continue - info.forward_relations[field_name] = relation - info.relations[field_name] = relation - for accessor_name, relation in team_info.reverse_relations.items(): - if accessor_name in info.reverse_relations: - continue - info.reverse_relations[accessor_name] = relation - info.relations[accessor_name] = relation - - field_names = self.get_field_names(declared_fields, info) - - extra_kwargs = self.get_extra_kwargs() - extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs(field_names, declared_fields, extra_kwargs) - - fields = {} - for field_name in field_names: - if field_name in declared_fields: - fields[field_name] = declared_fields[field_name] - continue - extra_field_kwargs = extra_kwargs.get(field_name, {}) - source = extra_field_kwargs.get("source", "*") - if source == "*": - source = field_name - field_class, field_kwargs = self.build_field(source, info, model_class=Project, nested_depth=0) - field_kwargs = self.include_extra_kwargs(field_kwargs, extra_field_kwargs) - fields[field_name] = field_class(**field_kwargs) - fields.update(hidden_fields) - return fields - - def build_field(self, field_name, info, model_class, nested_depth): - if field_name in self.Meta.team_passthrough_fields: - model_class = Team - return super().build_field(field_name, info, model_class, nested_depth) - - def to_representation(self, instance): - """ - Object instance -> Dict of primitive datatypes. - """ - ret = {} - fields = self._readable_fields - - for field in fields: - try: - attribute_source = instance - if field.field_name in self.Meta.team_passthrough_fields: - attribute_source = instance.passthrough_team - attribute = field.get_attribute(attribute_source) - except SkipField: - continue - - check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute - if check_for_none is None: - ret[field.field_name] = None - else: - ret[field.field_name] = field.to_representation(attribute) - - return ret - def get_effective_membership_level(self, project: Project) -> Optional[OrganizationMembership.Level]: team = project.teams.get(pk=project.pk) return self.user_permissions.team(team).effective_membership_level @@ -342,6 +268,9 @@ def update(self, instance: Project, validated_data: dict[str, Any]) -> Project: should_team_be_saved_too = True setattr(team, attr, value) else: + if attr == "name": # `name` should be updated on _both_ the Project and Team + should_team_be_saved_too = True + setattr(team, attr, value) setattr(instance, attr, value) instance.save() @@ -386,7 +315,7 @@ def safely_get_queryset(self, queryset): def get_serializer_class(self) -> type[serializers.BaseSerializer]: if self.action == "list": - return TeamBasicSerializer + return ProjectBasicSerializer return super().get_serializer_class() # NOTE: Team permissions are somewhat complex so we override the underlying viewset's get_permissions method diff --git a/posthog/api/shared.py b/posthog/api/shared.py index e37fe9de29297..49a390fad983f 100644 --- a/posthog/api/shared.py +++ b/posthog/api/shared.py @@ -2,12 +2,17 @@ This module contains serializers that are used across other serializers for nested representations. """ +import copy from typing import Optional from rest_framework import serializers from posthog.models import Organization, Team, User from posthog.models.organization import OrganizationMembership +from posthog.models.project import Project +from rest_framework.fields import SkipField +from rest_framework.relations import PKOnlyObject +from rest_framework.utils import model_meta class UserBasicSerializer(serializers.ModelSerializer): @@ -36,6 +41,110 @@ def get_hedgehog_config(self, user: User) -> Optional[dict]: return None +class ProjectBasicSerializer(serializers.ModelSerializer): + """ + Serializer for `Project` model with minimal attributes to speeed up loading and transfer times. + Also used for nested serializers. + """ + + class Meta: + model = Project + fields = ( + "id", + "uuid", # Compat with TeamSerializer + "organization", + "api_token", # Compat with TeamSerializer + "name", + "completed_snippet_onboarding", # Compat with TeamSerializer + "has_completed_onboarding_for", # Compat with TeamSerializer + "ingested_event", # Compat with TeamSerializer + "is_demo", # Compat with TeamSerializer + "timezone", # Compat with TeamSerializer + "access_control", # Compat with TeamSerializer + ) + read_only_fields = fields + team_passthrough_fields = { + "uuid", + "api_token", + "completed_snippet_onboarding", + "has_completed_onboarding_for", + "ingested_event", + "is_demo", + "timezone", + "access_control", + } + + def get_fields(self): + declared_fields = copy.deepcopy(self._declared_fields) + + info = model_meta.get_field_info(Project) + team_info = model_meta.get_field_info(Team) + for field_name, field in team_info.fields.items(): + if field_name in info.fields: + continue + info.fields[field_name] = field + info.fields_and_pk[field_name] = field + for field_name, relation in team_info.forward_relations.items(): + if field_name in info.forward_relations: + continue + info.forward_relations[field_name] = relation + info.relations[field_name] = relation + for accessor_name, relation in team_info.reverse_relations.items(): + if accessor_name in info.reverse_relations: + continue + info.reverse_relations[accessor_name] = relation + info.relations[accessor_name] = relation + + field_names = self.get_field_names(declared_fields, info) + + extra_kwargs = self.get_extra_kwargs() + extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs(field_names, declared_fields, extra_kwargs) + + fields = {} + for field_name in field_names: + if field_name in declared_fields: + fields[field_name] = declared_fields[field_name] + continue + extra_field_kwargs = extra_kwargs.get(field_name, {}) + source = extra_field_kwargs.get("source", "*") + if source == "*": + source = field_name + field_class, field_kwargs = self.build_field(source, info, model_class=Project, nested_depth=0) + field_kwargs = self.include_extra_kwargs(field_kwargs, extra_field_kwargs) + fields[field_name] = field_class(**field_kwargs) + fields.update(hidden_fields) + return fields + + def build_field(self, field_name, info, model_class, nested_depth): + if field_name in self.Meta.team_passthrough_fields: + model_class = Team + return super().build_field(field_name, info, model_class, nested_depth) + + def to_representation(self, instance): + """ + Object instance -> Dict of primitive datatypes. + """ + ret = {} + fields = self._readable_fields + + for field in fields: + try: + attribute_source = instance + if field.field_name in self.Meta.team_passthrough_fields: + attribute_source = instance.passthrough_team + attribute = field.get_attribute(attribute_source) + except SkipField: + continue + + check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute + if check_for_none is None: + ret[field.field_name] = None + else: + ret[field.field_name] = field.to_representation(attribute) + + return ret + + class TeamBasicSerializer(serializers.ModelSerializer): """ Serializer for `Team` model with minimal attributes to speeed up loading and transfer times. diff --git a/posthog/models/test/test_project.py b/posthog/models/test/test_project.py index d6bfe0ed3a36a..1e2e0cef2167a 100644 --- a/posthog/models/test/test_project.py +++ b/posthog/models/test/test_project.py @@ -17,7 +17,7 @@ def test_create_project_with_team_no_team_fields(self): self.assertEqual( team.name, - "Default project", # TODO: When Environments are rolled out, ensure this says "Default environment" + "Test project", # TODO: When Environments are rolled out, ensure this says "Default environment" ) self.assertEqual(team.organization, self.organization) self.assertEqual(team.project, project) diff --git a/posthog/test/test_middleware.py b/posthog/test/test_middleware.py index ce8bfeb71b7bb..f5b4190ef4293 100644 --- a/posthog/test/test_middleware.py +++ b/posthog/test/test_middleware.py @@ -124,7 +124,7 @@ class TestAutoProjectMiddleware(APIBaseTest): @classmethod def setUpTestData(cls): super().setUpTestData() - cls.base_app_num_queries = 40 + cls.base_app_num_queries = 45 # Create another team that the user does have access to cls.second_team = create_team(organization=cls.organization, name="Second Life") From dd662b3ced48a10c6b74223ad8707d19d2e50ea2 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Tue, 20 Aug 2024 00:07:06 +0200 Subject: [PATCH 09/32] Add `TeamAndOrgViewSetMixin` tests --- posthog/api/test/test_routing.py | 65 +++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/posthog/api/test/test_routing.py b/posthog/api/test/test_routing.py index 76abb2693cf92..52712ae0500de 100644 --- a/posthog/api/test/test_routing.py +++ b/posthog/api/test/test_routing.py @@ -2,9 +2,72 @@ from posthog.api.routing import TeamAndOrgViewSetMixin +from django.test import override_settings +from django.urls import include, path +from rest_framework import viewsets +from posthog.api.annotation import AnnotationSerializer +from posthog.api.routing import DefaultRouterPlusPlus +from posthog.models.annotation import Annotation +from posthog.models.organization import Organization +from posthog.models.project import Project +from posthog.models.team.team import Team +from posthog.test.base import APIBaseTest -class TestRouting: +class FooViewSet(TeamAndOrgViewSetMixin, viewsets.ModelViewSet): + scope_object = "INTERNAL" + queryset = Annotation.objects.all() + serializer_class = AnnotationSerializer + + +test_router = DefaultRouterPlusPlus() + +test_environments_router = test_router.register(r"environments", FooViewSet, "environments") +test_environments_router.register(r"foos", FooViewSet, "environment_foos", ["team_id"]) + +test_projects_router = test_router.register(r"projects", FooViewSet, "projects") +test_projects_router.register(r"foos", FooViewSet, "project_foos", ["project_id"]) + +test_organizations_router = test_router.register(r"organizations", FooViewSet, "organizations") +test_organizations_router.register(r"foos", FooViewSet, "organization_foos", ["organization_id"]) + + +urlpatterns = [ + path("api/", include(test_router.urls)), +] + + +@override_settings(ROOT_URLCONF=__name__) # Use `urlpatterns` from this file and not from `posthog.urls` +class TestTeamAndOrgViewSetMixin(APIBaseTest): + test_annotation: Annotation + + def setUp(self): + super().setUp() + other_org, _, other_org_team = Organization.objects.bootstrap(user=self.user) + self.other_org_annotation = Annotation.objects.create(team=other_org_team, organization=other_org) + _, other_project_team = Project.objects.create_with_team(organization=self.organization) + self.other_project_annotation = Annotation.objects.create( + team=other_project_team, organization=self.organization + ) + other_team = Team.objects.create(organization=self.organization, project=self.project) + self.other_team_annotation = Annotation.objects.create(team=other_team, organization=self.organization) + self.current_team_annotation = Annotation.objects.create(team=self.team, organization=self.organization) + + def test_environment_nested_filtering(self): + response = self.client.get(f"/api/environments/{self.team.id}/foos/") + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json()["count"], 1) # Just current_team_annotation + + def test_project_nested_filtering(self): + response = self.client.get(f"/api/projects/{self.team.id}/foos/") + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json()["count"], 2) # Both current_team_annotation and other_team_annotation + + def test_organization_nested_filtering(self): + response = self.client.get(f"/api/organizations/{self.organization.id}/foos/") + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json()["count"], 3) # All except other_org_annotation + def test_cannot_override_special_methods(self): with pytest.raises(Exception) as e: From f0782731d785fbcad412b54fe8963827367b8fad Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Wed, 21 Aug 2024 15:55:34 +0200 Subject: [PATCH 10/32] Fix code quality points --- .storybook/app-context.ts | 3 ++- frontend/src/lib/api.mock.ts | 8 ++++++++ frontend/src/types.ts | 2 +- posthog/models/project.py | 8 ++++---- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.storybook/app-context.ts b/.storybook/app-context.ts index 6f52182cec58c..a85f06aa80e79 100644 --- a/.storybook/app-context.ts +++ b/.storybook/app-context.ts @@ -1,4 +1,4 @@ -import { MOCK_DEFAULT_TEAM } from 'lib/api.mock' +import { MOCK_DEFAULT_TEAM, MOCK_DEFAULT_PROJECT } from 'lib/api.mock' import { AppContext } from '~/types' export const getStorybookAppContext = (): AppContext => ({ @@ -6,6 +6,7 @@ export const getStorybookAppContext = (): AppContext => ({ // Ideally we wouldn't set `current_team` here, the same way we don't set `current_user`, but unfortunately // as of March 2024, a bunch of logics make the assumption that this is set, via `AppConfig` current_team: MOCK_DEFAULT_TEAM, + current_project: MOCK_DEFAULT_PROJECT, current_user: undefined as any, // `undefined` triggers a fetch and lets us mock the data default_event_name: '$pageview', persisted_feature_flags: [], diff --git a/frontend/src/lib/api.mock.ts b/frontend/src/lib/api.mock.ts index c6ca0a28c2cda..e10d348595cdd 100644 --- a/frontend/src/lib/api.mock.ts +++ b/frontend/src/lib/api.mock.ts @@ -12,6 +12,7 @@ import { PluginConfigWithPluginInfo, PluginInstallationType, PluginType, + ProjectType, PropertyFilterType, PropertyOperator, TeamType, @@ -90,6 +91,13 @@ export const MOCK_DEFAULT_TEAM: TeamType = { live_events_token: '123', } +export const MOCK_DEFAULT_PROJECT: ProjectType = { + id: MOCK_TEAM_ID, + name: 'MockHog App + Marketing', + organization_id: MOCK_ORGANIZATION_ID, + created_at: '2020-06-30T09:53:35.932534Z', +} + export const MOCK_DEFAULT_ORGANIZATION: OrganizationType = { customer_id: null, id: MOCK_ORGANIZATION_ID, diff --git a/frontend/src/types.ts b/frontend/src/types.ts index d9e13888e4f96..5ee55ac6c0d27 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -469,7 +469,7 @@ export interface SessionRecordingAIConfig { export interface ProjectType { id: number name: string - organization_id: number + organization_id: string created_at: string } export interface TeamType extends TeamBasicType { diff --git a/posthog/models/project.py b/posthog/models/project.py index fc62bc6ef43fa..bc006bf6546c3 100644 --- a/posthog/models/project.py +++ b/posthog/models/project.py @@ -50,13 +50,13 @@ class Project(models.Model): objects: ProjectManager = ProjectManager() - @cached_property - def passthrough_team(self) -> "Team": - return self.teams.get(pk=self.pk) - def __str__(self): if self.name: return self.name return str(self.pk) __repr__ = sane_repr("id", "name") + + @cached_property + def passthrough_team(self) -> "Team": + return self.teams.get(pk=self.pk) From 780f163399d63b3bef7b06b202c89c4137dac797 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Thu, 22 Aug 2024 18:38:24 +0200 Subject: [PATCH 11/32] Make mypy happy --- posthog/api/shared.py | 8 +++++--- posthog/api/team.py | 7 +++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/posthog/api/shared.py b/posthog/api/shared.py index 49a390fad983f..fc849eb2e2b42 100644 --- a/posthog/api/shared.py +++ b/posthog/api/shared.py @@ -3,7 +3,7 @@ """ import copy -from typing import Optional +from typing import Any, Optional from rest_framework import serializers @@ -122,15 +122,17 @@ def build_field(self, field_name, info, model_class, nested_depth): def to_representation(self, instance): """ - Object instance -> Dict of primitive datatypes. + Object instance -> Dict of primitive datatypes. Basically copied from Serializer.to_representation """ - ret = {} + ret: dict[str, Any] = {} fields = self._readable_fields for field in fields: + assert field.field_name is not None try: attribute_source = instance if field.field_name in self.Meta.team_passthrough_fields: + # This branch is the only material change from the original method attribute_source = instance.passthrough_team attribute = field.get_attribute(attribute_source) except SkipField: diff --git a/posthog/api/team.py b/posthog/api/team.py index 5a71d2ef72df6..3755ad58078f9 100644 --- a/posthog/api/team.py +++ b/posthog/api/team.py @@ -9,7 +9,7 @@ from posthog.jwt import PosthogJwtAudience, encode_jwt from rest_framework.permissions import BasePermission, IsAuthenticated from posthog.api.utils import action -from rest_framework import exceptions, request, response, serializers, viewsets, views +from rest_framework import exceptions, request, response, serializers, viewsets from posthog.api.geoip import get_geoip_properties from posthog.api.routing import TeamAndOrgViewSetMixin @@ -534,13 +534,16 @@ class RootTeamViewSet(TeamViewSet): hide_api_docs = True -def validate_team_attrs(attrs: dict[str, Any], view: views.View, request: request.Request, instance) -> dict[str, Any]: +def validate_team_attrs( + attrs: dict[str, Any], view: TeamAndOrgViewSetMixin, request: request.Request, instance +) -> dict[str, Any]: attrs["organization_id"] = view.organization_id if "primary_dashboard" in attrs and attrs["primary_dashboard"].team_id != instance.id: raise exceptions.PermissionDenied("Dashboard does not belong to this team.") if "access_control" in attrs: + assert isinstance(request.user, User) # Only organization-wide admins and above should be allowed to switch the project between open and private # If a project-only admin who is only an org member disabled this it, they wouldn't be able to reenable it org_membership: OrganizationMembership = OrganizationMembership.objects.only("level").get( From 7d71ea4f2f4f828adf2e269177f6e7be3ee2c821 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Wed, 28 Aug 2024 08:14:52 +0100 Subject: [PATCH 12/32] Add test coverage across /projects AND /environments endpoints --- ee/api/test/test_project.py | 48 + ee/api/test/test_team.py | 998 ++++++++-------- posthog/api/project.py | 7 +- posthog/api/routing.py | 2 +- posthog/api/team.py | 9 +- posthog/api/test/test_project.py | 11 + posthog/api/test/test_team.py | 1902 +++++++++++++++--------------- posthog/models/team/team.py | 9 +- 8 files changed, 1539 insertions(+), 1447 deletions(-) create mode 100644 ee/api/test/test_project.py create mode 100644 posthog/api/test/test_project.py diff --git a/ee/api/test/test_project.py b/ee/api/test/test_project.py new file mode 100644 index 0000000000000..5061bad71d32e --- /dev/null +++ b/ee/api/test/test_project.py @@ -0,0 +1,48 @@ +from ee.api.test.test_team import team_enterprise_api_test_factory +from posthog.api.test.test_team import EnvironmentToProjectRewriteClient +from posthog.models.organization import Organization, OrganizationMembership +from posthog.models.project import Project +from posthog.models.team.team import Team + + +class TestProjectEnterpriseAPI(team_enterprise_api_test_factory()): + """ + We inherit from TestTeamEnterpriseAPI, as previously /api/projects/ referred to the Team model, which used to mean "project". + Now as Team means "environment" and Project is separate, we must ensure backward compatibility of /api/projects/. + At the same time, this class is where we can continue adding `Project`-specific API tests. + """ + + client_class = EnvironmentToProjectRewriteClient + + def test_user_create_project_for_org_via_url(self): + # Set both current and new org to high enough membership level + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + + current_org, _, _ = Organization.objects.bootstrap(self.user, name="other_org") + other_org = self.organization # Bootstrapping above sets it to the current org + assert Team.objects.count() == 2 + assert Project.objects.count() == 2 + + assert current_org.id == self.user.current_organization_id + response = self.client.post(f"/api/organizations/{current_org.id}/projects/", {"name": "Via current org"}) + self.assertEqual(response.status_code, 201) + assert response.json()["organization"] == str(current_org.id) + assert Team.objects.count() == 3 + assert Project.objects.count() == 3 + + assert other_org.id != self.user.current_organization_id + response = self.client.post(f"/api/organizations/{other_org.id}/projects/", {"name": "Via path org"}) + self.assertEqual(response.status_code, 201, msg=response.json()) + assert response.json()["organization"] == str(other_org.id) + assert Team.objects.count() == 4 + assert Project.objects.count() == 4 + + def test_user_cannot_create_project_in_org_without_access(self): + _, _, _ = Organization.objects.bootstrap(self.user, name="other_org") + other_org = self.organization # Bootstrapping above sets it to the current org + + assert other_org.id != self.user.current_organization_id + response = self.client.post(f"/api/organizations/{other_org.id}/projects/", {"name": "Via path org"}) + self.assertEqual(response.status_code, 403, msg=response.json()) + assert response.json() == self.permission_denied_response("Your organization access level is insufficient.") diff --git a/ee/api/test/test_team.py b/ee/api/test/test_team.py index 9ace30a718798..860bdfe87a452 100644 --- a/ee/api/test/test_team.py +++ b/ee/api/test/test_team.py @@ -8,519 +8,503 @@ from ee.api.test.base import APILicensedTest from ee.models.explicit_team_membership import ExplicitTeamMembership from posthog.models.organization import Organization, OrganizationMembership +from posthog.models.project import Project from posthog.models.team import Team from posthog.models.user import User from posthog.test.base import FuzzyInt -class TestProjectEnterpriseAPI(APILicensedTest): - CLASS_DATA_LEVEL_SETUP = False - - # Creating projects - - def test_create_project(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - response = self.client.post("/api/projects/", {"name": "Test"}) - self.assertEqual(response.status_code, 201) - self.assertEqual(Team.objects.count(), 2) - response_data = response.json() - self.assertDictContainsSubset( - { - "name": "Test", - "access_control": False, - "effective_membership_level": OrganizationMembership.Level.ADMIN, - }, - response_data, - ) - self.assertEqual(self.organization.teams.count(), 2) - - def test_non_admin_cannot_create_project(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - count = Team.objects.count() - response = self.client.post("/api/projects/", {"name": "Test"}) - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertEqual(Team.objects.count(), count) - self.assertEqual( - response.json(), - self.permission_denied_response("Your organization access level is insufficient."), - ) - - def test_create_demo_project(self, *args): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - response = self.client.post("/api/projects/", {"name": "Hedgebox", "is_demo": True}) - self.assertEqual(Team.objects.count(), 2) - self.assertEqual(response.status_code, 201) - response_data = response.json() - self.assertDictContainsSubset( - { - "name": "Hedgebox", - "access_control": False, - "effective_membership_level": OrganizationMembership.Level.ADMIN, - }, - response_data, - ) - self.assertEqual(self.organization.teams.count(), 2) - - def test_create_two_demo_projects(self, *args): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - response = self.client.post("/api/projects/", {"name": "Hedgebox", "is_demo": True}) - self.assertEqual(Team.objects.count(), 2) - self.assertEqual(response.status_code, 201) - response_data = response.json() - self.assertDictContainsSubset( - { - "name": "Hedgebox", - "access_control": False, - "effective_membership_level": OrganizationMembership.Level.ADMIN, - }, - response_data, - ) - response_2 = self.client.post("/api/projects/", {"name": "Hedgebox", "is_demo": True}) - self.assertEqual(Team.objects.count(), 2) - response_2_data = response_2.json() - self.assertDictContainsSubset( - { - "type": "authentication_error", - "code": "permission_denied", - "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments.", - }, - response_2_data, - ) - self.assertEqual(self.organization.teams.count(), 2) - - def test_user_that_does_not_belong_to_an_org_cannot_create_a_project(self): - user = User.objects.create(email="no_org@posthog.com") - self.client.force_login(user) - - response = self.client.post("/api/projects/", {"name": "Test"}) - self.assertEqual(response.status_code, HTTP_404_NOT_FOUND, response.content) - self.assertEqual( - response.json(), - { - "type": "invalid_request", - "code": "not_found", - "detail": "You need to belong to an organization.", - "attr": None, - }, - ) - - def test_user_create_project_for_org_via_url(self): - # Set both current and new org to high enough membership level - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - - current_org, _, _ = Organization.objects.bootstrap(self.user, name="other_org") - other_org = self.organization # Bootstrapping above sets it to the current org - - assert current_org.id == self.user.current_organization_id - response = self.client.post(f"/api/organizations/{current_org.id}/projects/", {"name": "Via current org"}) - self.assertEqual(response.status_code, 201) - assert response.json()["organization"] == str(current_org.id) - - assert other_org.id != self.user.current_organization_id - response = self.client.post(f"/api/organizations/{other_org.id}/projects/", {"name": "Via path org"}) - self.assertEqual(response.status_code, 201, msg=response.json()) - assert response.json()["organization"] == str(other_org.id) - - def test_user_cannot_create_project_in_org_without_access(self): - _, _, _ = Organization.objects.bootstrap(self.user, name="other_org") - other_org = self.organization # Bootstrapping above sets it to the current org - - assert other_org.id != self.user.current_organization_id - response = self.client.post(f"/api/organizations/{other_org.id}/projects/", {"name": "Via path org"}) - self.assertEqual(response.status_code, 403, msg=response.json()) - assert response.json() == self.permission_denied_response("Your organization access level is insufficient.") - - # Deleting projects - - def test_delete_team_as_org_admin_allowed(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - response = self.client.delete(f"/api/projects/{self.team.id}") - self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) - self.assertEqual(Team.objects.filter(organization=self.organization).count(), 0) - - def test_delete_team_as_org_member_forbidden(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - response = self.client.delete(f"/api/projects/{self.team.id}") - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertEqual(Team.objects.filter(organization=self.organization).count(), 1) - - def test_delete_open_team_as_org_member_but_project_admin_forbidden(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - ExplicitTeamMembership.objects.create( - team=self.team, - parent_membership=self.organization_membership, - level=ExplicitTeamMembership.Level.ADMIN, - ) - response = self.client.delete(f"/api/projects/{self.team.id}") - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertEqual(Team.objects.filter(organization=self.organization).count(), 1) - - def test_delete_private_team_as_org_member_but_project_admin_allowed(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - self.team.access_control = True - self.team.save() - ExplicitTeamMembership.objects.create( - team=self.team, - parent_membership=self.organization_membership, - level=ExplicitTeamMembership.Level.ADMIN, - ) - response = self.client.delete(f"/api/projects/{self.team.id}") - self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) - self.assertEqual(Team.objects.filter(organization=self.organization).count(), 0) - - def test_delete_second_team_as_org_admin_allowed(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - team = Team.objects.create(organization=self.organization) - response = self.client.delete(f"/api/projects/{team.id}") - self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) - self.assertEqual(Team.objects.filter(organization=self.organization).count(), 1) - - def test_no_delete_team_not_administrating_organization(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - team = Team.objects.create(organization=self.organization) - response = self.client.delete(f"/api/projects/{team.id}") - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertEqual(Team.objects.filter(organization=self.organization).count(), 2) - - def test_no_delete_team_not_belonging_to_organization(self): - team_1 = Organization.objects.bootstrap(None)[2] - response = self.client.delete(f"/api/projects/{team_1.id}") - self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) - self.assertTrue(Team.objects.filter(id=team_1.id).exists()) - organization, _, _ = User.objects.bootstrap("X", "someone@x.com", "qwerty", "Someone") - team_2 = Team.objects.create(organization=organization) - response = self.client.delete(f"/api/projects/{team_2.id}") - self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) - self.assertEqual(Team.objects.filter(organization=organization).count(), 2) - - # Updating projects - - def test_rename_project_as_org_member_allowed(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - - response = self.client.patch(f"/api/projects/@current/", {"name": "Erinaceus europaeus"}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_200_OK) - self.assertEqual(self.team.name, "Erinaceus europaeus") - - def test_rename_private_project_as_org_member_forbidden(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - self.team.access_control = True - self.team.save() - - response = self.client.patch(f"/api/projects/@current/", {"name": "Acherontia atropos"}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertEqual(self.team.name, "Default project") - - def test_rename_private_project_current_as_org_outsider_forbidden(self): - self.organization_membership.delete() - - response = self.client.patch(f"/api/projects/@current/", {"name": "Acherontia atropos"}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) - - def test_rename_private_project_id_as_org_outsider_forbidden(self): - self.organization_membership.delete() - - response = self.client.patch(f"/api/projects/{self.team.id}/", {"name": "Acherontia atropos"}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) - - def test_rename_private_project_as_org_member_and_project_member_allowed(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - self.team.access_control = True - self.team.save() - ExplicitTeamMembership.objects.create( - team=self.team, - parent_membership=self.organization_membership, - level=ExplicitTeamMembership.Level.MEMBER, - ) - - response = self.client.patch(f"/api/projects/@current/", {"name": "Acherontia atropos"}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_200_OK) - self.assertEqual(self.team.name, "Acherontia atropos") - - def test_enable_access_control_as_org_member_forbidden(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - - response = self.client.patch(f"/api/projects/@current/", {"access_control": True}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertFalse(self.team.access_control) - - def test_enable_access_control_as_org_admin_allowed(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - - response = self.client.patch(f"/api/projects/@current/", {"access_control": True}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_200_OK) - self.assertTrue(self.team.access_control) - - def test_enable_access_control_as_org_member_and_project_admin_forbidden(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - ExplicitTeamMembership.objects.create( - team=self.team, - parent_membership=self.organization_membership, - level=ExplicitTeamMembership.Level.ADMIN, - ) - - response = self.client.patch(f"/api/projects/@current/", {"access_control": True}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertFalse(self.team.access_control) - - def test_disable_access_control_as_org_member_forbidden(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - self.team.access_control = True - self.team.save() - - response = self.client.patch(f"/api/projects/@current/", {"access_control": False}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertTrue(self.team.access_control) - - def test_disable_access_control_as_org_member_and_project_admin_forbidden(self): - # Only org-wide admins+ should be allowed to make the project open, - # because if a project-specific admin who is only an org member did it, they wouldn't be able to reenable it - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - self.team.access_control = True - self.team.save() - ExplicitTeamMembership.objects.create( - team=self.team, - parent_membership=self.organization_membership, - level=ExplicitTeamMembership.Level.ADMIN, - ) - - response = self.client.patch(f"/api/projects/@current/", {"access_control": False}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertTrue(self.team.access_control) - - def test_disable_access_control_as_org_admin_allowed(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - self.team.access_control = True - self.team.save() - - response = self.client.patch(f"/api/projects/@current/", {"access_control": False}) - self.team.refresh_from_db() - - self.assertEqual(response.status_code, HTTP_200_OK) - self.assertFalse(self.team.access_control) - - def test_can_update_and_retrieve_person_property_names_excluded_from_correlation(self): - response = self.client.patch( - f"/api/projects/@current/", - {"correlation_config": {"excluded_person_property_names": ["$os"]}}, - ) - self.assertEqual(response.status_code, HTTP_200_OK) - - response = self.client.get(f"/api/projects/@current/") - self.assertEqual(response.status_code, HTTP_200_OK) - - response_data = response.json() - - self.assertDictContainsSubset( - {"correlation_config": {"excluded_person_property_names": ["$os"]}}, - response_data, - ) - - # Fetching projects - - def test_fetch_team_as_org_admin_works(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - - response = self.client.get(f"/api/projects/@current/") - response_data = response.json() - - self.assertEqual(response.status_code, HTTP_200_OK) - self.assertDictContainsSubset( - { - "name": "Default project", - "access_control": False, - "effective_membership_level": OrganizationMembership.Level.ADMIN, - }, - response_data, - ) - - def test_fetch_team_as_org_member_works(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - - response = self.client.get(f"/api/projects/@current/") - response_data = response.json() - - self.assertEqual(response.status_code, HTTP_200_OK) - self.assertDictContainsSubset( - { - "name": "Default project", - "access_control": False, - "effective_membership_level": OrganizationMembership.Level.MEMBER, - }, - response_data, - ) - - def test_fetch_private_team_as_org_member(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - self.team.access_control = True - self.team.save() - - response = self.client.get(f"/api/projects/@current/") - response_data = response.json() - - self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) - self.assertEqual( - self.permission_denied_response("You don't have sufficient permissions in the project."), - response_data, - ) - - def test_fetch_private_team_as_org_member_and_project_member(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - self.team.access_control = True - self.team.save() - ExplicitTeamMembership.objects.create( - team=self.team, - parent_membership=self.organization_membership, - level=ExplicitTeamMembership.Level.MEMBER, - ) - - response = self.client.get(f"/api/projects/@current/") - response_data = response.json() - - self.assertEqual(response.status_code, HTTP_200_OK) - self.assertDictContainsSubset( - { - "name": "Default project", - "access_control": True, - "effective_membership_level": OrganizationMembership.Level.MEMBER, - }, - response_data, - ) - - def test_fetch_private_team_as_org_member_and_project_admin(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - self.team.access_control = True - self.team.save() - ExplicitTeamMembership.objects.create( - team=self.team, - parent_membership=self.organization_membership, - level=ExplicitTeamMembership.Level.ADMIN, - ) - - response = self.client.get(f"/api/projects/@current/") - response_data = response.json() - - self.assertEqual(response.status_code, HTTP_200_OK) - self.assertDictContainsSubset( - { - "name": "Default project", - "access_control": True, - "effective_membership_level": OrganizationMembership.Level.ADMIN, - }, - response_data, - ) - - def test_fetch_team_as_org_outsider(self): - self.organization_membership.delete() - response = self.client.get(f"/api/projects/@current/") - response_data = response.json() - - self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) - self.assertEqual(self.not_found_response(), response_data) - - def test_fetch_nonexistent_team(self): - response = self.client.get(f"/api/projects/234444/") - response_data = response.json() - - self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) - self.assertEqual(self.not_found_response(), response_data) - - def test_list_teams_restricted_ones_hidden(self): - self.organization_membership.level = OrganizationMembership.Level.MEMBER - self.organization_membership.save() - Team.objects.create( - organization=self.organization, - name="Other", - access_control=True, - ) - - # The other team should not be returned as it's restricted for the logged-in user - projects_response = self.client.get(f"/api/projects/") - - # 9 (above): - with self.assertNumQueries(FuzzyInt(9, 10)): - current_org_response = self.client.get(f"/api/organizations/{self.organization.id}/") - - self.assertEqual(projects_response.status_code, HTTP_200_OK) - self.assertEqual( - projects_response.json().get("results"), - [ +def team_enterprise_api_test_factory(): + class TestTeamEnterpriseAPI(APILicensedTest): + CLASS_DATA_LEVEL_SETUP = False + + # Creating projects + + def test_create_team(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + self.assertEqual(Team.objects.count(), 1) + self.assertEqual(Project.objects.count(), 1) + response = self.client.post("/api/environments/", {"name": "Test"}) + self.assertEqual(response.status_code, 201) + self.assertEqual(Team.objects.count(), 2) + self.assertEqual(Project.objects.count(), 2) + response_data = response.json() + self.assertDictContainsSubset( + { + "name": "Test", + "access_control": False, + "effective_membership_level": OrganizationMembership.Level.ADMIN, + }, + response_data, + ) + self.assertEqual(self.organization.teams.count(), 2) + + def test_non_admin_cannot_create_team(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + count = Team.objects.count() + response = self.client.post("/api/environments/", {"name": "Test"}) + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertEqual(Team.objects.count(), count) + self.assertEqual( + response.json(), + self.permission_denied_response("Your organization access level is insufficient."), + ) + + def test_create_demo_team(self, *args): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + response = self.client.post("/api/environments/", {"name": "Hedgebox", "is_demo": True}) + self.assertEqual(Team.objects.count(), 2) + self.assertEqual(response.status_code, 201) + response_data = response.json() + self.assertDictContainsSubset( { - "id": self.team.id, - "uuid": str(self.team.uuid), - "organization": str(self.organization.id), - "api_token": self.team.api_token, - "name": self.team.name, - "completed_snippet_onboarding": False, - "has_completed_onboarding_for": {"product_analytics": True}, - "ingested_event": False, - "is_demo": False, - "timezone": "UTC", + "name": "Hedgebox", "access_control": False, - } - ], - ) - self.assertEqual(current_org_response.status_code, HTTP_200_OK) - self.assertEqual( - current_org_response.json().get("teams"), - [ + "effective_membership_level": OrganizationMembership.Level.ADMIN, + }, + response_data, + ) + self.assertEqual(self.organization.teams.count(), 2) + + def test_create_two_demo_teams(self, *args): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + response = self.client.post("/api/environments/", {"name": "Hedgebox", "is_demo": True}) + self.assertEqual(Team.objects.count(), 2) + self.assertEqual(response.status_code, 201) + response_data = response.json() + self.assertDictContainsSubset( { - "id": self.team.id, - "uuid": str(self.team.uuid), - "organization": str(self.organization.id), - "api_token": self.team.api_token, - "name": self.team.name, - "completed_snippet_onboarding": False, - "has_completed_onboarding_for": {"product_analytics": True}, - "ingested_event": False, - "is_demo": False, - "timezone": "UTC", + "name": "Hedgebox", "access_control": False, - } - ], - ) + "effective_membership_level": OrganizationMembership.Level.ADMIN, + }, + response_data, + ) + response_2 = self.client.post("/api/environments/", {"name": "Hedgebox", "is_demo": True}) + self.assertEqual(Team.objects.count(), 2) + response_2_data = response_2.json() + self.assertDictContainsSubset( + { + "type": "authentication_error", + "code": "permission_denied", + "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments.", + }, + response_2_data, + ) + self.assertEqual(self.organization.teams.count(), 2) + + def test_user_that_does_not_belong_to_an_org_cannot_create_a_team(self): + user = User.objects.create(email="no_org@posthog.com") + self.client.force_login(user) + + response = self.client.post("/api/environments/", {"name": "Test"}) + self.assertEqual(response.status_code, HTTP_404_NOT_FOUND, response.content) + self.assertEqual( + response.json(), + { + "type": "invalid_request", + "code": "not_found", + "detail": "You need to belong to an organization.", + "attr": None, + }, + ) + + # Deleting projects + + def test_delete_team_as_org_admin_allowed(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + response = self.client.delete(f"/api/environments/{self.team.id}") + self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) + self.assertEqual(Team.objects.filter(organization=self.organization).count(), 0) + + def test_delete_team_as_org_member_forbidden(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + response = self.client.delete(f"/api/environments/{self.team.id}") + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertEqual(Team.objects.filter(organization=self.organization).count(), 1) + + def test_delete_open_team_as_org_member_but_team_admin_forbidden(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + ExplicitTeamMembership.objects.create( + team=self.team, + parent_membership=self.organization_membership, + level=ExplicitTeamMembership.Level.ADMIN, + ) + response = self.client.delete(f"/api/environments/{self.team.id}") + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertEqual(Team.objects.filter(organization=self.organization).count(), 1) + + def test_delete_private_team_as_org_member_but_team_admin_allowed(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + self.team.access_control = True + self.team.save() + ExplicitTeamMembership.objects.create( + team=self.team, + parent_membership=self.organization_membership, + level=ExplicitTeamMembership.Level.ADMIN, + ) + response = self.client.delete(f"/api/environments/{self.team.id}") + self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) + self.assertEqual(Team.objects.filter(organization=self.organization).count(), 0) + + def test_delete_second_team_as_org_admin_allowed(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + team = Team.objects.create(organization=self.organization) + response = self.client.delete(f"/api/environments/{team.id}") + self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) + self.assertEqual(Team.objects.filter(organization=self.organization).count(), 1) + + def test_no_delete_team_not_administrating_organization(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + team = Team.objects.create(organization=self.organization) + response = self.client.delete(f"/api/environments/{team.id}") + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertEqual(Team.objects.filter(organization=self.organization).count(), 2) + + def test_no_delete_team_not_belonging_to_organization(self): + team_1 = Organization.objects.bootstrap(None)[2] + response = self.client.delete(f"/api/environments/{team_1.id}") + self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) + self.assertTrue(Team.objects.filter(id=team_1.id).exists()) + organization, _, _ = User.objects.bootstrap("X", "someone@x.com", "qwerty", "Someone") + team_2 = Team.objects.create(organization=organization) + response = self.client.delete(f"/api/environments/{team_2.id}") + self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) + self.assertEqual(Team.objects.filter(organization=organization).count(), 2) + + # Updating projects + + def test_rename_team_as_org_member_allowed(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + + response = self.client.patch(f"/api/environments/@current/", {"name": "Erinaceus europaeus"}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(self.team.name, "Erinaceus europaeus") + + def test_rename_private_team_as_org_member_forbidden(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + self.team.access_control = True + self.team.save() + + response = self.client.patch(f"/api/environments/@current/", {"name": "Acherontia atropos"}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertEqual(self.team.name, "Default project") + + def test_rename_private_team_current_as_org_outsider_forbidden(self): + self.organization_membership.delete() + + response = self.client.patch(f"/api/environments/@current/", {"name": "Acherontia atropos"}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) + + def test_rename_private_team_id_as_org_outsider_forbidden(self): + self.organization_membership.delete() + + response = self.client.patch(f"/api/environments/{self.team.id}/", {"name": "Acherontia atropos"}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) + + def test_rename_private_team_as_org_member_and_team_member_allowed(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + self.team.access_control = True + self.team.save() + ExplicitTeamMembership.objects.create( + team=self.team, + parent_membership=self.organization_membership, + level=ExplicitTeamMembership.Level.MEMBER, + ) + + response = self.client.patch(f"/api/environments/@current/", {"name": "Acherontia atropos"}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(self.team.name, "Acherontia atropos") + + def test_enable_access_control_as_org_member_forbidden(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + + response = self.client.patch(f"/api/environments/@current/", {"access_control": True}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertFalse(self.team.access_control) + + def test_enable_access_control_as_org_admin_allowed(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + + response = self.client.patch(f"/api/environments/@current/", {"access_control": True}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertTrue(self.team.access_control) + + def test_enable_access_control_as_org_member_and_team_admin_forbidden(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + ExplicitTeamMembership.objects.create( + team=self.team, + parent_membership=self.organization_membership, + level=ExplicitTeamMembership.Level.ADMIN, + ) + + response = self.client.patch(f"/api/environments/@current/", {"access_control": True}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertFalse(self.team.access_control) + + def test_disable_access_control_as_org_member_forbidden(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + self.team.access_control = True + self.team.save() + + response = self.client.patch(f"/api/environments/@current/", {"access_control": False}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertTrue(self.team.access_control) + + def test_disable_access_control_as_org_member_and_team_admin_forbidden(self): + # Only org-wide admins+ should be allowed to make the project open, + # because if a project-specific admin who is only an org member did it, they wouldn't be able to reenable it + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + self.team.access_control = True + self.team.save() + ExplicitTeamMembership.objects.create( + team=self.team, + parent_membership=self.organization_membership, + level=ExplicitTeamMembership.Level.ADMIN, + ) + + response = self.client.patch(f"/api/environments/@current/", {"access_control": False}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertTrue(self.team.access_control) + + def test_disable_access_control_as_org_admin_allowed(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + self.team.access_control = True + self.team.save() + + response = self.client.patch(f"/api/environments/@current/", {"access_control": False}) + self.team.refresh_from_db() + + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertFalse(self.team.access_control) + + def test_can_update_and_retrieve_person_property_names_excluded_from_correlation(self): + response = self.client.patch( + f"/api/environments/@current/", + {"correlation_config": {"excluded_person_property_names": ["$os"]}}, + ) + self.assertEqual(response.status_code, HTTP_200_OK) + + response = self.client.get(f"/api/environments/@current/") + self.assertEqual(response.status_code, HTTP_200_OK) + + response_data = response.json() + + self.assertDictContainsSubset( + {"correlation_config": {"excluded_person_property_names": ["$os"]}}, + response_data, + ) + + # Fetching projects + + def test_fetch_team_as_org_admin_works(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + + response = self.client.get(f"/api/environments/@current/") + response_data = response.json() + + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertDictContainsSubset( + { + "name": "Default project", + "access_control": False, + "effective_membership_level": OrganizationMembership.Level.ADMIN, + }, + response_data, + ) + + def test_fetch_team_as_org_member_works(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + + response = self.client.get(f"/api/environments/@current/") + response_data = response.json() + + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertDictContainsSubset( + { + "name": "Default project", + "access_control": False, + "effective_membership_level": OrganizationMembership.Level.MEMBER, + }, + response_data, + ) + + def test_fetch_private_team_as_org_member(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + self.team.access_control = True + self.team.save() + + response = self.client.get(f"/api/environments/@current/") + response_data = response.json() + + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + self.assertEqual( + self.permission_denied_response("You don't have sufficient permissions in the project."), + response_data, + ) + + def test_fetch_private_team_as_org_member_and_team_member(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + self.team.access_control = True + self.team.save() + ExplicitTeamMembership.objects.create( + team=self.team, + parent_membership=self.organization_membership, + level=ExplicitTeamMembership.Level.MEMBER, + ) + + response = self.client.get(f"/api/environments/@current/") + response_data = response.json() + + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertDictContainsSubset( + { + "name": "Default project", + "access_control": True, + "effective_membership_level": OrganizationMembership.Level.MEMBER, + }, + response_data, + ) + + def test_fetch_private_team_as_org_member_and_team_admin(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + self.team.access_control = True + self.team.save() + ExplicitTeamMembership.objects.create( + team=self.team, + parent_membership=self.organization_membership, + level=ExplicitTeamMembership.Level.ADMIN, + ) + + response = self.client.get(f"/api/environments/@current/") + response_data = response.json() + + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertDictContainsSubset( + { + "name": "Default project", + "access_control": True, + "effective_membership_level": OrganizationMembership.Level.ADMIN, + }, + response_data, + ) + + def test_fetch_team_as_org_outsider(self): + self.organization_membership.delete() + response = self.client.get(f"/api/environments/@current/") + response_data = response.json() + + self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) + self.assertEqual(self.not_found_response(), response_data) + + def test_fetch_nonexistent_team(self): + response = self.client.get(f"/api/environments/234444/") + response_data = response.json() + + self.assertEqual(response.status_code, HTTP_404_NOT_FOUND) + self.assertEqual(self.not_found_response(), response_data) + + def test_list_teams_restricted_ones_hidden(self): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + Team.objects.create( + organization=self.organization, + name="Other", + access_control=True, + ) + + # The other team should not be returned as it's restricted for the logged-in user + projects_response = self.client.get(f"/api/environments/") + + # 9 (above): + with self.assertNumQueries(FuzzyInt(9, 10)): + current_org_response = self.client.get(f"/api/organizations/{self.organization.id}/") + + self.assertEqual(projects_response.status_code, HTTP_200_OK) + self.assertEqual( + projects_response.json().get("results"), + [ + { + "id": self.team.id, + "uuid": str(self.team.uuid), + "organization": str(self.organization.id), + "api_token": self.team.api_token, + "name": self.team.name, + "completed_snippet_onboarding": False, + "has_completed_onboarding_for": {"product_analytics": True}, + "ingested_event": False, + "is_demo": False, + "timezone": "UTC", + "access_control": False, + } + ], + ) + self.assertEqual(current_org_response.status_code, HTTP_200_OK) + self.assertEqual( + current_org_response.json().get("teams"), + [ + { + "id": self.team.id, + "uuid": str(self.team.uuid), + "organization": str(self.organization.id), + "api_token": self.team.api_token, + "name": self.team.name, + "completed_snippet_onboarding": False, + "has_completed_onboarding_for": {"product_analytics": True}, + "ingested_event": False, + "is_demo": False, + "timezone": "UTC", + "access_control": False, + } + ], + ) + + return TestTeamEnterpriseAPI + + +class TestTeamEnterpriseAPI(team_enterprise_api_test_factory()): + pass diff --git a/posthog/api/project.py b/posthog/api/project.py index e08a35cac0838..aad224ffb1c9e 100644 --- a/posthog/api/project.py +++ b/posthog/api/project.py @@ -198,7 +198,6 @@ def validate(self, attrs: Any) -> Any: def create(self, validated_data: dict[str, Any], **kwargs) -> Project: serializers.raise_errors_on_nested_writes("create", self, validated_data) request = self.context["request"] - organization = self.context["view"].organization # Use the org we used to validate permissions if "week_start_day" not in validated_data: country_code = get_geoip_properties(get_ip_address(request)).get("$geoip_country_code", None) @@ -212,14 +211,16 @@ def create(self, validated_data: dict[str, Any], **kwargs) -> Project: for field_name in validated_data.copy(): # Copy to avoid iterating over a changing dict if field_name in self.Meta.team_passthrough_fields: team_fields[field_name] = validated_data.pop(field_name) - project, team = Project.objects.create_with_team(**validated_data, team_fields=team_fields) + project, team = Project.objects.create_with_team( + organization_id=self.context["view"].organization_id, **validated_data, team_fields=team_fields + ) request.user.current_team = team request.user.team = request.user.current_team # Update cached property request.user.save() log_activity( - organization_id=organization.id, + organization_id=team.organization_id, team_id=team.pk, user=request.user, was_impersonated=is_impersonated_session(request), diff --git a/posthog/api/routing.py b/posthog/api/routing.py index b357ccf9ffa89..0f1784b3ac4a2 100644 --- a/posthog/api/routing.py +++ b/posthog/api/routing.py @@ -46,7 +46,7 @@ def __init__(self, *args, **kwargs): # NOTE: Previously known as the StructuredViewSetMixin # IMPORTANT: Almost all viewsets should inherit from this mixin. It should be the first thing it inherits from to ensure # that typing works as expected -class TeamAndOrgViewSetMixin(_GenericViewSet): +class TeamAndOrgViewSetMixin(_GenericViewSet): # TODO: Rename to include "Env" in name # This flag disables nested routing handling, reverting to the old request.user.team behavior # Allows for a smoother transition from the old flat API structure to the newer nested one param_derived_from_user_current_team: Optional[Literal["team_id", "project_id"]] = None diff --git a/posthog/api/team.py b/posthog/api/team.py index 3755ad58078f9..9a10412a53db9 100644 --- a/posthog/api/team.py +++ b/posthog/api/team.py @@ -46,7 +46,7 @@ from posthog.utils import get_ip_address, get_week_start_for_country_code -class PremiumMultiProjectPermissions(BasePermission): +class PremiumMultiProjectPermissions(BasePermission): # TODO: Rename to include "Env" in name """Require user to have all necessary premium features on their plan for create access to the endpoint.""" message = "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments." @@ -276,7 +276,6 @@ def validate(self, attrs: Any) -> Any: def create(self, validated_data: dict[str, Any], **kwargs) -> Team: serializers.raise_errors_on_nested_writes("create", self, validated_data) request = self.context["request"] - organization = self.context["view"].organization # Use the org we used to validate permissions if "week_start_day" not in validated_data: country_code = get_geoip_properties(get_ip_address(request)).get("$geoip_country_code", None) @@ -286,14 +285,14 @@ def create(self, validated_data: dict[str, Any], **kwargs) -> Team: # but ClickHouse doesn't support Saturday as the first day of the week, so we fall back to Sunday validated_data["week_start_day"] = 1 if week_start_day_for_user_ip_location == 1 else 0 - team = Team.objects.create_with_data(**validated_data) + team = Team.objects.create_with_data(organization=self.context["view"].organization, **validated_data) request.user.current_team = team request.user.team = request.user.current_team # Update cached property request.user.save() log_activity( - organization_id=organization.id, + organization_id=team.organization_id, team_id=team.pk, user=request.user, was_impersonated=is_impersonated_session(request), @@ -537,8 +536,6 @@ class RootTeamViewSet(TeamViewSet): def validate_team_attrs( attrs: dict[str, Any], view: TeamAndOrgViewSetMixin, request: request.Request, instance ) -> dict[str, Any]: - attrs["organization_id"] = view.organization_id - if "primary_dashboard" in attrs and attrs["primary_dashboard"].team_id != instance.id: raise exceptions.PermissionDenied("Dashboard does not belong to this team.") diff --git a/posthog/api/test/test_project.py b/posthog/api/test/test_project.py new file mode 100644 index 0000000000000..144cc49002c0b --- /dev/null +++ b/posthog/api/test/test_project.py @@ -0,0 +1,11 @@ +from posthog.api.test.test_team import EnvironmentToProjectRewriteClient, team_api_test_factory + + +class TestProjectAPI(team_api_test_factory()): + """ + We inherit from TestTeamAPI, as previously /api/projects/ referred to the Team model, which used to mean "project". + Now as Team means "environment" and Project is separate, we must ensure backward compatibility of /api/projects/. + At the same time, this class is where we can continue adding `Project`-specific API tests. + """ + + client_class = EnvironmentToProjectRewriteClient diff --git a/posthog/api/test/test_team.py b/posthog/api/test/test_team.py index cfd8b125218cb..1cce0f880542d 100644 --- a/posthog/api/test/test_team.py +++ b/posthog/api/test/test_team.py @@ -4,12 +4,11 @@ from unittest import mock from unittest.mock import ANY, MagicMock, call, patch -from asgiref.sync import sync_to_async from django.core.cache import cache from django.http import HttpResponse from freezegun import freeze_time from parameterized import parameterized -from rest_framework import status +from rest_framework import status, test from temporalio.service import RPCError from posthog.api.test.batch_exports.conftest import start_test_worker @@ -26,1013 +25,1067 @@ from posthog.test.base import APIBaseTest -class TestTeamAPI(APIBaseTest): - def _assert_activity_log(self, expected: list[dict], team_id: Optional[int] = None) -> None: - if not team_id: - team_id = self.team.pk - - starting_log_response = self.client.get(f"/api/projects/{team_id}/activity") - assert starting_log_response.status_code == 200, starting_log_response.json() - assert starting_log_response.json()["results"] == expected - - def _assert_organization_activity_log(self, expected: list[dict]) -> None: - starting_log_response = self.client.get(f"/api/organizations/{self.organization.pk}/activity") - assert starting_log_response.status_code == 200, starting_log_response.json() - assert starting_log_response.json()["results"] == expected - - def _assert_activity_log_is_empty(self) -> None: - self._assert_activity_log([]) - - def test_list_projects(self): - response = self.client.get("/api/projects/") - self.assertEqual(response.status_code, status.HTTP_200_OK) - - # Listing endpoint always uses the simplified serializer - response_data = response.json() - self.assertEqual(len(response_data["results"]), 1) - self.assertEqual(response_data["results"][0]["name"], self.team.name) - self.assertNotIn("test_account_filters", response_data["results"][0]) - self.assertNotIn("data_attributes", response_data["results"][0]) - - # TODO: These assertions will no longer make sense when we fully remove these attributes from the model - self.assertNotIn("event_names", response_data["results"][0]) - self.assertNotIn("event_properties", response_data["results"][0]) - self.assertNotIn("event_properties_numerical", response_data["results"][0]) - - def test_retrieve_project(self): - response = self.client.get("/api/projects/@current/") - self.assertEqual(response.status_code, status.HTTP_200_OK) - - response_data = response.json() - self.assertEqual(response_data["name"], self.team.name) - self.assertEqual(response_data["timezone"], "UTC") - self.assertEqual(response_data["is_demo"], False) - self.assertEqual(response_data["slack_incoming_webhook"], self.team.slack_incoming_webhook) - self.assertEqual(response_data["has_group_types"], False) - self.assertEqual( - response_data["person_on_events_querying_enabled"], - get_instance_setting("PERSON_ON_EVENTS_ENABLED") or get_instance_setting("PERSON_ON_EVENTS_V2_ENABLED"), - ) +def team_api_test_factory(): + class TestTeamAPI(APIBaseTest): + """Tests for /api/environments/.""" + + def _assert_activity_log(self, expected: list[dict], team_id: Optional[int] = None) -> None: + if not team_id: + team_id = self.team.pk + + starting_log_response = self.client.get(f"/api/environments/{team_id}/activity") + assert starting_log_response.status_code == 200, starting_log_response.json() + assert starting_log_response.json()["results"] == expected + + def _assert_organization_activity_log(self, expected: list[dict]) -> None: + starting_log_response = self.client.get(f"/api/organizations/{self.organization.pk}/activity") + assert starting_log_response.status_code == 200, starting_log_response.json() + assert starting_log_response.json()["results"] == expected + + def _assert_activity_log_is_empty(self) -> None: + self._assert_activity_log([]) + + def test_list_teams(self): + response = self.client.get("/api/environments/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + + # Listing endpoint always uses the simplified serializer + response_data = response.json() + self.assertEqual(len(response_data["results"]), 1) + self.assertEqual(response_data["results"][0]["name"], self.team.name) + self.assertNotIn("test_account_filters", response_data["results"][0]) + self.assertNotIn("data_attributes", response_data["results"][0]) + + # TODO: These assertions will no longer make sense when we fully remove these attributes from the model + self.assertNotIn("event_names", response_data["results"][0]) + self.assertNotIn("event_properties", response_data["results"][0]) + self.assertNotIn("event_properties_numerical", response_data["results"][0]) + + def test_retrieve_team(self): + response = self.client.get("/api/environments/@current/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response_data = response.json() + self.assertEqual(response_data["name"], self.team.name) + self.assertEqual(response_data["timezone"], "UTC") + self.assertEqual(response_data["is_demo"], False) + self.assertEqual(response_data["slack_incoming_webhook"], self.team.slack_incoming_webhook) + self.assertEqual(response_data["has_group_types"], False) + self.assertEqual( + response_data["person_on_events_querying_enabled"], + get_instance_setting("PERSON_ON_EVENTS_ENABLED") or get_instance_setting("PERSON_ON_EVENTS_V2_ENABLED"), + ) - # TODO: These assertions will no longer make sense when we fully remove these attributes from the model - self.assertNotIn("event_names", response_data) - self.assertNotIn("event_properties", response_data) - self.assertNotIn("event_properties_numerical", response_data) - self.assertNotIn("event_names_with_usage", response_data) - self.assertNotIn("event_properties_with_usage", response_data) - - def test_cant_retrieve_project_from_another_org(self): - org = Organization.objects.create(name="New Org") - team = Team.objects.create(organization=org, name="Default project") - - response = self.client.get(f"/api/projects/{team.pk}/") - self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) - self.assertEqual(response.json(), self.not_found_response()) - - @patch("posthog.api.project.get_geoip_properties") - def test_ip_location_is_used_for_new_project_week_day_start(self, get_geoip_properties_mock: MagicMock): - self.organization.available_product_features = [ - {"key": AvailableFeature.ORGANIZATIONS_PROJECTS, "name": AvailableFeature.ORGANIZATIONS_PROJECTS} - ] - self.organization.save() - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - - get_geoip_properties_mock.return_value = {} - response = self.client.post("/api/projects/", {"name": "Test World"}) - self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json()) - self.assertDictContainsSubset({"name": "Test World", "week_start_day": None}, response.json()) - - get_geoip_properties_mock.return_value = {"$geoip_country_code": "US"} - response = self.client.post("/api/projects/", {"name": "Test US"}) - self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json()) - self.assertDictContainsSubset({"name": "Test US", "week_start_day": 0}, response.json()) - - get_geoip_properties_mock.return_value = {"$geoip_country_code": "PL"} - response = self.client.post("/api/projects/", {"name": "Test PL"}) - self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json()) - self.assertDictContainsSubset({"name": "Test PL", "week_start_day": 1}, response.json()) - - get_geoip_properties_mock.return_value = {"$geoip_country_code": "IR"} - response = self.client.post("/api/projects/", {"name": "Test IR"}) - self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json()) - self.assertDictContainsSubset({"name": "Test IR", "week_start_day": 0}, response.json()) - - def test_cant_create_team_without_license_on_selfhosted(self): - with self.is_cloud(False): - response = self.client.post("/api/projects/", {"name": "Test"}) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + # TODO: These assertions will no longer make sense when we fully remove these attributes from the model + self.assertNotIn("event_names", response_data) + self.assertNotIn("event_properties", response_data) + self.assertNotIn("event_properties_numerical", response_data) + self.assertNotIn("event_names_with_usage", response_data) + self.assertNotIn("event_properties_with_usage", response_data) + + def test_cant_retrieve_team_from_another_org(self): + org = Organization.objects.create(name="New Org") + team = Team.objects.create(organization=org, name="Default project") + + response = self.client.get(f"/api/environments/{team.pk}/") + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + self.assertEqual(response.json(), self.not_found_response()) + + @patch("posthog.api.project.get_geoip_properties") + @patch("posthog.api.team.get_geoip_properties") + def test_ip_location_is_used_for_new_team_week_day_start( + self, get_geoip_properties_mock: MagicMock, get_geoip_properties_legacy_endpoint: MagicMock + ): + if self.client_class is EnvironmentToProjectRewriteClient: + get_geoip_properties_mock = get_geoip_properties_legacy_endpoint + + self.organization.available_product_features = [ + {"key": AvailableFeature.ORGANIZATIONS_PROJECTS, "name": AvailableFeature.ORGANIZATIONS_PROJECTS} + ] + self.organization.save() + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + + get_geoip_properties_mock.return_value = {} + response = self.client.post("/api/environments/", {"name": "Test World"}) + self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json()) + self.assertDictContainsSubset({"name": "Test World", "week_start_day": None}, response.json()) + + get_geoip_properties_mock.return_value = {"$geoip_country_code": "US"} + response = self.client.post("/api/environments/", {"name": "Test US"}) + self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json()) + self.assertDictContainsSubset({"name": "Test US", "week_start_day": 0}, response.json()) + + get_geoip_properties_mock.return_value = {"$geoip_country_code": "PL"} + response = self.client.post("/api/environments/", {"name": "Test PL"}) + self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json()) + self.assertDictContainsSubset({"name": "Test PL", "week_start_day": 1}, response.json()) + + get_geoip_properties_mock.return_value = {"$geoip_country_code": "IR"} + response = self.client.post("/api/environments/", {"name": "Test IR"}) + self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.json()) + self.assertDictContainsSubset({"name": "Test IR", "week_start_day": 0}, response.json()) + + def test_cant_create_team_without_license_on_selfhosted(self): + with self.is_cloud(False): + response = self.client.post("/api/environments/", {"name": "Test"}) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(Team.objects.count(), 1) + response = self.client.post("/api/environments/", {"name": "Test"}) + self.assertEqual(Team.objects.count(), 1) + + def test_cant_create_a_second_team_without_license(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() self.assertEqual(Team.objects.count(), 1) - response = self.client.post("/api/projects/", {"name": "Test"}) + + response = self.client.post("/api/environments/", {"name": "Hedgebox", "is_demo": False}) + self.assertEqual(response.status_code, 403) + response_data = response.json() + self.assertDictContainsSubset( + { + "type": "authentication_error", + "code": "permission_denied", + "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments.", + }, + response_data, + ) self.assertEqual(Team.objects.count(), 1) - def test_cant_create_a_second_project_without_license(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - self.assertEqual(Team.objects.count(), 1) - - response = self.client.post("/api/projects/", {"name": "Hedgebox", "is_demo": False}) - self.assertEqual(response.status_code, 403) - response_data = response.json() - self.assertDictContainsSubset( - { - "type": "authentication_error", - "code": "permission_denied", - "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments.", - }, - response_data, - ) - self.assertEqual(Team.objects.count(), 1) - - # another request without the is_demo parameter - response = self.client.post("/api/projects/", {"name": "Hedgebox"}) - self.assertEqual(response.status_code, 403) - response_data = response.json() - self.assertDictContainsSubset( - { - "type": "authentication_error", - "code": "permission_denied", - "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments.", - }, - response_data, - ) - self.assertEqual(Team.objects.count(), 1) + # another request without the is_demo parameter + response = self.client.post("/api/environments/", {"name": "Hedgebox"}) + self.assertEqual(response.status_code, 403) + response_data = response.json() + self.assertDictContainsSubset( + { + "type": "authentication_error", + "code": "permission_denied", + "detail": "You must upgrade your PostHog plan to be able to create and manage multiple projects or environments.", + }, + response_data, + ) + self.assertEqual(Team.objects.count(), 1) - @freeze_time("2022-02-08") - def test_update_project_timezone(self): - self._assert_activity_log_is_empty() + @freeze_time("2022-02-08") + def test_update_team_timezone(self): + self._assert_activity_log_is_empty() + + response = self.client.patch("/api/environments/@current/", {"timezone": "Europe/Lisbon"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response_data = response.json() + self.assertEqual(response_data["name"], self.team.name) + self.assertEqual(response_data["timezone"], "Europe/Lisbon") + + self.team.refresh_from_db() + self.assertEqual(self.team.timezone, "Europe/Lisbon") + + self._assert_activity_log( + [ + { + "activity": "updated", + "created_at": "2022-02-08T00:00:00Z", + "detail": { + "changes": [ + { + "action": "changed", + "after": "Europe/Lisbon", + "before": "UTC", + "field": "timezone", + "type": "Team", + }, + ], + "name": "Default project", + "short_id": None, + "trigger": None, + "type": None, + }, + "item_id": str(self.team.pk), + "scope": "Team", + "user": { + "email": "user1@posthog.com", + "first_name": "", + }, + }, + ] + ) - response = self.client.patch("/api/projects/@current/", {"timezone": "Europe/Lisbon"}) - self.assertEqual(response.status_code, status.HTTP_200_OK) + def test_update_test_filter_default_checked(self): + response = self.client.patch( + "/api/environments/@current/", {"test_account_filters_default_checked": "true"} + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) - response_data = response.json() - self.assertEqual(response_data["name"], self.team.name) - self.assertEqual(response_data["timezone"], "Europe/Lisbon") + response_data = response.json() + self.assertEqual(response_data["test_account_filters_default_checked"], True) - self.team.refresh_from_db() - self.assertEqual(self.team.timezone, "Europe/Lisbon") + self.team.refresh_from_db() + self.assertEqual(self.team.test_account_filters_default_checked, True) - self._assert_activity_log( - [ + def test_cannot_set_invalid_timezone_for_team(self): + response = self.client.patch("/api/environments/@current/", {"timezone": "America/I_Dont_Exist"}) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual( + response.json(), + { + "type": "validation_error", + "code": "invalid_choice", + "detail": '"America/I_Dont_Exist" is not a valid choice.', + "attr": "timezone", + }, + ) + + self.team.refresh_from_db() + self.assertNotEqual(self.team.timezone, "America/I_Dont_Exist") + + def test_cant_update_team_from_another_org(self): + org = Organization.objects.create(name="New Org") + team = Team.objects.create(organization=org, name="Default project") + + response = self.client.patch(f"/api/environments/{team.pk}/", {"timezone": "Africa/Accra"}) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + self.assertEqual(response.json(), self.not_found_response()) + + team.refresh_from_db() + self.assertEqual(team.timezone, "UTC") + + def test_filter_permission(self): + response = self.client.patch( + f"/api/environments/{self.team.id}/", + {"test_account_filters": [{"key": "$current_url", "value": "test"}]}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response_data = response.json() + self.assertEqual(response_data["name"], self.team.name) + self.assertEqual( + response_data["test_account_filters"], + [{"key": "$current_url", "value": "test"}], + ) + + @freeze_time("2022-02-08") + def test_delete_team_activity_log(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + + team: Team = Team.objects.create_with_data(organization=self.organization) + + response = self.client.delete(f"/api/environments/{team.id}") + assert response.status_code == 204 + + # activity log is queried in the context of the team + # and the team was deleted, so we can't (for now) view a deleted team activity via the API + # even though the activity log is recorded + + deleted_team_activity_response = self.client.get(f"/api/environments/{team.id}/activity") + assert deleted_team_activity_response.status_code == status.HTTP_404_NOT_FOUND + + # we can't query by API but can prove the log was recorded + activity = [a.__dict__ for a in ActivityLog.objects.filter(team_id=team.pk).all()] + assert activity == [ { - "activity": "updated", - "created_at": "2022-02-08T00:00:00Z", + "_state": ANY, + "activity": "deleted", + "created_at": ANY, "detail": { - "changes": [ - { - "action": "changed", - "after": "Europe/Lisbon", - "before": "UTC", - "field": "timezone", - "type": "Team", - }, - ], + "changes": None, "name": "Default project", "short_id": None, "trigger": None, "type": None, }, - "item_id": str(self.team.pk), + "id": ANY, + "is_system": False, + "organization_id": ANY, + "team_id": team.pk, + "item_id": str(team.pk), "scope": "Team", - "user": { - "email": "user1@posthog.com", - "first_name": "", - }, + "user_id": self.user.pk, + "was_impersonated": False, }, ] - ) - def test_update_test_filter_default_checked(self): - response = self.client.patch("/api/projects/@current/", {"test_account_filters_default_checked": "true"}) - self.assertEqual(response.status_code, status.HTTP_200_OK) + @patch("posthog.api.project.delete_bulky_postgres_data") + @patch("posthog.api.team.delete_bulky_postgres_data") + @patch("posthoganalytics.capture") + def test_delete_team_own_second( + self, + mock_capture: MagicMock, + mock_delete_bulky_postgres_data: MagicMock, + mock_delete_bulky_postgres_data_legacy_endpoint: MagicMock, + ): + if self.client_class is EnvironmentToProjectRewriteClient: + mock_delete_bulky_postgres_data = mock_delete_bulky_postgres_data_legacy_endpoint - response_data = response.json() - self.assertEqual(response_data["test_account_filters_default_checked"], True) + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() - self.team.refresh_from_db() - self.assertEqual(self.team.test_account_filters_default_checked, True) + team: Team = Team.objects.create_with_data(organization=self.organization) - def test_cannot_set_invalid_timezone_for_project(self): - response = self.client.patch("/api/projects/@current/", {"timezone": "America/I_Dont_Exist"}) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual( - response.json(), - { - "type": "validation_error", - "code": "invalid_choice", - "detail": '"America/I_Dont_Exist" is not a valid choice.', - "attr": "timezone", - }, - ) + self.assertEqual(Team.objects.filter(organization=self.organization).count(), 2) + + response = self.client.delete(f"/api/environments/{team.id}") + + self.assertEqual(response.status_code, 204) + self.assertEqual(Team.objects.filter(organization=self.organization).count(), 1) + self.assertEqual( + AsyncDeletion.objects.filter( + team_id=team.id, deletion_type=DeletionType.Team, key=str(team.id) + ).count(), + 1, + ) + mock_capture.assert_has_calls( + calls=[ + call( + self.user.distinct_id, + "membership level changed", + properties={"new_level": 8, "previous_level": 1, "$set": mock.ANY}, + groups=mock.ANY, + ), + call(self.user.distinct_id, "team deleted", properties={}, groups=mock.ANY), + ] + ) + mock_delete_bulky_postgres_data.assert_called_once_with(team_ids=[team.pk]) - self.team.refresh_from_db() - self.assertNotEqual(self.team.timezone, "America/I_Dont_Exist") + def test_delete_bulky_postgres_data(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() - def test_cant_update_project_from_another_org(self): - org = Organization.objects.create(name="New Org") - team = Team.objects.create(organization=org, name="Default project") + team: Team = Team.objects.create_with_data(organization=self.organization) - response = self.client.patch(f"/api/projects/{team.pk}/", {"timezone": "Africa/Accra"}) - self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) - self.assertEqual(response.json(), self.not_found_response()) + self.assertEqual(Team.objects.filter(organization=self.organization).count(), 2) - team.refresh_from_db() - self.assertEqual(team.timezone, "UTC") + from posthog.models.cohort import Cohort, CohortPeople + from posthog.models.feature_flag.feature_flag import ( + FeatureFlag, + FeatureFlagHashKeyOverride, + ) - def test_filter_permission(self): - response = self.client.patch( - f"/api/projects/{self.team.id}/", - {"test_account_filters": [{"key": "$current_url", "value": "test"}]}, - ) - self.assertEqual(response.status_code, status.HTTP_200_OK) + # from posthog.models.insight_caching_state import InsightCachingState + from posthog.models.person import Person - response_data = response.json() - self.assertEqual(response_data["name"], self.team.name) - self.assertEqual( - response_data["test_account_filters"], - [{"key": "$current_url", "value": "test"}], - ) + cohort = Cohort.objects.create(team=team, created_by=self.user, name="test") + person = Person.objects.create( + team=team, + distinct_ids=["example_id"], + properties={"email": "tim@posthog.com", "team": "posthog"}, + ) + person.add_distinct_id("test") + flag = FeatureFlag.objects.create( + team=team, + name="test", + key="test", + rollout_percentage=50, + created_by=self.user, + ) + FeatureFlagHashKeyOverride.objects.create( + team_id=team.pk, + person_id=person.id, + feature_flag_key=flag.key, + hash_key="test", + ) + CohortPeople.objects.create(cohort_id=cohort.pk, person_id=person.pk) + EarlyAccessFeature.objects.create( + team=team, + name="Test flag", + description="A fancy new flag.", + stage="beta", + feature_flag=flag, + ) + + # if something is missing then teardown fails + response = self.client.delete(f"/api/environments/{team.id}") + self.assertEqual(response.status_code, 204) - @freeze_time("2022-02-08") - @patch("posthog.api.project.delete_bulky_postgres_data") - @patch("posthoganalytics.capture") - def test_delete_team_activity_log(self, mock_capture: MagicMock, mock_delete_bulky_postgres_data: MagicMock): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - - team: Team = Team.objects.create_with_data(organization=self.organization) - - response = self.client.delete(f"/api/projects/{team.id}") - assert response.status_code == 204 - - # activity log is queried in the context of the team - # and the team was deleted, so we can't (for now) view a deleted team activity via the API - # even though the activity log is recorded - - deleted_team_activity_response = self.client.get(f"/api/projects/{team.id}/activity") - assert deleted_team_activity_response.status_code == status.HTTP_404_NOT_FOUND - - # we can't query by API but can prove the log was recorded - activity = [a.__dict__ for a in ActivityLog.objects.filter(team_id=team.pk).all()] - assert activity == [ - { - "_state": ANY, - "activity": "deleted", - "created_at": ANY, - "detail": { - "changes": None, - "name": "Default project", - "short_id": None, - "trigger": None, - "type": None, + def test_delete_batch_exports(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + + team: Team = Team.objects.create_with_data(organization=self.organization) + + destination_data = { + "type": "S3", + "config": { + "bucket_name": "my-production-s3-bucket", + "region": "us-east-1", + "prefix": "posthog-events/", + "aws_access_key_id": "abc123", + "aws_secret_access_key": "secret", }, - "id": ANY, - "is_system": False, - "organization_id": ANY, - "team_id": team.pk, - "item_id": str(team.pk), - "scope": "Team", - "user_id": self.user.pk, - "was_impersonated": False, - }, - ] - - @patch("posthog.api.project.delete_bulky_postgres_data") - @patch("posthoganalytics.capture") - def test_delete_team_own_second(self, mock_capture: MagicMock, mock_delete_bulky_postgres_data: MagicMock): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - - team: Team = Team.objects.create_with_data(organization=self.organization) - - self.assertEqual(Team.objects.filter(organization=self.organization).count(), 2) - - response = self.client.delete(f"/api/projects/{team.id}") - - self.assertEqual(response.status_code, 204) - self.assertEqual(Team.objects.filter(organization=self.organization).count(), 1) - self.assertEqual( - AsyncDeletion.objects.filter(team_id=team.id, deletion_type=DeletionType.Team, key=str(team.id)).count(), - 1, - ) - mock_capture.assert_has_calls( - calls=[ - call( - self.user.distinct_id, - "membership level changed", - properties={"new_level": 8, "previous_level": 1, "$set": mock.ANY}, - groups=mock.ANY, - ), - call(self.user.distinct_id, "team deleted", properties={}, groups=mock.ANY), - ] - ) - mock_delete_bulky_postgres_data.assert_called_once_with(team_ids=[team.pk]) + } + + batch_export_data = { + "name": "my-production-s3-bucket-destination", + "destination": destination_data, + "interval": "hour", + } + + temporal = sync_connect() + + with start_test_worker(temporal): + response = self.client.post( + f"/api/environments/{team.id}/batch_exports", + json.dumps(batch_export_data), + content_type="application/json", + ) + self.assertEqual(response.status_code, 201) + + batch_export = response.json() + batch_export_id = batch_export["id"] + + response = self.client.delete(f"/api/environments/{team.id}") + self.assertEqual(response.status_code, 204) + + response = self.client.get(f"/api/environments/{team.id}/batch_exports/{batch_export_id}") + self.assertEqual(response.status_code, 404) + + with self.assertRaises(RPCError): + describe_schedule(temporal, batch_export_id) + + @freeze_time("2022-02-08") + def test_reset_token(self): + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + + self._assert_activity_log_is_empty() + + self.team.api_token = "xyz" + self.team.save() + + response = self.client.patch(f"/api/environments/{self.team.id}/reset_token/") + response_data = response.json() + + self.team.refresh_from_db() + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertNotEqual(response_data["api_token"], "xyz") + self.assertEqual(response_data["api_token"], self.team.api_token) + self.assertTrue(response_data["api_token"].startswith("phc_")) + + self._assert_activity_log( + [ + { + "activity": "updated", + "created_at": "2022-02-08T00:00:00Z", + "detail": { + "changes": [ + { + "action": "changed", + "after": None, + "before": None, + "field": "api_token", + "type": "Team", + }, + ], + "name": "Default project", + "short_id": None, + "trigger": None, + "type": None, + }, + "item_id": str(self.team.pk), + "scope": "Team", + "user": { + "email": "user1@posthog.com", + "first_name": "", + }, + }, + ] + ) - def test_delete_bulky_postgres_data(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() + def test_reset_token_insufficient_priviledges(self): + self.team.api_token = "xyz" + self.team.save() - team: Team = Team.objects.create_with_data(organization=self.organization) + response = self.client.patch(f"/api/environments/{self.team.id}/reset_token/") + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - self.assertEqual(Team.objects.filter(organization=self.organization).count(), 2) + def test_update_primary_dashboard(self): + d = Dashboard.objects.create(name="Test", team=self.team) - from posthog.models.cohort import Cohort, CohortPeople - from posthog.models.feature_flag.feature_flag import ( - FeatureFlag, - FeatureFlagHashKeyOverride, - ) + # Can set it + response = self.client.patch("/api/environments/@current/", {"primary_dashboard": d.id}) + response_data = response.json() - # from posthog.models.insight_caching_state import InsightCachingState - from posthog.models.person import Person + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response_data["name"], self.team.name) + self.assertEqual(response_data["primary_dashboard"], d.id) - cohort = Cohort.objects.create(team=team, created_by=self.user, name="test") - person = Person.objects.create( - team=team, - distinct_ids=["example_id"], - properties={"email": "tim@posthog.com", "team": "posthog"}, - ) - person.add_distinct_id("test") - flag = FeatureFlag.objects.create( - team=team, - name="test", - key="test", - rollout_percentage=50, - created_by=self.user, - ) - FeatureFlagHashKeyOverride.objects.create( - team_id=team.pk, - person_id=person.id, - feature_flag_key=flag.key, - hash_key="test", - ) - CohortPeople.objects.create(cohort_id=cohort.pk, person_id=person.pk) - EarlyAccessFeature.objects.create( - team=team, - name="Test flag", - description="A fancy new flag.", - stage="beta", - feature_flag=flag, - ) + def test_cant_set_primary_dashboard_to_another_teams_dashboard(self): + team_2 = Team.objects.create(organization=self.organization, name="Default project") + d = Dashboard.objects.create(name="Test", team=team_2) + + response = self.client.patch("/api/environments/@current/", {"primary_dashboard": d.id}) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + response = self.client.get("/api/environments/@current/") + response_data = response.json() + self.assertEqual(response_data["primary_dashboard"], None) + + def test_is_generating_demo_data(self): + cache_key = f"is_generating_demo_data_{self.team.pk}" + cache.set(cache_key, "True") + response = self.client.get(f"/api/environments/{self.team.id}/is_generating_demo_data/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.json(), {"is_generating_demo_data": True}) + cache.delete(cache_key) + response = self.client.get(f"/api/environments/{self.team.id}/is_generating_demo_data/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.json(), {"is_generating_demo_data": False}) + + @freeze_time("2022-02-08") + def test_team_float_config_can_be_serialized_to_activity_log(self): + # regression test since this isn't true by default + response = self.client.patch(f"/api/environments/@current/", {"session_recording_sample_rate": 0.4}) + assert response.status_code == status.HTTP_200_OK + self._assert_activity_log( + [ + { + "activity": "updated", + "created_at": "2022-02-08T00:00:00Z", + "detail": { + "changes": [ + { + "action": "created", + "after": "0.4", + "before": None, + "field": "session_recording_sample_rate", + "type": "Team", + }, + ], + "name": "Default project", + "short_id": None, + "trigger": None, + "type": None, + }, + "item_id": str(self.team.pk), + "scope": "Team", + "user": { + "email": "user1@posthog.com", + "first_name": "", + }, + }, + ] + ) - # if something is missing then teardown fails - response = self.client.delete(f"/api/projects/{team.id}") - self.assertEqual(response.status_code, 204) - - def test_delete_batch_exports(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - - team: Team = Team.objects.create_with_data(organization=self.organization) - - destination_data = { - "type": "S3", - "config": { - "bucket_name": "my-production-s3-bucket", - "region": "us-east-1", - "prefix": "posthog-events/", - "aws_access_key_id": "abc123", - "aws_secret_access_key": "secret", - }, - } - - batch_export_data = { - "name": "my-production-s3-bucket-destination", - "destination": destination_data, - "interval": "hour", - } - - temporal = sync_connect() - - with start_test_worker(temporal): - response = self.client.post( - f"/api/projects/{team.id}/batch_exports", - json.dumps(batch_export_data), - content_type="application/json", + @freeze_time("2022-02-08") + def test_team_creation_is_in_activity_log(self): + Team.objects.all().delete() + + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() + + team_name = str(uuid.uuid4()) + response = self.client.post("/api/environments/", {"name": team_name, "is_demo": False}) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + team_id = response.json()["id"] + self._assert_activity_log( + [ + { + "activity": "created", + "created_at": "2022-02-08T00:00:00Z", + "detail": { + "changes": None, + "name": team_name, + "short_id": None, + "trigger": None, + "type": None, + }, + "item_id": str(team_id), + "scope": "Team", + "user": { + "email": "user1@posthog.com", + "first_name": "", + }, + }, + ], + team_id=team_id, ) - self.assertEqual(response.status_code, 201) - batch_export = response.json() - batch_export_id = batch_export["id"] + def test_team_is_cached_on_create_and_update(self): + Team.objects.all().delete() + self.organization_membership.level = OrganizationMembership.Level.ADMIN + self.organization_membership.save() - response = self.client.delete(f"/api/projects/{team.id}") - self.assertEqual(response.status_code, 204) + response = self.client.post("/api/environments/", {"name": "Test", "is_demo": False}) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(response.json()["name"], "Test") + + token = response.json()["api_token"] + team_id = response.json()["id"] + + cached_team = get_team_in_cache(token) + + assert cached_team is not None + self.assertEqual(cached_team.name, "Test") + self.assertEqual(cached_team.uuid, response.json()["uuid"]) + self.assertEqual(cached_team.id, response.json()["id"]) + + response = self.client.patch( + f"/api/environments/{team_id}/", + {"timezone": "Europe/Istanbul", "session_recording_opt_in": True}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + cached_team = get_team_in_cache(token) + assert cached_team is not None + + self.assertEqual(cached_team.name, "Test") + self.assertEqual(cached_team.uuid, response.json()["uuid"]) + self.assertEqual(cached_team.session_recording_opt_in, True) + + # only things in CachedTeamSerializer are cached! + self.assertEqual(cached_team.timezone, "UTC") + + # reset token should update cache as well + response = self.client.patch(f"/api/environments/{team_id}/reset_token/") + response_data = response.json() + + cached_team = get_team_in_cache(token) + assert cached_team is None - response = self.client.get(f"/api/projects/{team.id}/batch_exports/{batch_export_id}") - self.assertEqual(response.status_code, 404) + cached_team = get_team_in_cache(response_data["api_token"]) + assert cached_team is not None + self.assertEqual(cached_team.name, "Test") + self.assertEqual(cached_team.uuid, response.json()["uuid"]) + self.assertEqual(cached_team.session_recording_opt_in, True) - with self.assertRaises(RPCError): - describe_schedule(temporal, batch_export_id) + def test_turn_on_exception_autocapture(self): + response = self.client.get("/api/environments/@current/") + assert response.json()["autocapture_exceptions_opt_in"] is None - @freeze_time("2022-02-08") - def test_reset_token(self): - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() + response = self.client.patch( + "/api/environments/@current/", + {"autocapture_exceptions_opt_in": "Welwyn Garden City"}, + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert response.json()["detail"] == "Must be a valid boolean." + + response = self.client.patch("/api/environments/@current/", {"autocapture_exceptions_opt_in": True}) + assert response.status_code == status.HTTP_200_OK + response = self.client.get("/api/environments/@current/") + assert response.json()["autocapture_exceptions_opt_in"] is True - self._assert_activity_log_is_empty() + def test_configure_exception_autocapture_event_dropping(self): + response = self.client.get("/api/environments/@current/") + assert response.json()["autocapture_exceptions_errors_to_ignore"] is None - self.team.api_token = "xyz" - self.team.save() + response = self.client.patch( + "/api/environments/@current/", + {"autocapture_exceptions_errors_to_ignore": {"wat": "am i"}}, + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert ( + response.json()["detail"] == "Must provide a list for field: autocapture_exceptions_errors_to_ignore." + ) - response = self.client.patch(f"/api/projects/{self.team.id}/reset_token/") - response_data = response.json() + response = self.client.patch( + "/api/environments/@current/", + {"autocapture_exceptions_errors_to_ignore": [1, False]}, + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert ( + response.json()["detail"] + == "Must provide a list of strings to field: autocapture_exceptions_errors_to_ignore." + ) - self.team.refresh_from_db() - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertNotEqual(response_data["api_token"], "xyz") - self.assertEqual(response_data["api_token"], self.team.api_token) - self.assertTrue(response_data["api_token"].startswith("phc_")) + response = self.client.patch( + "/api/environments/@current/", + {"autocapture_exceptions_errors_to_ignore": ["wat am i"]}, + ) + assert response.status_code == status.HTTP_200_OK + response = self.client.get("/api/environments/@current/") + assert response.json()["autocapture_exceptions_errors_to_ignore"] == ["wat am i"] + + def test_configure_exception_autocapture_event_dropping_only_allows_simple_config(self): + response = self.client.patch( + "/api/environments/@current/", + {"autocapture_exceptions_errors_to_ignore": ["abc" * 300]}, + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert ( + response.json()["detail"] + == "Field autocapture_exceptions_errors_to_ignore must be less than 300 characters. Complex config should be provided in posthog-js initialization." + ) - self._assert_activity_log( + @parameterized.expand( [ - { - "activity": "updated", - "created_at": "2022-02-08T00:00:00Z", - "detail": { - "changes": [ - { - "action": "changed", - "after": None, - "before": None, - "field": "api_token", - "type": "Team", - }, - ], - "name": "Default project", - "short_id": None, - "trigger": None, - "type": None, - }, - "item_id": str(self.team.pk), - "scope": "Team", - "user": { - "email": "user1@posthog.com", - "first_name": "", - }, - }, + [ + "non numeric string", + "Welwyn Garden City", + "invalid_input", + "A valid number is required.", + ], + [ + "negative number", + "-1", + "min_value", + "Ensure this value is greater than or equal to 0.", + ], + [ + "greater than one", + "1.5", + "max_value", + "Ensure this value is less than or equal to 1.", + ], + [ + "too many digits", + "0.534", + "max_decimal_places", + "Ensure that there are no more than 2 decimal places.", + ], ] ) + def test_invalid_session_recording_sample_rates( + self, _name: str, provided_value: str, expected_code: str, expected_error: str + ) -> None: + response = self.client.patch( + "/api/environments/@current/", {"session_recording_sample_rate": provided_value} + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert response.json() == { + "attr": "session_recording_sample_rate", + "code": expected_code, + "detail": expected_error, + "type": "validation_error", + } - def test_reset_token_insufficient_priviledges(self): - self.team.api_token = "xyz" - self.team.save() - - response = self.client.patch(f"/api/projects/{self.team.id}/reset_token/") - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - - def test_update_primary_dashboard(self): - d = Dashboard.objects.create(name="Test", team=self.team) - - # Can set it - response = self.client.patch("/api/projects/@current/", {"primary_dashboard": d.id}) - response_data = response.json() - - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response_data["name"], self.team.name) - self.assertEqual(response_data["primary_dashboard"], d.id) - - def test_cant_set_primary_dashboard_to_another_teams_dashboard(self): - team_2 = Team.objects.create(organization=self.organization, name="Default project") - d = Dashboard.objects.create(name="Test", team=team_2) - - response = self.client.patch("/api/projects/@current/", {"primary_dashboard": d.id}) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - - response = self.client.get("/api/projects/@current/") - response_data = response.json() - self.assertEqual(response_data["primary_dashboard"], None) - - def test_is_generating_demo_data(self): - cache_key = f"is_generating_demo_data_{self.team.pk}" - cache.set(cache_key, "True") - response = self.client.get(f"/api/projects/{self.team.id}/is_generating_demo_data/") - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.json(), {"is_generating_demo_data": True}) - cache.delete(cache_key) - response = self.client.get(f"/api/projects/{self.team.id}/is_generating_demo_data/") - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.json(), {"is_generating_demo_data": False}) - - @freeze_time("2022-02-08") - def test_team_float_config_can_be_serialized_to_activity_log(self): - # regression test since this isn't true by default - response = self.client.patch(f"/api/projects/@current/", {"session_recording_sample_rate": 0.4}) - assert response.status_code == status.HTTP_200_OK - self._assert_activity_log( + @parameterized.expand( [ - { - "activity": "updated", - "created_at": "2022-02-08T00:00:00Z", - "detail": { - "changes": [ - { - "action": "created", - "after": "0.4", - "before": None, - "field": "session_recording_sample_rate", - "type": "Team", - }, - ], - "name": "Default project", - "short_id": None, - "trigger": None, - "type": None, - }, - "item_id": str(self.team.pk), - "scope": "Team", - "user": { - "email": "user1@posthog.com", - "first_name": "", - }, - }, + [ + "non numeric string", + "Trentham monkey forest", + "invalid_input", + "A valid integer is required.", + ], + [ + "negative number", + "-1", + "min_value", + "Ensure this value is greater than or equal to 0.", + ], + [ + "greater than 15000", + "15001", + "max_value", + "Ensure this value is less than or equal to 15000.", + ], + ["too many digits", "0.5", "invalid_input", "A valid integer is required."], + ] + ) + def test_invalid_session_recording_minimum_duration( + self, _name: str, provided_value: str, expected_code: str, expected_error: str + ) -> None: + response = self.client.patch( + "/api/environments/@current/", + {"session_recording_minimum_duration_milliseconds": provided_value}, + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert response.json() == { + "attr": "session_recording_minimum_duration_milliseconds", + "code": expected_code, + "detail": expected_error, + "type": "validation_error", + } + + @parameterized.expand( + [ + [ + "string", + "Marple bridge", + "invalid_input", + "Must provide a dictionary or None.", + ], + ["numeric string", "-1", "invalid_input", "Must provide a dictionary or None."], + ["numeric", 1, "invalid_input", "Must provide a dictionary or None."], + ["numeric positive string", "1", "invalid_input", "Must provide a dictionary or None."], + [ + "unexpected json - no id", + {"key": "something"}, + "invalid_input", + "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", + ], + [ + "unexpected json - no key", + {"id": 1}, + "invalid_input", + "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", + ], + [ + "unexpected json - only variant", + {"variant": "1"}, + "invalid_input", + "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", + ], + [ + "unexpected json - variant must be string", + {"variant": 1}, + "invalid_input", + "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", + ], + [ + "unexpected json - missing id", + {"key": "one", "variant": "1"}, + "invalid_input", + "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", + ], + [ + "unexpected json - missing key", + {"id": "one", "variant": "1"}, + "invalid_input", + "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", + ], + [ + "unexpected json - neither", + {"wat": "wat"}, + "invalid_input", + "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", + ], ] ) + def test_invalid_session_recording_linked_flag( + self, _name: str, provided_value: Any, expected_code: str, expected_error: str + ) -> None: + response = self._patch_linked_flag_config(provided_value, expected_status=status.HTTP_400_BAD_REQUEST) + + assert response.json() == { + "attr": "session_recording_linked_flag", + "code": expected_code, + "detail": expected_error, + "type": "validation_error", + } + + def test_can_set_and_unset_session_recording_linked_flag(self) -> None: + self._patch_linked_flag_config({"id": 1, "key": "provided_value"}) + self._assert_linked_flag_config({"id": 1, "key": "provided_value"}) - @freeze_time("2022-02-08") - def test_team_creation_is_in_activity_log(self): - Team.objects.all().delete() + self._patch_linked_flag_config(None) + self._assert_linked_flag_config(None) - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() + def test_can_set_and_unset_session_recording_linked_flag_variant(self) -> None: + self._patch_linked_flag_config({"id": 1, "key": "provided_value", "variant": "test"}) + self._assert_linked_flag_config({"id": 1, "key": "provided_value", "variant": "test"}) - team_name = str(uuid.uuid4()) - response = self.client.post("/api/projects/", {"name": team_name, "is_demo": False}) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self._patch_linked_flag_config(None) + self._assert_linked_flag_config(None) - team_id = response.json()["id"] - self._assert_activity_log( + @parameterized.expand( [ - { - "activity": "created", - "created_at": "2022-02-08T00:00:00Z", - "detail": { - "changes": None, - "name": team_name, - "short_id": None, - "trigger": None, - "type": None, - }, - "item_id": str(team_id), - "scope": "Team", - "user": { - "email": "user1@posthog.com", - "first_name": "", - }, - }, - ], - team_id=team_id, + [ + "string", + "Marple bridge", + "invalid_input", + "Must provide a dictionary or None.", + ], + ["numeric", "-1", "invalid_input", "Must provide a dictionary or None."], + [ + "unexpected json - no recordX", + {"key": "something"}, + "invalid_input", + "Must provide a dictionary with only 'recordHeaders' and/or 'recordBody' keys.", + ], + ] ) + def test_invalid_session_recording_network_payload_capture_config( + self, _name: str, provided_value: str, expected_code: str, expected_error: str + ) -> None: + response = self.client.patch( + "/api/environments/@current/", {"session_recording_network_payload_capture_config": provided_value} + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert response.json() == { + "attr": "session_recording_network_payload_capture_config", + "code": expected_code, + "detail": expected_error, + "type": "validation_error", + } - def test_team_is_cached_on_create_and_update(self): - Team.objects.all().delete() - self.organization_membership.level = OrganizationMembership.Level.ADMIN - self.organization_membership.save() - - response = self.client.post("/api/projects/", {"name": "Test", "is_demo": False}) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - self.assertEqual(response.json()["name"], "Test") + def test_can_set_and_unset_session_recording_network_payload_capture_config(self) -> None: + # can set just one + first_patch_response = self.client.patch( + "/api/environments/@current/", + {"session_recording_network_payload_capture_config": {"recordHeaders": True}}, + ) + assert first_patch_response.status_code == status.HTTP_200_OK + get_response = self.client.get("/api/environments/@current/") + assert get_response.json()["session_recording_network_payload_capture_config"] == {"recordHeaders": True} + + # can set the other + first_patch_response = self.client.patch( + "/api/environments/@current/", + {"session_recording_network_payload_capture_config": {"recordBody": False}}, + ) + assert first_patch_response.status_code == status.HTTP_200_OK + get_response = self.client.get("/api/environments/@current/") + assert get_response.json()["session_recording_network_payload_capture_config"] == {"recordBody": False} - token = response.json()["api_token"] - team_id = response.json()["id"] + # can unset both + response = self.client.patch( + "/api/environments/@current/", {"session_recording_network_payload_capture_config": None} + ) + assert response.status_code == status.HTTP_200_OK + second_get_response = self.client.get("/api/environments/@current/") + assert second_get_response.json()["session_recording_network_payload_capture_config"] is None - cached_team = get_team_in_cache(token) + def test_can_set_and_unset_session_replay_config(self) -> None: + # can set + self._patch_session_replay_config({"record_canvas": True}) + self._assert_replay_config_is({"record_canvas": True}) - assert cached_team is not None - self.assertEqual(cached_team.name, "Test") - self.assertEqual(cached_team.uuid, response.json()["uuid"]) - self.assertEqual(cached_team.id, response.json()["id"]) + # can unset + self._patch_session_replay_config(None) + self._assert_replay_config_is(None) - response = self.client.patch( - f"/api/projects/{team_id}/", - {"timezone": "Europe/Istanbul", "session_recording_opt_in": True}, + @parameterized.expand( + [ + [ + "string", + "Marple bridge", + "invalid_input", + "Must provide a dictionary or None.", + ], + ["numeric", "-1", "invalid_input", "Must provide a dictionary or None."], + [ + "unexpected json - no record", + {"key": "something"}, + "invalid_input", + "Must provide a dictionary with only allowed keys: included_event_properties, opt_in, preferred_events, excluded_events, important_user_properties.", + ], + ] ) - self.assertEqual(response.status_code, status.HTTP_200_OK) + def test_invalid_session_replay_config_ai_config( + self, _name: str, provided_value: str, expected_code: str, expected_error: str + ) -> None: + response = self._patch_session_replay_config( + {"ai_config": provided_value}, expected_status=status.HTTP_400_BAD_REQUEST + ) + assert response.json() == { + "attr": "session_replay_config", + "code": expected_code, + "detail": expected_error, + "type": "validation_error", + } - cached_team = get_team_in_cache(token) - assert cached_team is not None + def test_can_set_and_unset_session_replay_config_ai_config(self) -> None: + # can set just the opt-in + self._patch_session_replay_config({"ai_config": {"opt_in": True}}) + self._assert_replay_config_is({"ai_config": {"opt_in": True}}) - self.assertEqual(cached_team.name, "Test") - self.assertEqual(cached_team.uuid, response.json()["uuid"]) - self.assertEqual(cached_team.session_recording_opt_in, True) + # can set some preferences + self._patch_session_replay_config( + {"ai_config": {"opt_in": False, "included_event_properties": ["something"]}} + ) + self._assert_replay_config_is({"ai_config": {"opt_in": False, "included_event_properties": ["something"]}}) - # only things in CachedTeamSerializer are cached! - self.assertEqual(cached_team.timezone, "UTC") + self._patch_session_replay_config({"ai_config": None}) + self._assert_replay_config_is({"ai_config": None}) - # reset token should update cache as well - response = self.client.patch(f"/api/projects/{team_id}/reset_token/") - response_data = response.json() + def test_can_set_replay_configs_without_providing_them_all(self) -> None: + # can set just the opt-in + self._patch_session_replay_config({"ai_config": {"opt_in": True}}) + self._assert_replay_config_is({"ai_config": {"opt_in": True}}) - cached_team = get_team_in_cache(token) - assert cached_team is None + self._patch_session_replay_config({"record_canvas": True}) + self._assert_replay_config_is({"record_canvas": True, "ai_config": {"opt_in": True}}) - cached_team = get_team_in_cache(response_data["api_token"]) - assert cached_team is not None - self.assertEqual(cached_team.name, "Test") - self.assertEqual(cached_team.uuid, response.json()["uuid"]) - self.assertEqual(cached_team.session_recording_opt_in, True) + def test_can_set_replay_configs_without_providing_them_all_even_when_either_side_is_none(self) -> None: + # because we do some dictionary copying we need a regression test to ensure we can always set and unset keys + self._patch_session_replay_config({"record_canvas": True, "ai_config": {"opt_in": True}}) + self._assert_replay_config_is({"record_canvas": True, "ai_config": {"opt_in": True}}) - def test_turn_on_exception_autocapture(self): - response = self.client.get("/api/projects/@current/") - assert response.json()["autocapture_exceptions_opt_in"] is None + self._patch_session_replay_config({"record_canvas": None}) + self._assert_replay_config_is({"record_canvas": None, "ai_config": {"opt_in": True}}) - response = self.client.patch( - "/api/projects/@current/", - {"autocapture_exceptions_opt_in": "Welwyn Garden City"}, - ) - assert response.status_code == status.HTTP_400_BAD_REQUEST - assert response.json()["detail"] == "Must be a valid boolean." + # top-level from having a value to None + self._patch_session_replay_config(None) + self._assert_replay_config_is(None) - response = self.client.patch("/api/projects/@current/", {"autocapture_exceptions_opt_in": True}) - assert response.status_code == status.HTTP_200_OK - response = self.client.get("/api/projects/@current/") - assert response.json()["autocapture_exceptions_opt_in"] is True + # top-level from None to having a value + self._patch_session_replay_config({"ai_config": None}) + self._assert_replay_config_is({"ai_config": None}) - def test_configure_exception_autocapture_event_dropping(self): - response = self.client.get("/api/projects/@current/") - assert response.json()["autocapture_exceptions_errors_to_ignore"] is None + # next-level from None to having a value + self._patch_session_replay_config({"ai_config": {"opt_in": True}}) + self._assert_replay_config_is({"ai_config": {"opt_in": True}}) - response = self.client.patch( - "/api/projects/@current/", - {"autocapture_exceptions_errors_to_ignore": {"wat": "am i"}}, - ) - assert response.status_code == status.HTTP_400_BAD_REQUEST - assert response.json()["detail"] == "Must provide a list for field: autocapture_exceptions_errors_to_ignore." + # next-level from having a value to None + self._patch_session_replay_config({"ai_config": None}) + self._assert_replay_config_is({"ai_config": None}) - response = self.client.patch( - "/api/projects/@current/", - {"autocapture_exceptions_errors_to_ignore": [1, False]}, - ) - assert response.status_code == status.HTTP_400_BAD_REQUEST - assert ( - response.json()["detail"] - == "Must provide a list of strings to field: autocapture_exceptions_errors_to_ignore." - ) + def test_can_set_replay_configs_patch_session_replay_config_one_level_deep(self) -> None: + # can set just the opt-in + self._patch_session_replay_config({"ai_config": {"opt_in": True}}) + self._assert_replay_config_is({"ai_config": {"opt_in": True}}) - response = self.client.patch( - "/api/projects/@current/", - {"autocapture_exceptions_errors_to_ignore": ["wat am i"]}, - ) - assert response.status_code == status.HTTP_200_OK - response = self.client.get("/api/projects/@current/") - assert response.json()["autocapture_exceptions_errors_to_ignore"] == ["wat am i"] - - def test_configure_exception_autocapture_event_dropping_only_allows_simple_config(self): - response = self.client.patch( - "/api/projects/@current/", - {"autocapture_exceptions_errors_to_ignore": ["abc" * 300]}, - ) - assert response.status_code == status.HTTP_400_BAD_REQUEST - assert ( - response.json()["detail"] - == "Field autocapture_exceptions_errors_to_ignore must be less than 300 characters. Complex config should be provided in posthog-js initialization." - ) + self._patch_session_replay_config({"ai_config": {"included_event_properties": ["something"]}}) + # even though opt_in was not provided in the patch it should be preserved + self._assert_replay_config_is({"ai_config": {"opt_in": True, "included_event_properties": ["something"]}}) - @parameterized.expand( - [ - [ - "non numeric string", - "Welwyn Garden City", - "invalid_input", - "A valid number is required.", - ], - [ - "negative number", - "-1", - "min_value", - "Ensure this value is greater than or equal to 0.", - ], - [ - "greater than one", - "1.5", - "max_value", - "Ensure this value is less than or equal to 1.", - ], - [ - "too many digits", - "0.534", - "max_decimal_places", - "Ensure that there are no more than 2 decimal places.", - ], - ] - ) - def test_invalid_session_recording_sample_rates( - self, _name: str, provided_value: str, expected_code: str, expected_error: str - ) -> None: - response = self.client.patch("/api/projects/@current/", {"session_recording_sample_rate": provided_value}) - assert response.status_code == status.HTTP_400_BAD_REQUEST - assert response.json() == { - "attr": "session_recording_sample_rate", - "code": expected_code, - "detail": expected_error, - "type": "validation_error", - } - - @parameterized.expand( - [ - [ - "non numeric string", - "Trentham monkey forest", - "invalid_input", - "A valid integer is required.", - ], - [ - "negative number", - "-1", - "min_value", - "Ensure this value is greater than or equal to 0.", - ], - [ - "greater than 15000", - "15001", - "max_value", - "Ensure this value is less than or equal to 15000.", - ], - ["too many digits", "0.5", "invalid_input", "A valid integer is required."], - ] - ) - def test_invalid_session_recording_minimum_duration( - self, _name: str, provided_value: str, expected_code: str, expected_error: str - ) -> None: - response = self.client.patch( - "/api/projects/@current/", - {"session_recording_minimum_duration_milliseconds": provided_value}, - ) - assert response.status_code == status.HTTP_400_BAD_REQUEST - assert response.json() == { - "attr": "session_recording_minimum_duration_milliseconds", - "code": expected_code, - "detail": expected_error, - "type": "validation_error", - } - - @parameterized.expand( - [ - [ - "string", - "Marple bridge", - "invalid_input", - "Must provide a dictionary or None.", - ], - ["numeric string", "-1", "invalid_input", "Must provide a dictionary or None."], - ["numeric", 1, "invalid_input", "Must provide a dictionary or None."], - ["numeric positive string", "1", "invalid_input", "Must provide a dictionary or None."], - [ - "unexpected json - no id", - {"key": "something"}, - "invalid_input", - "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", - ], - [ - "unexpected json - no key", - {"id": 1}, - "invalid_input", - "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", - ], - [ - "unexpected json - only variant", - {"variant": "1"}, - "invalid_input", - "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", - ], - [ - "unexpected json - variant must be string", - {"variant": 1}, - "invalid_input", - "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", - ], - [ - "unexpected json - missing id", - {"key": "one", "variant": "1"}, - "invalid_input", - "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", - ], - [ - "unexpected json - missing key", - {"id": "one", "variant": "1"}, - "invalid_input", - "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", - ], - [ - "unexpected json - neither", - {"wat": "wat"}, - "invalid_input", - "Must provide a dictionary with only 'id' and 'key' keys. _or_ only 'id', 'key', and 'variant' keys.", - ], - ] - ) - def test_invalid_session_recording_linked_flag( - self, _name: str, provided_value: Any, expected_code: str, expected_error: str - ) -> None: - response = self._patch_linked_flag_config(provided_value, expected_status=status.HTTP_400_BAD_REQUEST) - - assert response.json() == { - "attr": "session_recording_linked_flag", - "code": expected_code, - "detail": expected_error, - "type": "validation_error", - } - - def test_can_set_and_unset_session_recording_linked_flag(self) -> None: - self._patch_linked_flag_config({"id": 1, "key": "provided_value"}) - self._assert_linked_flag_config({"id": 1, "key": "provided_value"}) - - self._patch_linked_flag_config(None) - self._assert_linked_flag_config(None) - - def test_can_set_and_unset_session_recording_linked_flag_variant(self) -> None: - self._patch_linked_flag_config({"id": 1, "key": "provided_value", "variant": "test"}) - self._assert_linked_flag_config({"id": 1, "key": "provided_value", "variant": "test"}) - - self._patch_linked_flag_config(None) - self._assert_linked_flag_config(None) - - @parameterized.expand( - [ - [ - "string", - "Marple bridge", - "invalid_input", - "Must provide a dictionary or None.", - ], - ["numeric", "-1", "invalid_input", "Must provide a dictionary or None."], - [ - "unexpected json - no recordX", - {"key": "something"}, - "invalid_input", - "Must provide a dictionary with only 'recordHeaders' and/or 'recordBody' keys.", - ], - ] - ) - def test_invalid_session_recording_network_payload_capture_config( - self, _name: str, provided_value: str, expected_code: str, expected_error: str - ) -> None: - response = self.client.patch( - "/api/projects/@current/", {"session_recording_network_payload_capture_config": provided_value} - ) - assert response.status_code == status.HTTP_400_BAD_REQUEST - assert response.json() == { - "attr": "session_recording_network_payload_capture_config", - "code": expected_code, - "detail": expected_error, - "type": "validation_error", - } - - def test_can_set_and_unset_session_recording_network_payload_capture_config(self) -> None: - # can set just one - first_patch_response = self.client.patch( - "/api/projects/@current/", - {"session_recording_network_payload_capture_config": {"recordHeaders": True}}, - ) - assert first_patch_response.status_code == status.HTTP_200_OK - get_response = self.client.get("/api/projects/@current/") - assert get_response.json()["session_recording_network_payload_capture_config"] == {"recordHeaders": True} - - # can set the other - first_patch_response = self.client.patch( - "/api/projects/@current/", - {"session_recording_network_payload_capture_config": {"recordBody": False}}, - ) - assert first_patch_response.status_code == status.HTTP_200_OK - get_response = self.client.get("/api/projects/@current/") - assert get_response.json()["session_recording_network_payload_capture_config"] == {"recordBody": False} + self._patch_session_replay_config( + {"ai_config": {"opt_in": None, "included_event_properties": ["something"]}} + ) + # even though opt_in was not provided in the patch it should be preserved + self._assert_replay_config_is({"ai_config": {"opt_in": None, "included_event_properties": ["something"]}}) + + # but we don't go into the next nested level and patch that data + # sending a new value without the original + self._patch_session_replay_config({"ai_config": {"included_event_properties": ["and another"]}}) + # and the existing second level nesting is not preserved + self._assert_replay_config_is({"ai_config": {"opt_in": None, "included_event_properties": ["and another"]}}) + + def _assert_replay_config_is(self, expected: dict[str, Any] | None) -> HttpResponse: + get_response = self.client.get("/api/environments/@current/") + assert get_response.status_code == status.HTTP_200_OK, get_response.json() + assert get_response.json()["session_replay_config"] == expected + + return get_response + + def _patch_session_replay_config( + self, config: dict[str, Any] | None, expected_status: int = status.HTTP_200_OK + ) -> HttpResponse: + patch_response = self.client.patch( + "/api/environments/@current/", + {"session_replay_config": config}, + ) + assert patch_response.status_code == expected_status, patch_response.json() - # can unset both - response = self.client.patch( - "/api/projects/@current/", {"session_recording_network_payload_capture_config": None} - ) - assert response.status_code == status.HTTP_200_OK - second_get_response = self.client.get("/api/projects/@current/") - assert second_get_response.json()["session_recording_network_payload_capture_config"] is None + return patch_response - def test_can_set_and_unset_session_replay_config(self) -> None: - # can set - self._patch_session_replay_config({"record_canvas": True}) - self._assert_replay_config_is({"record_canvas": True}) + def _assert_linked_flag_config(self, expected_config: dict | None) -> HttpResponse: + response = self.client.get("/api/environments/@current/") + assert response.status_code == status.HTTP_200_OK + assert response.json()["session_recording_linked_flag"] == expected_config + return response - # can unset - self._patch_session_replay_config(None) - self._assert_replay_config_is(None) + def _patch_linked_flag_config( + self, config: dict | None, expected_status: int = status.HTTP_200_OK + ) -> HttpResponse: + response = self.client.patch("/api/environments/@current/", {"session_recording_linked_flag": config}) + assert response.status_code == expected_status, response.json() + return response - @parameterized.expand( - [ - [ - "string", - "Marple bridge", - "invalid_input", - "Must provide a dictionary or None.", - ], - ["numeric", "-1", "invalid_input", "Must provide a dictionary or None."], - [ - "unexpected json - no record", - {"key": "something"}, - "invalid_input", - "Must provide a dictionary with only allowed keys: included_event_properties, opt_in, preferred_events, excluded_events, important_user_properties.", - ], - ] - ) - def test_invalid_session_replay_config_ai_config( - self, _name: str, provided_value: str, expected_code: str, expected_error: str - ) -> None: - response = self._patch_session_replay_config( - {"ai_config": provided_value}, expected_status=status.HTTP_400_BAD_REQUEST - ) - assert response.json() == { - "attr": "session_replay_config", - "code": expected_code, - "detail": expected_error, - "type": "validation_error", - } - - def test_can_set_and_unset_session_replay_config_ai_config(self) -> None: - # can set just the opt-in - self._patch_session_replay_config({"ai_config": {"opt_in": True}}) - self._assert_replay_config_is({"ai_config": {"opt_in": True}}) - - # can set some preferences - self._patch_session_replay_config({"ai_config": {"opt_in": False, "included_event_properties": ["something"]}}) - self._assert_replay_config_is({"ai_config": {"opt_in": False, "included_event_properties": ["something"]}}) - - self._patch_session_replay_config({"ai_config": None}) - self._assert_replay_config_is({"ai_config": None}) - - def test_can_set_replay_configs_without_providing_them_all(self) -> None: - # can set just the opt-in - self._patch_session_replay_config({"ai_config": {"opt_in": True}}) - self._assert_replay_config_is({"ai_config": {"opt_in": True}}) - - self._patch_session_replay_config({"record_canvas": True}) - self._assert_replay_config_is({"record_canvas": True, "ai_config": {"opt_in": True}}) - - def test_can_set_replay_configs_without_providing_them_all_even_when_either_side_is_none(self) -> None: - # because we do some dictionary copying we need a regression test to ensure we can always set and unset keys - self._patch_session_replay_config({"record_canvas": True, "ai_config": {"opt_in": True}}) - self._assert_replay_config_is({"record_canvas": True, "ai_config": {"opt_in": True}}) - - self._patch_session_replay_config({"record_canvas": None}) - self._assert_replay_config_is({"record_canvas": None, "ai_config": {"opt_in": True}}) - - # top-level from having a value to None - self._patch_session_replay_config(None) - self._assert_replay_config_is(None) - - # top-level from None to having a value - self._patch_session_replay_config({"ai_config": None}) - self._assert_replay_config_is({"ai_config": None}) - - # next-level from None to having a value - self._patch_session_replay_config({"ai_config": {"opt_in": True}}) - self._assert_replay_config_is({"ai_config": {"opt_in": True}}) - - # next-level from having a value to None - self._patch_session_replay_config({"ai_config": None}) - self._assert_replay_config_is({"ai_config": None}) - - def test_can_set_replay_configs_patch_session_replay_config_one_level_deep(self) -> None: - # can set just the opt-in - self._patch_session_replay_config({"ai_config": {"opt_in": True}}) - self._assert_replay_config_is({"ai_config": {"opt_in": True}}) - - self._patch_session_replay_config({"ai_config": {"included_event_properties": ["something"]}}) - # even though opt_in was not provided in the patch it should be preserved - self._assert_replay_config_is({"ai_config": {"opt_in": True, "included_event_properties": ["something"]}}) - - self._patch_session_replay_config({"ai_config": {"opt_in": None, "included_event_properties": ["something"]}}) - # even though opt_in was not provided in the patch it should be preserved - self._assert_replay_config_is({"ai_config": {"opt_in": None, "included_event_properties": ["something"]}}) - - # but we don't go into the next nested level and patch that data - # sending a new value without the original - self._patch_session_replay_config({"ai_config": {"included_event_properties": ["and another"]}}) - # and the existing second level nesting is not preserved - self._assert_replay_config_is({"ai_config": {"opt_in": None, "included_event_properties": ["and another"]}}) - - def _assert_replay_config_is(self, expected: dict[str, Any] | None) -> HttpResponse: - get_response = self.client.get("/api/projects/@current/") - assert get_response.status_code == status.HTTP_200_OK, get_response.json() - assert get_response.json()["session_replay_config"] == expected - - return get_response - - def _patch_session_replay_config( - self, config: dict[str, Any] | None, expected_status: int = status.HTTP_200_OK - ) -> HttpResponse: - patch_response = self.client.patch( - "/api/projects/@current/", - {"session_replay_config": config}, - ) - assert patch_response.status_code == expected_status, patch_response.json() + return TestTeamAPI - return patch_response - def _assert_linked_flag_config(self, expected_config: dict | None) -> HttpResponse: - response = self.client.get("/api/projects/@current/") - assert response.status_code == status.HTTP_200_OK - assert response.json()["session_recording_linked_flag"] == expected_config - return response +class EnvironmentToProjectRewriteClient(test.APIClient): + """ + This client rewrites all requests to the /api/environments/ endpoint ("proper" environments endpoint) + to /api/projects/ (previously known as the "team" endpoint). Allows us to test for backwards compatibility of + the /api/projects/ endpoint - for use in `test_project.py`. + """ - def _patch_linked_flag_config(self, config: dict | None, expected_status: int = status.HTTP_200_OK) -> HttpResponse: - response = self.client.patch("/api/projects/@current/", {"session_recording_linked_flag": config}) - assert response.status_code == expected_status, response.json() - return response + def generic( + self, + method, + path, + data="", + content_type="application/octet-stream", + secure=False, + *, + headers=None, + **extra, + ): + path = path.replace("/api/environments/", "/api/projects/") + return super().generic(method, path, data, content_type, secure, headers=headers, **extra) def create_team(organization: Organization, name: str = "Test team", timezone: str = "UTC") -> Team: @@ -1051,10 +1104,5 @@ def create_team(organization: Organization, name: str = "Test team", timezone: s ) -async def acreate_team(organization: Organization, name: str = "Test team", timezone: str = "UTC") -> Team: - """ - This is a helper that just creates a team. It currently uses the orm, but we - could use either the api, or django admin to create, to get better parity - with real world scenarios. - """ - return await sync_to_async(create_team)(organization, name=name, timezone=timezone) +class TestTeamAPI(team_api_test_factory()): + pass diff --git a/posthog/models/team/team.py b/posthog/models/team/team.py index 10e658022f386..de4e0b9e55411 100644 --- a/posthog/models/team/team.py +++ b/posthog/models/team/team.py @@ -26,6 +26,7 @@ from posthog.models.filters.mixins.utils import cached_property from posthog.models.filters.utils import GroupTypeIndex from posthog.models.instance_setting import get_instance_setting +from posthog.models.organization import Organization from posthog.models.signals import mutable_receiver from posthog.models.utils import ( UUIDClassicModel, @@ -87,9 +88,11 @@ def set_test_account_filters(self, organization: Optional[Any]) -> list: ] return filters - def create_with_data(self, user: Any = None, default_dashboards: bool = True, **kwargs) -> "Team": - kwargs["test_account_filters"] = self.set_test_account_filters(kwargs.get("organization")) - team = cast("Team", self.create(**kwargs)) + def create_with_data( + self, user: Any = None, default_dashboards: bool = True, *, organization: Organization, **kwargs + ) -> "Team": + kwargs["test_account_filters"] = self.set_test_account_filters(organization) + team = cast("Team", self.create(organization=organization, **kwargs)) # Create default dashboards (skipped for demo projects) if default_dashboards: From eeca4227daad814f658309638bc03cae61448bd0 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Wed, 28 Aug 2024 13:29:47 +0100 Subject: [PATCH 13/32] Make mypy happy --- ee/api/test/test_team.py | 2 +- posthog/api/test/test_team.py | 2 +- posthog/models/activity_logging/activity_log.py | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ee/api/test/test_team.py b/ee/api/test/test_team.py index 860bdfe87a452..254b6aa337382 100644 --- a/ee/api/test/test_team.py +++ b/ee/api/test/test_team.py @@ -14,7 +14,7 @@ from posthog.test.base import FuzzyInt -def team_enterprise_api_test_factory(): +def team_enterprise_api_test_factory(): # type: ignore class TestTeamEnterpriseAPI(APILicensedTest): CLASS_DATA_LEVEL_SETUP = False diff --git a/posthog/api/test/test_team.py b/posthog/api/test/test_team.py index 1cce0f880542d..7391a79cb3317 100644 --- a/posthog/api/test/test_team.py +++ b/posthog/api/test/test_team.py @@ -1104,5 +1104,5 @@ def create_team(organization: Organization, name: str = "Test team", timezone: s ) -class TestTeamAPI(team_api_test_factory()): +class TestTeamAPI(team_api_test_factory()): # type: ignore pass diff --git a/posthog/models/activity_logging/activity_log.py b/posthog/models/activity_logging/activity_log.py index 82c13105f1ebb..2f89521adb8c0 100644 --- a/posthog/models/activity_logging/activity_log.py +++ b/posthog/models/activity_logging/activity_log.py @@ -3,6 +3,7 @@ from datetime import datetime from decimal import Decimal from typing import Any, Literal, Optional, Union +from uuid import UUID import structlog from django.core.paginator import Paginator @@ -368,10 +369,10 @@ def dict_changes_between( def log_activity( *, - organization_id: Optional[UUIDT], + organization_id: Optional[UUID], team_id: int, user: Optional[User], - item_id: Optional[Union[int, str, UUIDT]], + item_id: Optional[Union[int, str, UUID]], scope: str, activity: str, detail: Detail, From a6171db33374ff67a0b88db156cdd21409e61a91 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Sun, 1 Sep 2024 01:50:54 +0200 Subject: [PATCH 14/32] Make mypy happier --- posthog/api/test/test_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posthog/api/test/test_project.py b/posthog/api/test/test_project.py index 144cc49002c0b..a3da3c81f9ce0 100644 --- a/posthog/api/test/test_project.py +++ b/posthog/api/test/test_project.py @@ -1,7 +1,7 @@ from posthog.api.test.test_team import EnvironmentToProjectRewriteClient, team_api_test_factory -class TestProjectAPI(team_api_test_factory()): +class TestProjectAPI(team_api_test_factory()): # type: ignore """ We inherit from TestTeamAPI, as previously /api/projects/ referred to the Team model, which used to mean "project". Now as Team means "environment" and Project is separate, we must ensure backward compatibility of /api/projects/. From 08cc28657453a2dc0577722eb846bc4cc8a5b912 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Mon, 2 Sep 2024 11:54:04 +0200 Subject: [PATCH 15/32] Update mypy-baseline.txt --- mypy-baseline.txt | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 2a1b0092f3f1b..82d14674239cb 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -356,18 +356,12 @@ ee/clickhouse/queries/funnels/funnel_correlation.py:0: error: Statement is unrea posthog/api/insight.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] posthog/api/dashboards/dashboard.py:0: error: Argument 1 to "dashboard_queryset" of "DashboardTile" has incompatible type "DashboardTile_RelatedManager"; expected "QuerySet[Any, Any]" [arg-type] posthog/api/person.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] -posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Argument 1 to "loads" has incompatible type "str | None"; expected "str | bytes | bytearray" [arg-type] -posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Argument "user" to "log_activity" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type] -posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Argument "user" to "log_activity" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type] -posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Cannot determine type of "group_properties_filter_group" [has-type] posthog/caching/insight_caching_state.py:0: error: Argument "params" to "execute" of "CursorWrapper" has incompatible type "list[object]"; expected "Sequence[bool | int | float | Decimal | str | <6 more items> | None] | Mapping[str, bool | int | float | Decimal | str | <6 more items> | None] | None" [arg-type] posthog/api/cohort.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] -posthog/api/cohort.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/api/cohort.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/cohort.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] posthog/caching/insights_api.py:0: error: Unsupported operand types for >= ("datetime" and "None") [operator] posthog/caching/insights_api.py:0: note: Right operand is of type "datetime | None" @@ -375,8 +369,6 @@ posthog/api/feature_flag.py:0: error: Item "Sequence[Any]" of "Any | Sequence[An posthog/api/feature_flag.py:0: error: Item "None" of "Any | Sequence[Any] | None" has no attribute "filters" [union-attr] posthog/api/feature_flag.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] posthog/api/feature_flag.py:0: error: Argument 2 to "get_all_feature_flags" has incompatible type "str | None"; expected "str" [arg-type] -posthog/api/feature_flag.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/api/feature_flag.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/hogql_queries/web_analytics/web_analytics_query_runner.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/hogql_queries/web_analytics/web_analytics_query_runner.py:0: error: Argument 1 to "append" of "list" has incompatible type "EventPropertyFilter"; expected "Expr" [arg-type] posthog/hogql_queries/insights/trends/trends_query_runner.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] @@ -400,8 +392,6 @@ posthog/hogql_queries/insights/lifecycle_query_runner.py:0: error: Item "SelectU posthog/hogql_queries/insights/lifecycle_query_runner.py:0: error: Item "None" of "JoinExpr | Any | None" has no attribute "sample" [union-attr] posthog/hogql_queries/insights/funnels/funnels_query_runner.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/survey.py:0: error: Incompatible types in assignment (expression has type "Any | Sequence[Any] | None", variable has type "Survey | None") [assignment] -posthog/api/survey.py:0: error: Argument "item_id" to "log_activity" has incompatible type "UUID"; expected "int | str | UUIDT | None" [arg-type] -posthog/api/survey.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/survey.py:0: error: Item "list[_ErrorFullDetails]" of "_FullDetailDict | list[_ErrorFullDetails] | dict[str, _ErrorFullDetails]" has no attribute "get" [union-attr] posthog/api/survey.py:0: error: Item "object" of "object | Any" has no attribute "__iter__" (not iterable) [union-attr] posthog/hogql_queries/web_analytics/web_overview.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] @@ -433,9 +423,6 @@ posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "tiles" [union-attr] posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "tiles" [union-attr] posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "delete" [union-attr] -posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/tasks/test/test_update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "filters" [union-attr] posthog/tasks/test/test_stop_surveys_reached_target.py:0: error: No overload variant of "__sub__" of "datetime" matches argument type "None" [operator] posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: Possible overload variants: @@ -578,7 +565,6 @@ posthog/api/organization_feature_flag.py:0: error: Invalid index type "str | Non posthog/api/organization_feature_flag.py:0: error: Invalid index type "str | None" for "dict[str, int]"; expected type "str" [index] posthog/api/organization_feature_flag.py:0: error: Invalid index type "str | None" for "dict[str, int]"; expected type "str" [index] posthog/api/notebook.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "str | None") [assignment] -posthog/api/exports.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "DataWarehouseCredential | Combinable | None") [assignment] posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "str | int | Combinable") [assignment] posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "dict[str, dict[str, str | bool]] | dict[str, str]", variable has type "dict[str, dict[str, str]]") [assignment] @@ -825,10 +811,8 @@ posthog/warehouse/external_data_source/source.py:0: error: Argument 1 to "_creat posthog/temporal/tests/batch_exports/test_redshift_batch_export_workflow.py:0: error: Incompatible types in assignment (expression has type "str | int", variable has type "int") [assignment] posthog/api/sharing.py:0: error: Item "None" of "list[Any] | None" has no attribute "__iter__" (not iterable) [union-attr] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "organization" [union-attr] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID | Any"; expected "UUIDT | None" [arg-type] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "id" [union-attr] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "organization" [union-attr] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID | Any"; expected "UUIDT | None" [arg-type] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "id" [union-attr] posthog/api/plugin.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str | int | Combinable") [assignment] posthog/api/plugin.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str | int | Combinable") [assignment] @@ -838,10 +822,7 @@ posthog/api/plugin.py:0: error: Incompatible type for "file_name" of "PluginAtta posthog/api/plugin.py:0: error: Incompatible type for "file_size" of "PluginAttachment" (got "int | None", expected "float | int | str | Combinable") [misc] posthog/api/plugin.py:0: error: Item "None" of "IO[Any] | None" has no attribute "read" [union-attr] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "organization" [union-attr] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID | Any"; expected "UUIDT | None" [arg-type] posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "id" [union-attr] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] -posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] From 3f6d2d94d0b6709011ea520ac5d43e36d75430aa Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Tue, 3 Sep 2024 18:23:43 +0200 Subject: [PATCH 16/32] More DRY --- posthog/api/project.py | 122 ++++++++++-------- posthog/api/team.py | 36 +----- .../models/activity_logging/activity_log.py | 1 + posthog/models/team/team.py | 37 +++++- 4 files changed, 108 insertions(+), 88 deletions(-) diff --git a/posthog/api/project.py b/posthog/api/project.py index aad224ffb1c9e..39c843f4f8b2f 100644 --- a/posthog/api/project.py +++ b/posthog/api/project.py @@ -2,7 +2,6 @@ from functools import cached_property from typing import Any, Optional, cast -from django.core.cache import cache from django.shortcuts import get_object_or_404 from loginas.utils import is_impersonated_session from rest_framework import exceptions, request, response, serializers, viewsets @@ -17,7 +16,6 @@ from posthog.jwt import PosthogJwtAudience, encode_jwt from posthog.models import User from posthog.models.activity_logging.activity_log import ( - Change, Detail, dict_changes_between, load_activity, @@ -30,9 +28,9 @@ from posthog.models.personal_api_key import APIScopeObjectOrNotSupported from posthog.models.project import Project from posthog.models.signals import mute_selected_signals -from posthog.models.team.team import set_team_in_cache +from posthog.models.team.team import Team from posthog.models.team.util import delete_batch_exports, delete_bulky_postgres_data -from posthog.models.utils import UUIDT, generate_random_token_project +from posthog.models.utils import UUIDT from posthog.permissions import ( APIScopePermission, OrganizationAdminWritePermissions, @@ -220,7 +218,17 @@ def create(self, validated_data: dict[str, Any], **kwargs) -> Project: request.user.save() log_activity( - organization_id=team.organization_id, + organization_id=project.organization_id, + team_id=project.pk, + user=request.user, + was_impersonated=is_impersonated_session(request), + scope="Project", + item_id=project.pk, + activity="created", + detail=Detail(name=str(project.name)), + ) + log_activity( + organization_id=project.organization_id, team_id=team.pk, user=request.user, was_impersonated=is_impersonated_session(request), @@ -235,6 +243,7 @@ def create(self, validated_data: dict[str, Any], **kwargs) -> Project: def update(self, instance: Project, validated_data: dict[str, Any]) -> Project: team = instance.passthrough_team team_before_update = team.__dict__.copy() + project_before_update = instance.__dict__.copy() if ( "session_replay_config" in validated_data @@ -279,22 +288,41 @@ def update(self, instance: Project, validated_data: dict[str, Any]) -> Project: team.save() team_after_update = team.__dict__.copy() - changes = dict_changes_between("Team", team_before_update, team_after_update, use_field_exclusions=True) - - log_activity( - organization_id=cast(UUIDT, instance.organization_id), - team_id=instance.pk, - user=cast(User, self.context["request"].user), - was_impersonated=is_impersonated_session(request), - scope="Team", - item_id=instance.pk, - activity="updated", - detail=Detail( - name=str(instance.name), - changes=changes, - ), + project_after_update = instance.__dict__.copy() + team_changes = dict_changes_between("Team", team_before_update, team_after_update, use_field_exclusions=True) + project_changes = dict_changes_between( + "Project", project_before_update, project_after_update, use_field_exclusions=True ) + if team_changes: + log_activity( + organization_id=cast(UUIDT, instance.organization_id), + team_id=instance.pk, + user=cast(User, self.context["request"].user), + was_impersonated=is_impersonated_session(request), + scope="Team", + item_id=instance.pk, + activity="updated", + detail=Detail( + name=str(team.name), + changes=team_changes, + ), + ) + if project_changes: + log_activity( + organization_id=cast(UUIDT, instance.organization_id), + team_id=instance.pk, + user=cast(User, self.context["request"].user), + was_impersonated=is_impersonated_session(request), + scope="Project", + item_id=instance.pk, + activity="updated", + detail=Detail( + name=str(instance.name), + changes=project_changes, + ), + ) + return instance @@ -373,7 +401,7 @@ def perform_destroy(self, project: Project): user = cast(User, self.request.user) - teams = list(project.teams.all()) + teams: list[Team] = list(project.teams.all()) delete_bulky_postgres_data(team_ids=[team.id for team in teams]) delete_batch_exports(team_ids=[team.pk for team in teams]) @@ -399,13 +427,29 @@ def perform_destroy(self, project: Project): team_id=project_id, user=user, was_impersonated=is_impersonated_session(self.request), - scope="Team", # TODO: Change to "Project" + scope="Project", item_id=project_id, activity="deleted", detail=Detail(name=str(project_name)), ) - # TRICKY: We pass in Team here as otherwise the access to "current_team" can fail if it was deleted - report_user_action(user, f"team deleted", team=teams[0]) # TODO: Change to "project deleted" + report_user_action( + user, + f"project deleted", + {"project_name": project_name}, + team=teams[0], + ) + for team in teams: + log_activity( + organization_id=cast(UUIDT, organization_id), + team_id=team.pk, + user=user, + was_impersonated=is_impersonated_session(self.request), + scope="Team", + item_id=team.pk, + activity="deleted", + detail=Detail(name=str(team.name)), + ) + report_user_action(user, f"team deleted", team=team) @action( methods=["PATCH"], @@ -415,32 +459,7 @@ def perform_destroy(self, project: Project): ) def reset_token(self, request: request.Request, id: str, **kwargs) -> response.Response: project = self.get_object() - team = project.passthrough_team - old_token = team.api_token - team.api_token = generate_random_token_project() - team.save() - - log_activity( - organization_id=team.organization_id, - team_id=team.pk, - user=cast(User, request.user), - was_impersonated=is_impersonated_session(request), - scope="Team", - item_id=team.pk, - activity="updated", - detail=Detail( - name=str(team.name), - changes=[ - Change( - type="Team", - action="changed", - field="api_token", - ) - ], - ), - ) - - set_team_in_cache(old_token, None) + project.passthrough_team.reset_token_and_save(is_impersonated_session=is_impersonated_session(request)) return response.Response(ProjectSerializer(project, context=self.get_serializer_context()).data) @action( @@ -450,12 +469,11 @@ def reset_token(self, request: request.Request, id: str, **kwargs) -> response.R ) def is_generating_demo_data(self, request: request.Request, id: str, **kwargs) -> response.Response: project = self.get_object() - cache_key = f"is_generating_demo_data_{project.pk}" - return response.Response({"is_generating_demo_data": cache.get(cache_key) == "True"}) + return response.Response({"is_generating_demo_data": project.passthrough_team.get_is_generating_demo_data()}) @action(methods=["GET"], detail=True) def activity(self, request: request.Request, **kwargs): - # TODO: Rework for Project scope + # TODO: This is currently the same as in TeamViewSet - we should rework for the Project scope limit = int(request.query_params.get("limit", "10")) page = int(request.query_params.get("page", "1")) diff --git a/posthog/api/team.py b/posthog/api/team.py index 9a10412a53db9..83abaff1970e7 100644 --- a/posthog/api/team.py +++ b/posthog/api/team.py @@ -3,7 +3,6 @@ from typing import Any, Optional, cast from datetime import timedelta -from django.core.cache import cache from django.shortcuts import get_object_or_404 from loginas.utils import is_impersonated_session from posthog.jwt import PosthogJwtAudience, encode_jwt @@ -18,7 +17,6 @@ from posthog.event_usage import report_user_action from posthog.models import Team, User from posthog.models.activity_logging.activity_log import ( - Change, Detail, dict_changes_between, load_activity, @@ -30,9 +28,8 @@ from posthog.models.organization import OrganizationMembership from posthog.models.personal_api_key import APIScopeObjectOrNotSupported from posthog.models.signals import mute_selected_signals -from posthog.models.team.team import set_team_in_cache from posthog.models.team.util import delete_batch_exports, delete_bulky_postgres_data -from posthog.models.utils import UUIDT, generate_random_token_project +from posthog.models.utils import UUIDT from posthog.permissions import ( CREATE_METHODS, APIScopePermission, @@ -457,7 +454,7 @@ def perform_destroy(self, team: Team): activity="deleted", detail=Detail(name=str(team_name)), ) - # TRICKY: We pass in Team here as otherwise the access to "current_team" can fail if it was deleted + # TRICKY: We pass in `team` here as access to `user.current_team` can fail if it was deleted report_user_action(user, f"team deleted", team=team) @action( @@ -468,31 +465,7 @@ def perform_destroy(self, team: Team): ) def reset_token(self, request: request.Request, id: str, **kwargs) -> response.Response: team = self.get_object() - old_token = team.api_token - team.api_token = generate_random_token_project() - team.save() - - log_activity( - organization_id=team.organization_id, - team_id=team.pk, - user=cast(User, request.user), - was_impersonated=is_impersonated_session(request), - scope="Team", - item_id=team.pk, - activity="updated", - detail=Detail( - name=str(team.name), - changes=[ - Change( - type="Team", - action="changed", - field="api_token", - ) - ], - ), - ) - - set_team_in_cache(old_token, None) + team.reset_token_and_save(is_impersonated_session=is_impersonated_session(request)) return response.Response(TeamSerializer(team, context=self.get_serializer_context()).data) @action( @@ -502,8 +475,7 @@ def reset_token(self, request: request.Request, id: str, **kwargs) -> response.R ) def is_generating_demo_data(self, request: request.Request, id: str, **kwargs) -> response.Response: team = self.get_object() - cache_key = f"is_generating_demo_data_{team.pk}" - return response.Response({"is_generating_demo_data": cache.get(cache_key) == "True"}) + return response.Response({"is_generating_demo_data": team.get_is_generating_demo_data()}) @action(methods=["GET"], detail=True) def activity(self, request: request.Request, **kwargs): diff --git a/posthog/models/activity_logging/activity_log.py b/posthog/models/activity_logging/activity_log.py index 2f89521adb8c0..35bf3f8751ffb 100644 --- a/posthog/models/activity_logging/activity_log.py +++ b/posthog/models/activity_logging/activity_log.py @@ -220,6 +220,7 @@ class Meta: "property_type_format", ], "Team": ["uuid", "updated_at", "api_token", "created_at", "id"], + "Project": ["id", "created_at"], } diff --git a/posthog/models/team/team.py b/posthog/models/team/team.py index de4e0b9e55411..b8e2d09400a44 100644 --- a/posthog/models/team/team.py +++ b/posthog/models/team/team.py @@ -1,9 +1,9 @@ import re from decimal import Decimal from functools import lru_cache -from typing import TYPE_CHECKING, Any, Optional, cast +from typing import Any, Optional, cast from zoneinfo import ZoneInfo - +from django.core import cache import posthoganalytics import pydantic import pytz @@ -40,8 +40,7 @@ from ...schema import HogQLQueryModifiers, PathCleaningFilter, PersonsOnEventsMode from .team_caching import get_team_in_cache, set_team_in_cache -if TYPE_CHECKING: - from posthog.models.user import User +from posthog.models.user import User TIMEZONES = [(tz, tz) for tz in pytz.all_timezones] @@ -449,6 +448,36 @@ def path_cleaning_filter_models(self) -> list[PathCleaningFilter]: continue return filters + def reset_token_and_save(self, *, is_impersonated_session: bool): + from posthog.models.activity_logging.activity_log import Change, Detail, log_activity + + old_token = self.api_token + self.api_token = generate_random_token_project() + self.save() + set_team_in_cache(old_token, None) + log_activity( + organization_id=self.organization_id, + team_id=self.pk, + user=cast(User, self.user), + was_impersonated=is_impersonated_session, + scope="Team", + item_id=self.pk, + activity="updated", + detail=Detail( + name=str(self.name), + changes=[ + Change( + type="Team", + action="changed", + field="api_token", + ) + ], + ), + ) + + def get_is_generating_demo_data(self) -> bool: + return cache.get(f"is_generating_demo_data_{self.pk}") == "True" + def all_users_with_access(self) -> QuerySet["User"]: from ee.models.explicit_team_membership import ExplicitTeamMembership from posthog.models.organization import OrganizationMembership From b397a27ae8ebe791e24938baa8435f9fee04de8f Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Wed, 4 Sep 2024 09:58:58 +0200 Subject: [PATCH 17/32] Fix undefined var --- posthog/models/team/team.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/posthog/models/team/team.py b/posthog/models/team/team.py index b8e2d09400a44..64d3f18c90076 100644 --- a/posthog/models/team/team.py +++ b/posthog/models/team/team.py @@ -1,7 +1,7 @@ import re from decimal import Decimal from functools import lru_cache -from typing import Any, Optional, cast +from typing import TYPE_CHECKING, Any, Optional, cast from zoneinfo import ZoneInfo from django.core import cache import posthoganalytics @@ -40,7 +40,8 @@ from ...schema import HogQLQueryModifiers, PathCleaningFilter, PersonsOnEventsMode from .team_caching import get_team_in_cache, set_team_in_cache -from posthog.models.user import User +if TYPE_CHECKING: + from posthog.models.user import User TIMEZONES = [(tz, tz) for tz in pytz.all_timezones] @@ -458,7 +459,7 @@ def reset_token_and_save(self, *, is_impersonated_session: bool): log_activity( organization_id=self.organization_id, team_id=self.pk, - user=cast(User, self.user), + user=cast("User", self.user), was_impersonated=is_impersonated_session, scope="Team", item_id=self.pk, From 1b349e4680f1c611019f61b30e333f4790785a85 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 08:29:09 +0000 Subject: [PATCH 18/32] Update query snapshots --- .../transforms/test/__snapshots__/test_in_cohort.ambr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr b/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr index 66203f817267f..f018e96ef067a 100644 --- a/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr +++ b/posthog/hogql/transforms/test/__snapshots__/test_in_cohort.ambr @@ -31,7 +31,7 @@ FROM events LEFT JOIN ( SELECT person_static_cohort.person_id AS cohort_person_id, 1 AS matched, person_static_cohort.cohort_id AS cohort_id FROM person_static_cohort - WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [13]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) + WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [4]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) WHERE and(equals(events.team_id, 420), 1, ifNull(equals(__in_cohort.matched, 1), 0)) LIMIT 100 SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1, format_csv_allow_double_quotes=0, max_ast_elements=4000000, max_expanded_ast_elements=4000000, max_bytes_before_external_group_by=0 @@ -42,7 +42,7 @@ FROM events LEFT JOIN ( SELECT person_id AS cohort_person_id, 1 AS matched, cohort_id FROM static_cohort_people - WHERE in(cohort_id, [13])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) + WHERE in(cohort_id, [4])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) WHERE and(1, equals(__in_cohort.matched, 1)) LIMIT 100 ''' @@ -55,7 +55,7 @@ FROM events LEFT JOIN ( SELECT person_static_cohort.person_id AS cohort_person_id, 1 AS matched, person_static_cohort.cohort_id AS cohort_id FROM person_static_cohort - WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [14]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) + WHERE and(equals(person_static_cohort.team_id, 420), in(person_static_cohort.cohort_id, [5]))) AS __in_cohort ON equals(__in_cohort.cohort_person_id, events.person_id) WHERE and(equals(events.team_id, 420), 1, ifNull(equals(__in_cohort.matched, 1), 0)) LIMIT 100 SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1, format_csv_allow_double_quotes=0, max_ast_elements=4000000, max_expanded_ast_elements=4000000, max_bytes_before_external_group_by=0 @@ -66,7 +66,7 @@ FROM events LEFT JOIN ( SELECT person_id AS cohort_person_id, 1 AS matched, cohort_id FROM static_cohort_people - WHERE in(cohort_id, [14])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) + WHERE in(cohort_id, [5])) AS __in_cohort ON equals(__in_cohort.cohort_person_id, person_id) WHERE and(1, equals(__in_cohort.matched, 1)) LIMIT 100 ''' From 083b86cd729a0665433a4cb8a11c2e843d59602b Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Wed, 4 Sep 2024 22:49:12 +0200 Subject: [PATCH 19/32] Fix missing kwarg --- posthog/api/project.py | 4 +++- posthog/api/team.py | 2 +- posthog/models/activity_logging/activity_log.py | 1 + posthog/models/team/team.py | 6 +++--- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/posthog/api/project.py b/posthog/api/project.py index 39c843f4f8b2f..6169336a007c6 100644 --- a/posthog/api/project.py +++ b/posthog/api/project.py @@ -459,7 +459,9 @@ def perform_destroy(self, project: Project): ) def reset_token(self, request: request.Request, id: str, **kwargs) -> response.Response: project = self.get_object() - project.passthrough_team.reset_token_and_save(is_impersonated_session=is_impersonated_session(request)) + project.passthrough_team.reset_token_and_save( + user=request.user, is_impersonated_session=is_impersonated_session(request) + ) return response.Response(ProjectSerializer(project, context=self.get_serializer_context()).data) @action( diff --git a/posthog/api/team.py b/posthog/api/team.py index 83abaff1970e7..66e2347ce60c7 100644 --- a/posthog/api/team.py +++ b/posthog/api/team.py @@ -465,7 +465,7 @@ def perform_destroy(self, team: Team): ) def reset_token(self, request: request.Request, id: str, **kwargs) -> response.Response: team = self.get_object() - team.reset_token_and_save(is_impersonated_session=is_impersonated_session(request)) + team.reset_token_and_save(user=request.user, is_impersonated_session=is_impersonated_session(request)) return response.Response(TeamSerializer(team, context=self.get_serializer_context()).data) @action( diff --git a/posthog/models/activity_logging/activity_log.py b/posthog/models/activity_logging/activity_log.py index 35bf3f8751ffb..3b8489d897645 100644 --- a/posthog/models/activity_logging/activity_log.py +++ b/posthog/models/activity_logging/activity_log.py @@ -41,6 +41,7 @@ "SessionRecordingPlaylist", "Comment", "Team", + "Project", ] ChangeAction = Literal["changed", "created", "deleted", "merged", "split", "exported"] diff --git a/posthog/models/team/team.py b/posthog/models/team/team.py index 64d3f18c90076..9be00476f58cf 100644 --- a/posthog/models/team/team.py +++ b/posthog/models/team/team.py @@ -3,7 +3,7 @@ from functools import lru_cache from typing import TYPE_CHECKING, Any, Optional, cast from zoneinfo import ZoneInfo -from django.core import cache +from django.core.cache import cache import posthoganalytics import pydantic import pytz @@ -449,7 +449,7 @@ def path_cleaning_filter_models(self) -> list[PathCleaningFilter]: continue return filters - def reset_token_and_save(self, *, is_impersonated_session: bool): + def reset_token_and_save(self, *, user: "User", is_impersonated_session: bool): from posthog.models.activity_logging.activity_log import Change, Detail, log_activity old_token = self.api_token @@ -459,7 +459,7 @@ def reset_token_and_save(self, *, is_impersonated_session: bool): log_activity( organization_id=self.organization_id, team_id=self.pk, - user=cast("User", self.user), + user=cast("User", user), was_impersonated=is_impersonated_session, scope="Team", item_id=self.pk, From 1343645a2117db5d00f57dd400b1436d0ba598eb Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Mon, 9 Sep 2024 21:19:30 +0200 Subject: [PATCH 20/32] Update projects API tests --- posthog/api/project.py | 24 ++++++++--------- posthog/api/test/test_team.py | 51 ++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/posthog/api/project.py b/posthog/api/project.py index 6169336a007c6..ca61df684f801 100644 --- a/posthog/api/project.py +++ b/posthog/api/project.py @@ -422,6 +422,18 @@ def perform_destroy(self, project: Project): ignore_conflicts=True, ) + for team in teams: + log_activity( + organization_id=cast(UUIDT, organization_id), + team_id=team.pk, + user=user, + was_impersonated=is_impersonated_session(self.request), + scope="Team", + item_id=team.pk, + activity="deleted", + detail=Detail(name=str(team.name)), + ) + report_user_action(user, f"team deleted", team=team) log_activity( organization_id=cast(UUIDT, organization_id), team_id=project_id, @@ -438,18 +450,6 @@ def perform_destroy(self, project: Project): {"project_name": project_name}, team=teams[0], ) - for team in teams: - log_activity( - organization_id=cast(UUIDT, organization_id), - team_id=team.pk, - user=user, - was_impersonated=is_impersonated_session(self.request), - scope="Team", - item_id=team.pk, - activity="deleted", - detail=Detail(name=str(team.name)), - ) - report_user_action(user, f"team deleted", team=team) @action( methods=["PATCH"], diff --git a/posthog/api/test/test_team.py b/posthog/api/test/test_team.py index 7391a79cb3317..0c69c2b6620d0 100644 --- a/posthog/api/test/test_team.py +++ b/posthog/api/test/test_team.py @@ -282,7 +282,7 @@ def test_delete_team_activity_log(self): # we can't query by API but can prove the log was recorded activity = [a.__dict__ for a in ActivityLog.objects.filter(team_id=team.pk).all()] - assert activity == [ + expected_activity = [ { "_state": ANY, "activity": "deleted", @@ -304,6 +304,31 @@ def test_delete_team_activity_log(self): "was_impersonated": False, }, ] + if self.client_class is EnvironmentToProjectRewriteClient: + expected_activity.insert( + 0, + { + "_state": ANY, + "activity": "deleted", + "created_at": ANY, + "detail": { + "changes": None, + "name": "Default project", + "short_id": None, + "trigger": None, + "type": None, + }, + "id": ANY, + "is_system": False, + "organization_id": ANY, + "team_id": team.pk, + "item_id": str(team.project_id), + "scope": "Project", + "user_id": self.user.pk, + "was_impersonated": False, + }, + ) + assert activity == expected_activity @patch("posthog.api.project.delete_bulky_postgres_data") @patch("posthog.api.team.delete_bulky_postgres_data") @@ -334,17 +359,25 @@ def test_delete_team_own_second( ).count(), 1, ) - mock_capture.assert_has_calls( - calls=[ + expected_capture_calls = [ + call( + self.user.distinct_id, + "membership level changed", + properties={"new_level": 8, "previous_level": 1, "$set": mock.ANY}, + groups=mock.ANY, + ), + call(self.user.distinct_id, "team deleted", properties={}, groups=mock.ANY), + ] + if self.client_class is EnvironmentToProjectRewriteClient: + expected_capture_calls.append( call( self.user.distinct_id, - "membership level changed", - properties={"new_level": 8, "previous_level": 1, "$set": mock.ANY}, + "project deleted", + properties={"project_name": "Default project"}, groups=mock.ANY, - ), - call(self.user.distinct_id, "team deleted", properties={}, groups=mock.ANY), - ] - ) + ) + ) + assert mock_capture.call_args_list == expected_capture_calls mock_delete_bulky_postgres_data.assert_called_once_with(team_ids=[team.pk]) def test_delete_bulky_postgres_data(self): From b5b9d35f85dc4e9ed050244699668574a525e429 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 19:31:48 +0000 Subject: [PATCH 21/32] Update query snapshots --- .../api/test/__snapshots__/test_api_docs.ambr | 94 ++--- .../api/test/__snapshots__/test_decide.ambr | 383 ++++++++++++++---- 2 files changed, 359 insertions(+), 118 deletions(-) diff --git a/posthog/api/test/__snapshots__/test_api_docs.ambr b/posthog/api/test/__snapshots__/test_api_docs.ambr index 9b470bb936f43..fb629e787c4f6 100644 --- a/posthog/api/test/__snapshots__/test_api_docs.ambr +++ b/posthog/api/test/__snapshots__/test_api_docs.ambr @@ -1,19 +1,7 @@ # serializer version: 1 # name: TestAPIDocsSchema.test_api_docs_generation_warnings_snapshot list([ - '/home/runner/work/posthog/posthog/posthog/api/organization.py: Warning [OrganizationViewSet > OrganizationSerializer]: unable to resolve type hint for function "get_metadata". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/organization.py: Warning [OrganizationViewSet > OrganizationSerializer]: unable to resolve type hint for function "get_member_count". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/batch_exports/http.py: Warning [BatchExportOrganizationViewSet]: could not derive type of path parameter "organization_id" because model "posthog.batch_exports.models.BatchExport" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/batch_exports/http.py: Warning [BatchExportOrganizationViewSet > BatchExportSerializer]: could not resolve serializer field "HogQLSelectQueryField(required=False)". Defaulting to "string"', - '/home/runner/work/posthog/posthog/posthog/api/plugin.py: Warning [PipelineDestinationsViewSet > PluginSerializer]: unable to resolve type hint for function "get_hog_function_migration_available". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/proxy_record.py: Warning [ProxyRecordViewset]: could not derive type of path parameter "organization_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/proxy_record.py: Warning [ProxyRecordViewset]: could not derive type of path parameter "id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/ee/api/role.py: Warning [RoleViewSet > RoleSerializer]: unable to resolve type hint for function "get_members". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/ee/api/role.py: Warning [RoleViewSet > RoleSerializer]: unable to resolve type hint for function "get_associated_flags". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/ee/api/role.py: Warning [RoleMembershipViewSet]: could not derive type of path parameter "organization_id" because model "ee.models.role.RoleMembership" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/action.py: Warning [ActionViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.action.action.Action" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/activity_log.py: Warning [ActivityLogViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.activity_logging.activity_log.ActivityLog" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/annotation.py: Warning [AnnotationsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.annotation.Annotation" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/plugin_log_entry.py: Warning [PluginLogEntryViewSet]: could not derive type of path parameter "plugin_config_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', "/home/runner/work/posthog/posthog/posthog/api/app_metrics.py: Error [AppMetricsViewSet]: exception raised while getting serializer. Hint: Is get_serializer_class() returning None or is get_queryset() not working without a request? Ignoring the view for now. (Exception: 'AppMetricsViewSet' should either include a `serializer_class` attribute, or override the `get_serializer_class()` method.)", '/home/runner/work/posthog/posthog/posthog/api/app_metrics.py: Warning [AppMetricsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.plugin.PluginConfig" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/app_metrics.py: Error [HistoricalExportsAppMetricsViewSet]: unable to guess serializer. This is graceful fallback handling for APIViews. Consider using GenericAPIView as view base class, if view is under your control. Either way you may want to add a serializer_class (or method). Ignoring view for now.', @@ -21,15 +9,8 @@ '/home/runner/work/posthog/posthog/posthog/api/app_metrics.py: Warning [HistoricalExportsAppMetricsViewSet]: could not derive type of path parameter "plugin_config_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/app_metrics.py: Warning [HistoricalExportsAppMetricsViewSet]: could not derive type of path parameter "id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/batch_exports/http.py: Warning [BatchExportViewSet]: could not derive type of path parameter "project_id" because model "posthog.batch_exports.models.BatchExport" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/batch_exports/http.py: Warning [BatchExportViewSet > BatchExportSerializer]: could not resolve serializer field "HogQLSelectQueryField(required=False)". Defaulting to "string"', '/home/runner/work/posthog/posthog/posthog/batch_exports/http.py: Warning [BatchExportRunViewSet]: could not derive type of path parameter "project_id" because model "posthog.batch_exports.models.BatchExportRun" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/cohort.py: Warning [CohortViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.cohort.cohort.Cohort" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/dashboards/dashboard_templates.py: Warning [DashboardTemplateViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.dashboard_templates.DashboardTemplate" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/dashboards/dashboard.py: Warning [DashboardsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.dashboard.Dashboard" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/ee/api/dashboard_collaborator.py: Warning [DashboardCollaboratorViewSet]: could not derive type of path parameter "project_id" because model "ee.models.dashboard_privilege.DashboardPrivilege" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/sharing.py: Warning [SharingConfigurationViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.sharing_configuration.SharingConfiguration" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/early_access_feature.py: Warning [EarlyAccessFeatureViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.early_access_feature.EarlyAccessFeature" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - "/home/runner/work/posthog/posthog/posthog/api/event_definition.py: Error [EventDefinitionViewSet]: exception raised while getting serializer. Hint: Is get_serializer_class() returning None or is get_queryset() not working without a request? Ignoring the view for now. (Exception: 'AnonymousUser' object has no attribute 'organization')", - '/home/runner/work/posthog/posthog/posthog/api/event_definition.py: Warning [EventDefinitionViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.event_definition.EventDefinition" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/event.py: Warning [EventViewSet]: could not derive type of path parameter "project_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/models/event/util.py: Warning [EventViewSet > ClickhouseEventSerializer]: unable to resolve type hint for function "get_id". Consider using a type hint or @extend_schema_field. Defaulting to string.', '/home/runner/work/posthog/posthog/posthog/models/event/util.py: Warning [EventViewSet > ClickhouseEventSerializer]: unable to resolve type hint for function "get_distinct_id". Consider using a type hint or @extend_schema_field. Defaulting to string.', @@ -40,29 +21,11 @@ '/home/runner/work/posthog/posthog/posthog/models/event/util.py: Warning [EventViewSet > ClickhouseEventSerializer]: unable to resolve type hint for function "get_elements". Consider using a type hint or @extend_schema_field. Defaulting to string.', '/home/runner/work/posthog/posthog/posthog/models/event/util.py: Warning [EventViewSet > ClickhouseEventSerializer]: unable to resolve type hint for function "get_elements_chain". Consider using a type hint or @extend_schema_field. Defaulting to string.', '/home/runner/work/posthog/posthog/posthog/api/event.py: Warning [EventViewSet]: could not derive type of path parameter "id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/ee/clickhouse/views/experiments.py: Warning [ClickhouseExperimentsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.experiment.Experiment" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/ee/api/explicit_team_member.py: Warning [ExplicitTeamMemberViewSet]: could not derive type of path parameter "project_id" because model "ee.models.explicit_team_membership.ExplicitTeamMembership" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/exports.py: Warning [ExportedAssetViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.exported_asset.ExportedAsset" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/exports.py: Warning [ExportedAssetViewSet > ExportedAssetSerializer]: unable to resolve type hint for function "has_content". Consider using a type hint or @extend_schema_field. Defaulting to string.', '/home/runner/work/posthog/posthog/posthog/api/exports.py: Warning [ExportedAssetViewSet > ExportedAssetSerializer]: unable to resolve type hint for function "filename". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/feature_flag.py: Warning [FeatureFlagViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.feature_flag.feature_flag.FeatureFlag" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/ee/api/feature_flag_role_access.py: Warning [FeatureFlagRoleAccessViewSet]: could not derive type of path parameter "project_id" because model "ee.models.feature_flag_role_access.FeatureFlagRoleAccess" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/ee/clickhouse/views/groups.py: Warning [ClickhouseGroupsView]: could not derive type of path parameter "project_id" because model "posthog.models.group.group.Group" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/ee/clickhouse/views/groups.py: Warning [ClickhouseGroupsTypesView]: could not derive type of path parameter "project_id" because model "posthog.models.group_type_mapping.GroupTypeMapping" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/ee/clickhouse/views/insights.py: Warning [ClickhouseInsightsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.insight.Insight" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_last_refresh". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_cache_target_age". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_next_allowed_client_refresh". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_result". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_hasMore". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_columns". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_timezone". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_is_cached". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_query_status". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_hogql". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [ClickhouseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_types". Consider using a type hint or @extend_schema_field. Defaulting to string.', - '/home/runner/work/posthog/posthog/posthog/api/notebook.py: Warning [NotebookViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.notebook.notebook.Notebook" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/person.py: Warning [PersonViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.person.person.Person" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/ee/clickhouse/views/groups.py: Warning [GroupsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.group.group.Group" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/ee/clickhouse/views/person.py: Warning [EnterprisePersonViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.person.person.Person" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/plugin.py: Warning [PipelineDestinationsConfigsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.plugin.PluginConfig" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/plugin.py: Warning [PipelineDestinationsConfigsViewSet > PluginConfigSerializer]: unable to resolve type hint for function "get_config". Consider using a type hint or @extend_schema_field. Defaulting to string.', @@ -73,28 +36,67 @@ '/home/runner/work/posthog/posthog/posthog/api/plugin.py: Warning [PipelineImportAppsConfigsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.plugin.PluginConfig" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/plugin.py: Warning [PipelineTransformationsConfigsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.plugin.PluginConfig" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/plugin.py: Warning [PluginConfigViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.plugin.PluginConfig" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/plugin_log_entry.py: Warning [PluginLogEntryViewSet]: could not derive type of path parameter "project_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/posthog/api/plugin_log_entry.py: Warning [PluginLogEntryViewSet]: could not derive type of path parameter "plugin_config_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', - "/home/runner/work/posthog/posthog/posthog/api/property_definition.py: Error [PropertyDefinitionViewSet]: exception raised while getting serializer. Hint: Is get_serializer_class() returning None or is get_queryset() not working without a request? Ignoring the view for now. (Exception: 'AnonymousUser' object has no attribute 'organization')", - '/home/runner/work/posthog/posthog/posthog/api/property_definition.py: Warning [PropertyDefinitionViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.property_definition.PropertyDefinition" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/query.py: Warning [QueryViewSet]: could not derive type of path parameter "project_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', '/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/pydantic/_internal/_model_construction.py: Warning [QueryViewSet > ModelMetaclass]: Encountered 2 components with identical names "Person" and different classes and . This will very likely result in an incorrect schema. Try renaming one.', '/home/runner/work/posthog/posthog/posthog/api/query.py: Warning [QueryViewSet]: could not derive type of path parameter "id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/query.py: Error [QueryViewSet]: unable to guess serializer. This is graceful fallback handling for APIViews. Consider using GenericAPIView as view base class, if view is under your control. Either way you may want to add a serializer_class (or method). Ignoring view for now.', - '/home/runner/work/posthog/posthog/ee/session_recordings/session_recording_playlist.py: Warning [SessionRecordingPlaylistViewSet]: could not derive type of path parameter "project_id" because model "posthog.session_recordings.models.session_recording_playlist.SessionRecordingPlaylist" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', - '/home/runner/work/posthog/posthog/ee/session_recordings/session_recording_playlist.py: Warning [SessionRecordingPlaylistViewSet]: could not derive type of path parameter "session_recording_id" because model "posthog.session_recordings.models.session_recording_playlist.SessionRecordingPlaylist" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/session_recordings/session_recording_api.py: Warning [SessionRecordingViewSet]: could not derive type of path parameter "project_id" because model "posthog.session_recordings.models.session_recording.SessionRecording" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/session_recordings/session_recording_api.py: Warning [SessionRecordingViewSet > SessionRecordingSerializer]: could not resolve field on model with path "viewed". This is likely a custom field that does some unknown magic. Maybe consider annotating the field/property? Defaulting to "string". (Exception: SessionRecording has no field named \'viewed\')', '/home/runner/work/posthog/posthog/posthog/api/person.py: Warning [SessionRecordingViewSet > SessionRecordingSerializer > MinimalPersonSerializer]: unable to resolve type hint for function "get_distinct_ids". Consider using a type hint or @extend_schema_field. Defaulting to string.', '/home/runner/work/posthog/posthog/posthog/session_recordings/session_recording_api.py: Warning [SessionRecordingViewSet > SessionRecordingSerializer]: unable to resolve type hint for function "storage". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/sharing.py: Warning [SharingConfigurationViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.sharing_configuration.SharingConfiguration" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/session.py: Warning [SessionViewSet]: could not derive type of path parameter "project_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/ee/api/subscription.py: Warning [SubscriptionViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.subscription.Subscription" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/ee/api/subscription.py: Warning [SubscriptionViewSet > SubscriptionSerializer]: unable to resolve type hint for function "summary". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/organization.py: Warning [OrganizationViewSet > OrganizationSerializer]: unable to resolve type hint for function "get_metadata". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/organization.py: Warning [OrganizationViewSet > OrganizationSerializer]: unable to resolve type hint for function "get_member_count". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/batch_exports/http.py: Warning [BatchExportOrganizationViewSet]: could not derive type of path parameter "organization_id" because model "posthog.batch_exports.models.BatchExport" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/plugin.py: Warning [PipelineDestinationsViewSet > PluginSerializer]: unable to resolve type hint for function "get_hog_function_migration_available". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/project.py: Warning [ProjectViewSet > ProjectSerializer]: could not resolve field on model with path "person_on_events_querying_enabled". This is likely a custom field that does some unknown magic. Maybe consider annotating the field/property? Defaulting to "string". (Exception: Project has no field named \'person_on_events_querying_enabled\')', + '/home/runner/work/posthog/posthog/posthog/api/project.py: Warning [ProjectViewSet > ProjectSerializer]: could not resolve field on model with path "default_modifiers". This is likely a custom field that does some unknown magic. Maybe consider annotating the field/property? Defaulting to "string". (Exception: Project has no field named \'default_modifiers\')', + '/home/runner/work/posthog/posthog/posthog/api/proxy_record.py: Warning [ProxyRecordViewset]: could not derive type of path parameter "organization_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/proxy_record.py: Warning [ProxyRecordViewset]: could not derive type of path parameter "id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. ) or annotating the parameter type with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/ee/api/role.py: Warning [RoleViewSet > RoleSerializer]: unable to resolve type hint for function "get_members". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/ee/api/role.py: Warning [RoleViewSet > RoleSerializer]: unable to resolve type hint for function "get_associated_flags". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/ee/api/role.py: Warning [RoleMembershipViewSet]: could not derive type of path parameter "organization_id" because model "ee.models.role.RoleMembership" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/action.py: Warning [ActionViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.action.action.Action" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/activity_log.py: Warning [ActivityLogViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.activity_logging.activity_log.ActivityLog" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/annotation.py: Warning [AnnotationsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.annotation.Annotation" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/cohort.py: Warning [CohortViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.cohort.cohort.Cohort" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/dashboards/dashboard_templates.py: Warning [DashboardTemplateViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.dashboard_templates.DashboardTemplate" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/dashboards/dashboard.py: Warning [DashboardsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.dashboard.Dashboard" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/ee/api/dashboard_collaborator.py: Warning [DashboardCollaboratorViewSet]: could not derive type of path parameter "project_id" because model "ee.models.dashboard_privilege.DashboardPrivilege" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/early_access_feature.py: Warning [EarlyAccessFeatureViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.early_access_feature.EarlyAccessFeature" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + "/home/runner/work/posthog/posthog/posthog/api/event_definition.py: Error [EventDefinitionViewSet]: exception raised while getting serializer. Hint: Is get_serializer_class() returning None or is get_queryset() not working without a request? Ignoring the view for now. (Exception: 'AnonymousUser' object has no attribute 'organization')", + '/home/runner/work/posthog/posthog/posthog/api/event_definition.py: Warning [EventDefinitionViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.event_definition.EventDefinition" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/ee/clickhouse/views/experiments.py: Warning [EnterpriseExperimentsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.experiment.Experiment" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/feature_flag.py: Warning [FeatureFlagViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.feature_flag.feature_flag.FeatureFlag" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/ee/api/feature_flag_role_access.py: Warning [FeatureFlagRoleAccessViewSet]: could not derive type of path parameter "project_id" because model "ee.models.feature_flag_role_access.FeatureFlagRoleAccess" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/ee/clickhouse/views/groups.py: Warning [GroupsTypesViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.group_type_mapping.GroupTypeMapping" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/ee/clickhouse/views/insights.py: Warning [EnterpriseInsightsViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.insight.Insight" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_last_refresh". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_cache_target_age". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_next_allowed_client_refresh". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_result". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_hasMore". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_columns". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_timezone". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_is_cached". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_query_status". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_hogql". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/insight.py: Warning [EnterpriseInsightsViewSet > InsightSerializer]: unable to resolve type hint for function "get_types". Consider using a type hint or @extend_schema_field. Defaulting to string.', + '/home/runner/work/posthog/posthog/posthog/api/notebook.py: Warning [NotebookViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.notebook.notebook.Notebook" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + "/home/runner/work/posthog/posthog/posthog/api/property_definition.py: Error [PropertyDefinitionViewSet]: exception raised while getting serializer. Hint: Is get_serializer_class() returning None or is get_queryset() not working without a request? Ignoring the view for now. (Exception: 'AnonymousUser' object has no attribute 'organization')", + '/home/runner/work/posthog/posthog/posthog/api/property_definition.py: Warning [PropertyDefinitionViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.property_definition.PropertyDefinition" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/ee/session_recordings/session_recording_playlist.py: Warning [SessionRecordingPlaylistViewSet]: could not derive type of path parameter "project_id" because model "posthog.session_recordings.models.session_recording_playlist.SessionRecordingPlaylist" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', + '/home/runner/work/posthog/posthog/ee/session_recordings/session_recording_playlist.py: Warning [SessionRecordingPlaylistViewSet]: could not derive type of path parameter "session_recording_id" because model "posthog.session_recordings.models.session_recording_playlist.SessionRecordingPlaylist" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/survey.py: Warning [SurveyViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.feedback.survey.Survey" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".', '/home/runner/work/posthog/posthog/posthog/api/survey.py: Warning [SurveyViewSet > SurveySerializer]: unable to resolve type hint for function "get_conditions". Consider using a type hint or @extend_schema_field. Defaulting to string.', 'Warning: encountered multiple names for the same choice set (HrefMatchingEnum). This may be unwanted even though the generated schema is technically correct. Add an entry to ENUM_NAME_OVERRIDES to fix the naming.', 'Warning: encountered multiple names for the same choice set (EffectivePrivilegeLevelEnum). This may be unwanted even though the generated schema is technically correct. Add an entry to ENUM_NAME_OVERRIDES to fix the naming.', 'Warning: encountered multiple names for the same choice set (MembershipLevelEnum). This may be unwanted even though the generated schema is technically correct. Add an entry to ENUM_NAME_OVERRIDES to fix the naming.', + 'Warning: operationId "environments_app_metrics_historical_exports_retrieve" has collisions [(\'/api/environments/{project_id}/app_metrics/{plugin_config_id}/historical_exports/\', \'get\'), (\'/api/environments/{project_id}/app_metrics/{plugin_config_id}/historical_exports/{id}/\', \'get\')]. resolving with numeral suffixes.', + 'Warning: operationId "environments_persons_activity_retrieve" has collisions [(\'/api/environments/{project_id}/persons/{id}/activity/\', \'get\'), (\'/api/environments/{project_id}/persons/activity/\', \'get\')]. resolving with numeral suffixes.', 'Warning: operationId "list" has collisions [(\'/api/organizations/\', \'get\'), (\'/api/organizations/{organization_id}/projects/\', \'get\')]. resolving with numeral suffixes.', 'Warning: operationId "create" has collisions [(\'/api/organizations/\', \'post\'), (\'/api/organizations/{organization_id}/projects/\', \'post\')]. resolving with numeral suffixes.', 'Warning: operationId "retrieve" has collisions [(\'/api/organizations/{id}/\', \'get\'), (\'/api/organizations/{organization_id}/projects/{id}/\', \'get\')]. resolving with numeral suffixes.', diff --git a/posthog/api/test/__snapshots__/test_decide.ambr b/posthog/api/test/__snapshots__/test_decide.ambr index 1b4461960e2d4..8eabbacfd181d 100644 --- a/posthog/api/test/__snapshots__/test_decide.ambr +++ b/posthog/api/test/__snapshots__/test_decide.ambr @@ -64,6 +64,241 @@ ''' # --- # name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.10 + ''' + SELECT "posthog_hogfunction"."id", + "posthog_hogfunction"."team_id", + "posthog_hogfunction"."name", + "posthog_hogfunction"."description", + "posthog_hogfunction"."created_at", + "posthog_hogfunction"."created_by_id", + "posthog_hogfunction"."deleted", + "posthog_hogfunction"."updated_at", + "posthog_hogfunction"."enabled", + "posthog_hogfunction"."icon_url", + "posthog_hogfunction"."hog", + "posthog_hogfunction"."bytecode", + "posthog_hogfunction"."inputs_schema", + "posthog_hogfunction"."inputs", + "posthog_hogfunction"."filters", + "posthog_hogfunction"."masking", + "posthog_hogfunction"."template_id", + "posthog_team"."id", + "posthog_team"."uuid", + "posthog_team"."organization_id", + "posthog_team"."project_id", + "posthog_team"."api_token", + "posthog_team"."app_urls", + "posthog_team"."name", + "posthog_team"."slack_incoming_webhook", + "posthog_team"."created_at", + "posthog_team"."updated_at", + "posthog_team"."anonymize_ips", + "posthog_team"."completed_snippet_onboarding", + "posthog_team"."has_completed_onboarding_for", + "posthog_team"."ingested_event", + "posthog_team"."autocapture_opt_out", + "posthog_team"."autocapture_web_vitals_opt_in", + "posthog_team"."autocapture_exceptions_opt_in", + "posthog_team"."autocapture_exceptions_errors_to_ignore", + "posthog_team"."session_recording_opt_in", + "posthog_team"."session_recording_sample_rate", + "posthog_team"."session_recording_minimum_duration_milliseconds", + "posthog_team"."session_recording_linked_flag", + "posthog_team"."session_recording_network_payload_capture_config", + "posthog_team"."session_replay_config", + "posthog_team"."capture_console_log_opt_in", + "posthog_team"."capture_performance_opt_in", + "posthog_team"."surveys_opt_in", + "posthog_team"."heatmaps_opt_in", + "posthog_team"."session_recording_version", + "posthog_team"."signup_token", + "posthog_team"."is_demo", + "posthog_team"."access_control", + "posthog_team"."week_start_day", + "posthog_team"."inject_web_apps", + "posthog_team"."test_account_filters", + "posthog_team"."test_account_filters_default_checked", + "posthog_team"."path_cleaning_filters", + "posthog_team"."timezone", + "posthog_team"."data_attributes", + "posthog_team"."person_display_name_properties", + "posthog_team"."live_events_columns", + "posthog_team"."recording_domains", + "posthog_team"."primary_dashboard_id", + "posthog_team"."extra_settings", + "posthog_team"."modifiers", + "posthog_team"."correlation_config", + "posthog_team"."session_recording_retention_period_days", + "posthog_team"."plugins_opt_in", + "posthog_team"."opt_out_capture", + "posthog_team"."event_names", + "posthog_team"."event_names_with_usage", + "posthog_team"."event_properties", + "posthog_team"."event_properties_with_usage", + "posthog_team"."event_properties_numerical", + "posthog_team"."external_data_workspace_id", + "posthog_team"."external_data_workspace_last_synced_at" + FROM "posthog_hogfunction" + INNER JOIN "posthog_team" ON ("posthog_hogfunction"."team_id" = "posthog_team"."id") + WHERE ("posthog_hogfunction"."team_id" = 2 + AND "posthog_hogfunction"."filters" @> '{"filter_test_accounts": true}'::jsonb) + ''' +# --- +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.11 + ''' + SELECT "posthog_team"."id", + "posthog_team"."uuid", + "posthog_team"."organization_id", + "posthog_team"."project_id", + "posthog_team"."api_token", + "posthog_team"."app_urls", + "posthog_team"."name", + "posthog_team"."slack_incoming_webhook", + "posthog_team"."created_at", + "posthog_team"."updated_at", + "posthog_team"."anonymize_ips", + "posthog_team"."completed_snippet_onboarding", + "posthog_team"."has_completed_onboarding_for", + "posthog_team"."ingested_event", + "posthog_team"."autocapture_opt_out", + "posthog_team"."autocapture_web_vitals_opt_in", + "posthog_team"."autocapture_exceptions_opt_in", + "posthog_team"."autocapture_exceptions_errors_to_ignore", + "posthog_team"."session_recording_opt_in", + "posthog_team"."session_recording_sample_rate", + "posthog_team"."session_recording_minimum_duration_milliseconds", + "posthog_team"."session_recording_linked_flag", + "posthog_team"."session_recording_network_payload_capture_config", + "posthog_team"."session_replay_config", + "posthog_team"."capture_console_log_opt_in", + "posthog_team"."capture_performance_opt_in", + "posthog_team"."surveys_opt_in", + "posthog_team"."heatmaps_opt_in", + "posthog_team"."session_recording_version", + "posthog_team"."signup_token", + "posthog_team"."is_demo", + "posthog_team"."access_control", + "posthog_team"."week_start_day", + "posthog_team"."inject_web_apps", + "posthog_team"."test_account_filters", + "posthog_team"."test_account_filters_default_checked", + "posthog_team"."path_cleaning_filters", + "posthog_team"."timezone", + "posthog_team"."data_attributes", + "posthog_team"."person_display_name_properties", + "posthog_team"."live_events_columns", + "posthog_team"."recording_domains", + "posthog_team"."primary_dashboard_id", + "posthog_team"."extra_settings", + "posthog_team"."modifiers", + "posthog_team"."correlation_config", + "posthog_team"."session_recording_retention_period_days", + "posthog_team"."external_data_workspace_id", + "posthog_team"."external_data_workspace_last_synced_at" + FROM "posthog_team" + WHERE ("posthog_team"."project_id" = 2 + AND "posthog_team"."id" = 2) + LIMIT 21 + ''' +# --- +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.12 + ''' + SELECT 1 AS "a" + FROM "posthog_grouptypemapping" + WHERE "posthog_grouptypemapping"."team_id" = 2 + LIMIT 1 + ''' +# --- +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.13 + ''' + SELECT "posthog_team"."id", + "posthog_team"."uuid", + "posthog_team"."organization_id", + "posthog_team"."project_id", + "posthog_team"."api_token", + "posthog_team"."app_urls", + "posthog_team"."name", + "posthog_team"."slack_incoming_webhook", + "posthog_team"."created_at", + "posthog_team"."updated_at", + "posthog_team"."anonymize_ips", + "posthog_team"."completed_snippet_onboarding", + "posthog_team"."has_completed_onboarding_for", + "posthog_team"."ingested_event", + "posthog_team"."autocapture_opt_out", + "posthog_team"."autocapture_web_vitals_opt_in", + "posthog_team"."autocapture_exceptions_opt_in", + "posthog_team"."autocapture_exceptions_errors_to_ignore", + "posthog_team"."session_recording_opt_in", + "posthog_team"."session_recording_sample_rate", + "posthog_team"."session_recording_minimum_duration_milliseconds", + "posthog_team"."session_recording_linked_flag", + "posthog_team"."session_recording_network_payload_capture_config", + "posthog_team"."session_replay_config", + "posthog_team"."capture_console_log_opt_in", + "posthog_team"."capture_performance_opt_in", + "posthog_team"."surveys_opt_in", + "posthog_team"."heatmaps_opt_in", + "posthog_team"."session_recording_version", + "posthog_team"."signup_token", + "posthog_team"."is_demo", + "posthog_team"."access_control", + "posthog_team"."week_start_day", + "posthog_team"."inject_web_apps", + "posthog_team"."test_account_filters", + "posthog_team"."test_account_filters_default_checked", + "posthog_team"."path_cleaning_filters", + "posthog_team"."timezone", + "posthog_team"."data_attributes", + "posthog_team"."person_display_name_properties", + "posthog_team"."live_events_columns", + "posthog_team"."recording_domains", + "posthog_team"."primary_dashboard_id", + "posthog_team"."extra_settings", + "posthog_team"."modifiers", + "posthog_team"."correlation_config", + "posthog_team"."session_recording_retention_period_days", + "posthog_team"."external_data_workspace_id", + "posthog_team"."external_data_workspace_last_synced_at" + FROM "posthog_team" + WHERE ("posthog_team"."project_id" = 2 + AND "posthog_team"."id" = 2) + LIMIT 21 + ''' +# --- +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.14 + ''' + SELECT "posthog_user"."id", + "posthog_user"."password", + "posthog_user"."last_login", + "posthog_user"."first_name", + "posthog_user"."last_name", + "posthog_user"."is_staff", + "posthog_user"."is_active", + "posthog_user"."date_joined", + "posthog_user"."uuid", + "posthog_user"."current_organization_id", + "posthog_user"."current_team_id", + "posthog_user"."email", + "posthog_user"."pending_email", + "posthog_user"."temporary_token", + "posthog_user"."distinct_id", + "posthog_user"."is_email_verified", + "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", + "posthog_user"."theme_mode", + "posthog_user"."partial_notification_settings", + "posthog_user"."anonymize_data", + "posthog_user"."toolbar_mode", + "posthog_user"."hedgehog_config", + "posthog_user"."events_column_config", + "posthog_user"."email_opt_in" + FROM "posthog_user" + WHERE "posthog_user"."id" = 2 + LIMIT 21 + ''' +# --- +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.15 ''' SELECT "posthog_featureflag"."id", "posthog_featureflag"."key", @@ -86,7 +321,7 @@ AND "posthog_featureflag"."team_id" = 2) ''' # --- -# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.11 +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.16 ''' SELECT "posthog_pluginconfig"."id", "posthog_pluginconfig"."web_token", @@ -175,6 +410,74 @@ ''' # --- # name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.4 + ''' + SELECT "posthog_project"."id", + "posthog_project"."organization_id", + "posthog_project"."name", + "posthog_project"."created_at" + FROM "posthog_project" + WHERE "posthog_project"."id" = 2 + LIMIT 21 + ''' +# --- +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.5 + ''' + SELECT "posthog_team"."id", + "posthog_team"."uuid", + "posthog_team"."organization_id", + "posthog_team"."project_id", + "posthog_team"."api_token", + "posthog_team"."app_urls", + "posthog_team"."name", + "posthog_team"."slack_incoming_webhook", + "posthog_team"."created_at", + "posthog_team"."updated_at", + "posthog_team"."anonymize_ips", + "posthog_team"."completed_snippet_onboarding", + "posthog_team"."has_completed_onboarding_for", + "posthog_team"."ingested_event", + "posthog_team"."autocapture_opt_out", + "posthog_team"."autocapture_web_vitals_opt_in", + "posthog_team"."autocapture_exceptions_opt_in", + "posthog_team"."autocapture_exceptions_errors_to_ignore", + "posthog_team"."session_recording_opt_in", + "posthog_team"."session_recording_sample_rate", + "posthog_team"."session_recording_minimum_duration_milliseconds", + "posthog_team"."session_recording_linked_flag", + "posthog_team"."session_recording_network_payload_capture_config", + "posthog_team"."session_replay_config", + "posthog_team"."capture_console_log_opt_in", + "posthog_team"."capture_performance_opt_in", + "posthog_team"."surveys_opt_in", + "posthog_team"."heatmaps_opt_in", + "posthog_team"."session_recording_version", + "posthog_team"."signup_token", + "posthog_team"."is_demo", + "posthog_team"."access_control", + "posthog_team"."week_start_day", + "posthog_team"."inject_web_apps", + "posthog_team"."test_account_filters", + "posthog_team"."test_account_filters_default_checked", + "posthog_team"."path_cleaning_filters", + "posthog_team"."timezone", + "posthog_team"."data_attributes", + "posthog_team"."person_display_name_properties", + "posthog_team"."live_events_columns", + "posthog_team"."recording_domains", + "posthog_team"."primary_dashboard_id", + "posthog_team"."extra_settings", + "posthog_team"."modifiers", + "posthog_team"."correlation_config", + "posthog_team"."session_recording_retention_period_days", + "posthog_team"."external_data_workspace_id", + "posthog_team"."external_data_workspace_last_synced_at" + FROM "posthog_team" + WHERE ("posthog_team"."project_id" = 2 + AND "posthog_team"."id" = 2) + LIMIT 21 + ''' +# --- +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.6 ''' SELECT "posthog_organizationmembership"."id", "posthog_organizationmembership"."organization_id", @@ -206,7 +509,7 @@ WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- -# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.5 +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.7 ''' SELECT "posthog_organizationmembership"."id", "posthog_organizationmembership"."organization_id", @@ -238,7 +541,7 @@ WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- -# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.6 +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.8 ''' SELECT "posthog_team"."id", "posthog_team"."organization_id", @@ -247,26 +550,9 @@ WHERE "posthog_team"."organization_id" IN ('00000000-0000-0000-0000-000000000000'::uuid) ''' # --- -# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.7 +# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.9 ''' - SELECT "posthog_hogfunction"."id", - "posthog_hogfunction"."team_id", - "posthog_hogfunction"."name", - "posthog_hogfunction"."description", - "posthog_hogfunction"."created_at", - "posthog_hogfunction"."created_by_id", - "posthog_hogfunction"."deleted", - "posthog_hogfunction"."updated_at", - "posthog_hogfunction"."enabled", - "posthog_hogfunction"."icon_url", - "posthog_hogfunction"."hog", - "posthog_hogfunction"."bytecode", - "posthog_hogfunction"."inputs_schema", - "posthog_hogfunction"."inputs", - "posthog_hogfunction"."filters", - "posthog_hogfunction"."masking", - "posthog_hogfunction"."template_id", - "posthog_team"."id", + SELECT "posthog_team"."id", "posthog_team"."uuid", "posthog_team"."organization_id", "posthog_team"."project_id", @@ -313,58 +599,11 @@ "posthog_team"."modifiers", "posthog_team"."correlation_config", "posthog_team"."session_recording_retention_period_days", - "posthog_team"."plugins_opt_in", - "posthog_team"."opt_out_capture", - "posthog_team"."event_names", - "posthog_team"."event_names_with_usage", - "posthog_team"."event_properties", - "posthog_team"."event_properties_with_usage", - "posthog_team"."event_properties_numerical", "posthog_team"."external_data_workspace_id", "posthog_team"."external_data_workspace_last_synced_at" - FROM "posthog_hogfunction" - INNER JOIN "posthog_team" ON ("posthog_hogfunction"."team_id" = "posthog_team"."id") - WHERE ("posthog_hogfunction"."team_id" = 2 - AND "posthog_hogfunction"."filters" @> '{"filter_test_accounts": true}'::jsonb) - ''' -# --- -# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.8 - ''' - SELECT 1 AS "a" - FROM "posthog_grouptypemapping" - WHERE "posthog_grouptypemapping"."team_id" = 2 - LIMIT 1 - ''' -# --- -# name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.9 - ''' - SELECT "posthog_user"."id", - "posthog_user"."password", - "posthog_user"."last_login", - "posthog_user"."first_name", - "posthog_user"."last_name", - "posthog_user"."is_staff", - "posthog_user"."is_active", - "posthog_user"."date_joined", - "posthog_user"."uuid", - "posthog_user"."current_organization_id", - "posthog_user"."current_team_id", - "posthog_user"."email", - "posthog_user"."pending_email", - "posthog_user"."temporary_token", - "posthog_user"."distinct_id", - "posthog_user"."is_email_verified", - "posthog_user"."has_seen_product_intro_for", - "posthog_user"."strapi_id", - "posthog_user"."theme_mode", - "posthog_user"."partial_notification_settings", - "posthog_user"."anonymize_data", - "posthog_user"."toolbar_mode", - "posthog_user"."hedgehog_config", - "posthog_user"."events_column_config", - "posthog_user"."email_opt_in" - FROM "posthog_user" - WHERE "posthog_user"."id" = 2 + FROM "posthog_team" + WHERE ("posthog_team"."project_id" = 2 + AND "posthog_team"."id" = 2) LIMIT 21 ''' # --- From 53848e7e73c2dc893d58440ef63c4232a1431cdd Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 19:36:42 +0000 Subject: [PATCH 22/32] Update UI snapshots for `chromium` (1) --- ...es-other-settings--settings-user--dark.png | Bin 234745 -> 172743 bytes ...s-other-settings--settings-user--light.png | Bin 235142 -> 173310 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/scenes-other-settings--settings-user--dark.png b/frontend/__snapshots__/scenes-other-settings--settings-user--dark.png index 95204eb281d628831d268adb2074785aa9e15c88..bce2f8db1cab9c6d25ed46af1c109664c5ce0ed3 100644 GIT binary patch delta 41924 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 delta 104414 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 zï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�ZPg~fNZd@P(g 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

1C!A8@IBNJcqgM<>^pxog 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 BlJEck diff --git a/frontend/__snapshots__/scenes-other-settings--settings-user--light.png b/frontend/__snapshots__/scenes-other-settings--settings-user--light.png index 3c87296382dea658f467cb3e98cdd58eac64e20b..b9bbe05d37ef76271fa7fddef8678ed86b1c4188 100644 GIT binary patch delta 41854 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 delta 104173 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 EUmsJVq5uE@ From 2cdf008c9c9319385c8fa109aa1e79e3aaf3eab8 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Tue, 10 Sep 2024 16:16:59 +0200 Subject: [PATCH 23/32] Update test_external_data_source.py --- posthog/warehouse/api/test/test_external_data_source.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/posthog/warehouse/api/test/test_external_data_source.py b/posthog/warehouse/api/test/test_external_data_source.py index 8e295ac2e925c..8a455a7b89883 100644 --- a/posthog/warehouse/api/test/test_external_data_source.py +++ b/posthog/warehouse/api/test/test_external_data_source.py @@ -621,7 +621,7 @@ def test_internal_postgres(self, patch_get_sql_schemas_for_source_type): } ] - new_team = Team.objects.create(name="new_team", organization=self.team.organization) + new_team = Team.objects.create(id=984961485, name="new_team", organization=self.team.organization) response = self.client.post( f"/api/projects/{new_team.pk}/external_data_sources/database_schema/", @@ -665,7 +665,7 @@ def test_internal_postgres(self, patch_get_sql_schemas_for_source_type): } ] - new_team = Team.objects.create(name="new_team", organization=self.team.organization) + new_team = Team.objects.create(id=984961486, name="new_team", organization=self.team.organization) response = self.client.post( f"/api/projects/{new_team.pk}/external_data_sources/database_schema/", From cf886a6849f5d0eeb4a104e54ae99af1a2aa7ba1 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Tue, 10 Sep 2024 17:32:16 +0200 Subject: [PATCH 24/32] Restore `is_demo` support and test --- ee/api/test/test_team.py | 6 ++-- posthog/api/project.py | 5 ++- posthog/api/signup.py | 2 +- posthog/api/team.py | 6 +++- posthog/api/test/test_routing.py | 4 ++- posthog/api/test/test_team.py | 19 +++++++--- posthog/demo/legacy/__init__.py | 15 -------- posthog/models/organization.py | 4 ++- posthog/models/project.py | 14 +++++--- posthog/models/team/team.py | 56 +++++++++++++++++++---------- posthog/models/test/test_project.py | 4 +++ posthog/models/user.py | 4 ++- posthog/test/base.py | 27 +++++++------- posthog/test/test_team.py | 18 +++++----- 14 files changed, 111 insertions(+), 73 deletions(-) diff --git a/ee/api/test/test_team.py b/ee/api/test/test_team.py index 254b6aa337382..d90f699fcd5c6 100644 --- a/ee/api/test/test_team.py +++ b/ee/api/test/test_team.py @@ -56,7 +56,7 @@ def test_create_demo_team(self, *args): self.organization_membership.level = OrganizationMembership.Level.ADMIN self.organization_membership.save() response = self.client.post("/api/environments/", {"name": "Hedgebox", "is_demo": True}) - self.assertEqual(Team.objects.count(), 2) + self.assertEqual(Team.objects.count(), 3) self.assertEqual(response.status_code, 201) response_data = response.json() self.assertDictContainsSubset( @@ -73,7 +73,7 @@ def test_create_two_demo_teams(self, *args): self.organization_membership.level = OrganizationMembership.Level.ADMIN self.organization_membership.save() response = self.client.post("/api/environments/", {"name": "Hedgebox", "is_demo": True}) - self.assertEqual(Team.objects.count(), 2) + self.assertEqual(Team.objects.count(), 3) self.assertEqual(response.status_code, 201) response_data = response.json() self.assertDictContainsSubset( @@ -85,7 +85,7 @@ def test_create_two_demo_teams(self, *args): response_data, ) response_2 = self.client.post("/api/environments/", {"name": "Hedgebox", "is_demo": True}) - self.assertEqual(Team.objects.count(), 2) + self.assertEqual(Team.objects.count(), 3) response_2_data = response_2.json() self.assertDictContainsSubset( { diff --git a/posthog/api/project.py b/posthog/api/project.py index ca61df684f801..ef1c54faae677 100644 --- a/posthog/api/project.py +++ b/posthog/api/project.py @@ -210,7 +210,10 @@ def create(self, validated_data: dict[str, Any], **kwargs) -> Project: if field_name in self.Meta.team_passthrough_fields: team_fields[field_name] = validated_data.pop(field_name) project, team = Project.objects.create_with_team( - organization_id=self.context["view"].organization_id, **validated_data, team_fields=team_fields + organization_id=self.context["view"].organization_id, + initiating_user=self.context["request"].user, + **validated_data, + team_fields=team_fields, ) request.user.current_team = team diff --git a/posthog/api/signup.py b/posthog/api/signup.py index 7cda79d66195d..3847999ec551d 100644 --- a/posthog/api/signup.py +++ b/posthog/api/signup.py @@ -161,7 +161,7 @@ def enter_demo(self, validated_data) -> User: return self._user def create_team(self, organization: Organization, user: User) -> Team: - return Team.objects.create_with_data(user=user, organization=organization) + return Team.objects.create_with_data(initiating_user=user, organization=organization) def to_representation(self, instance) -> dict: data = UserBasicSerializer(instance=instance).data diff --git a/posthog/api/team.py b/posthog/api/team.py index 4711ef6addb4d..34349958a6e88 100644 --- a/posthog/api/team.py +++ b/posthog/api/team.py @@ -284,7 +284,11 @@ def create(self, validated_data: dict[str, Any], **kwargs) -> Team: # but ClickHouse doesn't support Saturday as the first day of the week, so we fall back to Sunday validated_data["week_start_day"] = 1 if week_start_day_for_user_ip_location == 1 else 0 - team = Team.objects.create_with_data(organization=self.context["view"].organization, **validated_data) + team = Team.objects.create_with_data( + initiating_user=self.context["request"].user, + organization=self.context["view"].organization, + **validated_data, + ) request.user.current_team = team request.user.team = request.user.current_team # Update cached property diff --git a/posthog/api/test/test_routing.py b/posthog/api/test/test_routing.py index 52712ae0500de..24063d1a655e5 100644 --- a/posthog/api/test/test_routing.py +++ b/posthog/api/test/test_routing.py @@ -45,7 +45,9 @@ def setUp(self): super().setUp() other_org, _, other_org_team = Organization.objects.bootstrap(user=self.user) self.other_org_annotation = Annotation.objects.create(team=other_org_team, organization=other_org) - _, other_project_team = Project.objects.create_with_team(organization=self.organization) + _, other_project_team = Project.objects.create_with_team( + initiating_user=self.user, organization=self.organization + ) self.other_project_annotation = Annotation.objects.create( team=other_project_team, organization=self.organization ) diff --git a/posthog/api/test/test_team.py b/posthog/api/test/test_team.py index 0c69c2b6620d0..3e4c3e48d2dad 100644 --- a/posthog/api/test/test_team.py +++ b/posthog/api/test/test_team.py @@ -268,7 +268,7 @@ def test_delete_team_activity_log(self): self.organization_membership.level = OrganizationMembership.Level.ADMIN self.organization_membership.save() - team: Team = Team.objects.create_with_data(organization=self.organization) + team: Team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) response = self.client.delete(f"/api/environments/{team.id}") assert response.status_code == 204 @@ -345,7 +345,7 @@ def test_delete_team_own_second( self.organization_membership.level = OrganizationMembership.Level.ADMIN self.organization_membership.save() - team: Team = Team.objects.create_with_data(organization=self.organization) + team: Team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) self.assertEqual(Team.objects.filter(organization=self.organization).count(), 2) @@ -384,7 +384,7 @@ def test_delete_bulky_postgres_data(self): self.organization_membership.level = OrganizationMembership.Level.ADMIN self.organization_membership.save() - team: Team = Team.objects.create_with_data(organization=self.organization) + team: Team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) self.assertEqual(Team.objects.filter(organization=self.organization).count(), 2) @@ -434,7 +434,7 @@ def test_delete_batch_exports(self): self.organization_membership.level = OrganizationMembership.Level.ADMIN self.organization_membership.save() - team: Team = Team.objects.create_with_data(organization=self.organization) + team: Team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) destination_data = { "type": "S3", @@ -543,6 +543,9 @@ def test_update_primary_dashboard(self): self.assertEqual(response_data["primary_dashboard"], d.id) def test_cant_set_primary_dashboard_to_another_teams_dashboard(self): + self.team.primary_dashboard_id = None # Remove the default primary dashboard from the picture + self.team.save() + team_2 = Team.objects.create(organization=self.organization, name="Default project") d = Dashboard.objects.create(name="Test", team=team_2) @@ -564,6 +567,14 @@ def test_is_generating_demo_data(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.json(), {"is_generating_demo_data": False}) + @patch("posthog.tasks.demo_create_data.create_data_for_demo_team.delay") + def test_org_member_can_create_demo_project(self, mock_create_data_for_demo_team: MagicMock): + self.organization_membership.level = OrganizationMembership.Level.MEMBER + self.organization_membership.save() + response = self.client.post("/api/environments/", {"name": "Hedgebox", "is_demo": True}) + mock_create_data_for_demo_team.assert_called_once() + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + @freeze_time("2022-02-08") def test_team_float_config_can_be_serialized_to_activity_log(self): # regression test since this isn't true by default diff --git a/posthog/demo/legacy/__init__.py b/posthog/demo/legacy/__init__.py index a62ca3f350e23..194eb3fcc0542 100644 --- a/posthog/demo/legacy/__init__.py +++ b/posthog/demo/legacy/__init__.py @@ -19,21 +19,6 @@ def demo_route(request: HttpRequest): return render_template("demo.html", request=request, context={"api_token": project_api_token}) -def create_demo_team(organization: Organization, *args) -> Team: - team = Team.objects.create_with_data( - default_dashboards=False, - organization=organization, - name=TEAM_NAME, - ingested_event=True, - completed_snippet_onboarding=True, - session_recording_opt_in=True, - is_demo=True, - ) - create_demo_data(team) - EventDefinition.objects.get_or_create(team=team, name="$pageview") - return team - - def create_demo_data(team: Team, dashboards=True): WebDataGenerator(team, n_people=40).create(dashboards=dashboards) AppDataGenerator(team, n_people=100).create(dashboards=dashboards) diff --git a/posthog/models/organization.py b/posthog/models/organization.py index e64f45ff8abc4..cf1cd5c26986a 100644 --- a/posthog/models/organization.py +++ b/posthog/models/organization.py @@ -72,7 +72,9 @@ def bootstrap( with transaction.atomic(using=self.db): organization = Organization.objects.create(**kwargs) - _, team = Project.objects.create_with_team(organization=organization, team_fields=team_fields) + _, team = Project.objects.create_with_team( + initiating_user=user, organization=organization, team_fields=team_fields + ) organization_membership: Optional[OrganizationMembership] = None if user is not None: organization_membership = OrganizationMembership.objects.create( diff --git a/posthog/models/project.py b/posthog/models/project.py index bc006bf6546c3..edd1fdff4edcc 100644 --- a/posthog/models/project.py +++ b/posthog/models/project.py @@ -7,11 +7,13 @@ from posthog.models.utils import sane_repr if TYPE_CHECKING: - from .team import Team + from posthog.models import Team, User class ProjectManager(models.Manager): - def create_with_team(self, *, team_fields: Optional[dict] = None, **kwargs) -> tuple["Project", "Team"]: + def create_with_team( + self, *, team_fields: Optional[dict] = None, initiating_user: Optional["User"], **kwargs + ) -> tuple["Project", "Team"]: from .team import Team if team_fields is None: @@ -22,8 +24,12 @@ def create_with_team(self, *, team_fields: Optional[dict] = None, **kwargs) -> t with transaction.atomic(using=self.db): common_id = Team.objects.increment_id_sequence() project = cast("Project", self.create(id=common_id, **kwargs)) - team = Team.objects.create( - id=common_id, organization_id=project.organization_id, project=project, **team_fields + team = Team.objects.create_with_data( + id=common_id, + organization_id=project.organization_id, + project=project, + initiating_user=initiating_user, + **team_fields, ) return project, team diff --git a/posthog/models/team/team.py b/posthog/models/team/team.py index 016d08e64830a..3bce7301ea23d 100644 --- a/posthog/models/team/team.py +++ b/posthog/models/team/team.py @@ -1,7 +1,8 @@ import re from decimal import Decimal from functools import lru_cache -from typing import TYPE_CHECKING, Any, Optional, cast +from typing import TYPE_CHECKING, Optional, cast +from uuid import UUID from zoneinfo import ZoneInfo from django.core.cache import cache import posthoganalytics @@ -26,7 +27,7 @@ from posthog.models.filters.mixins.utils import cached_property from posthog.models.filters.utils import GroupTypeIndex from posthog.models.instance_setting import get_instance_setting -from posthog.models.organization import Organization +from posthog.models.organization import OrganizationMembership from posthog.models.signals import mutable_receiver from posthog.models.utils import ( UUIDClassicModel, @@ -66,7 +67,7 @@ class TeamManager(models.Manager): def get_queryset(self): return super().get_queryset().defer(*DEPRECATED_ATTRS) - def set_test_account_filters(self, organization: Optional[Any]) -> list: + def set_test_account_filters(self, organization_id: Optional[UUID]) -> list: filters = [ { "key": "$host", @@ -75,10 +76,12 @@ def set_test_account_filters(self, organization: Optional[Any]) -> list: "type": "event", } ] - if organization: - example_emails = organization.members.only("email") + if organization_id: + example_emails_raw = OrganizationMembership.objects.filter(organization_id=organization_id).values_list( + "user__email", flat=True + ) generic_emails = GenericEmails() - example_emails = [email.email for email in example_emails if not generic_emails.is_generic(email.email)] + example_emails = [email for email in example_emails_raw if not generic_emails.is_generic(email)] if len(example_emails) > 0: example_email = re.search(r"@[\w.]+", example_emails[0]) if example_email: @@ -88,18 +91,25 @@ def set_test_account_filters(self, organization: Optional[Any]) -> list: ] return filters - def create_with_data( - self, user: Any = None, default_dashboards: bool = True, *, organization: Organization, **kwargs - ) -> "Team": - kwargs["test_account_filters"] = self.set_test_account_filters(organization) - team = cast("Team", self.create(organization=organization, **kwargs)) - - # Create default dashboards (skipped for demo projects) - if default_dashboards: - dashboard = Dashboard.objects.db_manager(self.db).create(name="My App Dashboard", pinned=True, team=team) - create_dashboard_from_template("DEFAULT_APP", dashboard) - team.primary_dashboard = dashboard - team.save() + def create_with_data(self, *, initiating_user: Optional["User"], **kwargs) -> "Team": + team = cast("Team", self.create(**kwargs)) + + if kwargs.get("is_demo"): + if initiating_user is None: + raise ValueError("initiating_user must be provided when creating a demo team") + team.kick_off_demo_data_generation(initiating_user) + return team # Return quickly, as the demo data and setup will be created asynchronously + + team.test_account_filters = self.set_test_account_filters( + kwargs.get("organization_id") or kwargs["organization"].id + ) + + # Create default dashboards + dashboard = Dashboard.objects.db_manager(self.db).create(name="My App Dashboard", pinned=True, team=team) + create_dashboard_from_template("DEFAULT_APP", dashboard) + team.primary_dashboard = dashboard + + team.save() return team def create(self, **kwargs): @@ -478,7 +488,15 @@ def reset_token_and_save(self, *, user: "User", is_impersonated_session: bool): ) def get_is_generating_demo_data(self) -> bool: - return cache.get(f"is_generating_demo_data_{self.pk}") == "True" + cache_key = f"is_generating_demo_data_{self.id}" + return cache.get(cache_key) == "True" + + def kick_off_demo_data_generation(self, initiating_user: "User") -> None: + from posthog.tasks.demo_create_data import create_data_for_demo_team + + cache_key = f"is_generating_demo_data_{self.id}" + cache.set(cache_key, "True") # Create an item in the cache that we can use to see if the demo data is ready + create_data_for_demo_team.delay(self.id, initiating_user.id, cache_key) def all_users_with_access(self) -> QuerySet["User"]: from ee.models.explicit_team_membership import ExplicitTeamMembership diff --git a/posthog/models/test/test_project.py b/posthog/models/test/test_project.py index 1e2e0cef2167a..1fd7434f90da3 100644 --- a/posthog/models/test/test_project.py +++ b/posthog/models/test/test_project.py @@ -7,6 +7,7 @@ class TestProject(BaseTest): def test_create_project_with_team_no_team_fields(self): project, team = Project.objects.create_with_team( + initiating_user=self.user, organization=self.organization, name="Test project", ) @@ -24,6 +25,7 @@ def test_create_project_with_team_no_team_fields(self): def test_create_project_with_team_with_team_fields(self): project, team = Project.objects.create_with_team( + initiating_user=self.user, organization=self.organization, name="Test project", team_fields={"name": "Test team", "access_control": True}, @@ -42,6 +44,7 @@ def test_create_project_with_team_uses_team_id_sequence(self): expected_common_id = Team.objects.increment_id_sequence() + 1 project, team = Project.objects.create_with_team( + initiating_user=self.user, organization=self.organization, name="Test project", team_fields={"name": "Test team", "access_control": True}, @@ -64,6 +67,7 @@ def test_create_project_with_team_does_not_create_if_team_fails(self, mock_creat with self.assertRaises(Exception): Project.objects.create_with_team( + initiating_user=self.user, organization=self.organization, name="Test project", team_fields={"name": "Test team", "access_control": True}, diff --git a/posthog/models/user.py b/posthog/models/user.py index 621c1d36429a7..748533be437cd 100644 --- a/posthog/models/user.py +++ b/posthog/models/user.py @@ -80,7 +80,9 @@ def bootstrap( if create_team: team = create_team(organization, user) else: - team = Team.objects.create_with_data(user=user, organization=organization, **(team_fields or {})) + team = Team.objects.create_with_data( + initiating_user=user, organization=organization, **(team_fields or {}) + ) user.join(organization=organization, level=OrganizationMembership.Level.OWNER) return organization, team, user diff --git a/posthog/test/base.py b/posthog/test/base.py index 451264bfc205b..0b7ccd78a85dc 100644 --- a/posthog/test/base.py +++ b/posthog/test/base.py @@ -107,20 +107,21 @@ def _setup_test_data(klass): klass.organization = Organization.objects.create(name=klass.CONFIG_ORGANIZATION_NAME) - klass.project, klass.team = Project.objects.create_with_team( + klass.project = Project.objects.create(id=Team.objects.increment_id_sequence(), organization=klass.organization) + klass.team = Team.objects.create( + id=klass.project.id, + project=klass.project, organization=klass.organization, - team_fields={ - "api_token": klass.CONFIG_API_TOKEN, - "test_account_filters": [ - { - "key": "email", - "value": "@posthog.com", - "operator": "not_icontains", - "type": "person", - } - ], - "has_completed_onboarding_for": {"product_analytics": True}, - }, + api_token=klass.CONFIG_API_TOKEN, + test_account_filters=[ + { + "key": "email", + "value": "@posthog.com", + "operator": "not_icontains", + "type": "person", + } + ], + has_completed_onboarding_for={"product_analytics": True}, ) if klass.CONFIG_EMAIL: klass.user = User.objects.create_and_join(klass.organization, klass.CONFIG_EMAIL, klass.CONFIG_PASSWORD) diff --git a/posthog/test/test_team.py b/posthog/test/test_team.py index 076fc21e5fe34..b47eb70e016e2 100644 --- a/posthog/test/test_team.py +++ b/posthog/test/test_team.py @@ -76,7 +76,7 @@ def test_team_has_expected_defaults(self): self.assertEqual(team.autocapture_exceptions_errors_to_ignore, None) def test_create_team_with_test_account_filters(self): - team = Team.objects.create_with_data(organization=self.organization) + team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) self.assertEqual( team.test_account_filters, [ @@ -99,7 +99,7 @@ def test_create_team_with_test_account_filters(self): user = User.objects.create(email="test@gmail.com") organization = Organization.objects.create() organization.members.set([user]) - team = Team.objects.create_with_data(organization=organization) + team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) self.assertEqual( team.test_account_filters, [ @@ -113,7 +113,7 @@ def test_create_team_with_test_account_filters(self): ) def test_create_team_sets_primary_dashboard(self): - team = Team.objects.create_with_data(organization=self.organization) + team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) self.assertIsInstance(team.primary_dashboard, Dashboard) # Ensure insights are created and linked @@ -139,7 +139,7 @@ def test_preinstalled_are_autoenabled(self, mock_get): def test_team_on_cloud_uses_feature_flag_to_determine_person_on_events(self, mock_feature_enabled): with self.is_cloud(True): with override_instance_config("PERSON_ON_EVENTS_ENABLED", False): - team = Team.objects.create_with_data(organization=self.organization) + team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) self.assertEqual( team.person_on_events_mode, PersonsOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS ) @@ -162,7 +162,7 @@ def test_team_on_cloud_uses_feature_flag_to_determine_person_on_events(self, moc def test_team_on_self_hosted_uses_instance_setting_to_determine_person_on_events(self, mock_feature_enabled): with self.is_cloud(False): with override_instance_config("PERSON_ON_EVENTS_V2_ENABLED", True): - team = Team.objects.create_with_data(organization=self.organization) + team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) self.assertEqual( team.person_on_events_mode, PersonsOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS ) @@ -171,7 +171,7 @@ def test_team_on_self_hosted_uses_instance_setting_to_determine_person_on_events assert args_list[0][0] != "persons-on-events-v2-reads-enabled" with override_instance_config("PERSON_ON_EVENTS_V2_ENABLED", False): - team = Team.objects.create_with_data(organization=self.organization) + team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) self.assertEqual(team.person_on_events_mode, PersonsOnEventsMode.DISABLED) for args_list in mock_feature_enabled.call_args_list: # It is ok if we check other feature flags, just not `persons-on-events-v2-reads-enabled` @@ -179,7 +179,7 @@ def test_team_on_self_hosted_uses_instance_setting_to_determine_person_on_events def test_each_team_gets_project_with_default_name_and_same_id(self): # Can be removed once environments are fully rolled out - team = Team.objects.create_with_data(organization=self.organization) + team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) project = Project.objects.filter(id=team.id).first() @@ -188,7 +188,7 @@ def test_each_team_gets_project_with_default_name_and_same_id(self): def test_each_team_gets_project_with_custom_name_and_same_id(self): # Can be removed once environments are fully rolled out - team = Team.objects.create_with_data(organization=self.organization, name="Hogflix") + team = Team.objects.create_with_data(organization=self.organization, initiating_user=self.user, name="Hogflix") project = Project.objects.filter(id=team.id).first() @@ -203,7 +203,7 @@ def test_team_not_created_if_project_creation_fails(self, mock_create): initial_project_count = Project.objects.count() with self.assertRaises(Exception): - Team.objects.create_with_data(organization=self.organization, name="Hogflix") + Team.objects.create_with_data(organization=self.organization, initiating_user=self.user, name="Hogflix") self.assertEqual(Team.objects.count(), initial_team_count) self.assertEqual(Project.objects.count(), initial_project_count) From 910e133fa62b9fc83ff9fb94adbba6d330141b80 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:05:12 +0000 Subject: [PATCH 25/32] Update query snapshots --- .../test/__snapshots__/test_trends.ambr | 260 +++++++++++++++++- 1 file changed, 250 insertions(+), 10 deletions(-) diff --git a/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr b/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr index 69d6e856f5540..0f3ec9882b914 100644 --- a/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr +++ b/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr @@ -840,6 +840,54 @@ ''' # --- # name: TestTrends.test_dau_with_breakdown_filtering_with_sampling + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.1 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.10 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.11 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.12 ''' SELECT groupArray(1)(date)[1] AS date, arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, @@ -886,7 +934,7 @@ max_bytes_before_external_group_by=0 ''' # --- -# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.1 +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.13 ''' SELECT groupArray(1)(date)[1] AS date, arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, @@ -933,7 +981,7 @@ max_bytes_before_external_group_by=0 ''' # --- -# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.2 +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.14 ''' SELECT groupArray(1)(date)[1] AS date, arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, @@ -980,7 +1028,7 @@ max_bytes_before_external_group_by=0 ''' # --- -# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.3 +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.15 ''' SELECT groupArray(1)(date)[1] AS date, arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, @@ -1027,6 +1075,102 @@ max_bytes_before_external_group_by=0 ''' # --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.2 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.3 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.4 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.5 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.6 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.7 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.8 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.9 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- # name: TestTrends.test_filter_events_by_precalculated_cohort ''' @@ -1642,6 +1786,18 @@ # --- # name: TestTrends.test_person_filtering_in_cohort_in_action ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_person_filtering_in_cohort_in_action.1 + ''' SELECT count(DISTINCT person_id) FROM cohortpeople @@ -1650,7 +1806,7 @@ AND version = NULL ''' # --- -# name: TestTrends.test_person_filtering_in_cohort_in_action.1 +# name: TestTrends.test_person_filtering_in_cohort_in_action.2 ''' /* cohort_calculation: */ SELECT count(DISTINCT person_id) @@ -1660,7 +1816,7 @@ AND version = 0 ''' # --- -# name: TestTrends.test_person_filtering_in_cohort_in_action.2 +# name: TestTrends.test_person_filtering_in_cohort_in_action.3 ''' SELECT groupArray(1)(date)[1] AS date, arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, @@ -1712,6 +1868,18 @@ # --- # name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2 ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2.1 + ''' SELECT count(DISTINCT person_id) FROM cohortpeople @@ -1720,7 +1888,7 @@ AND version = NULL ''' # --- -# name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2.1 +# name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2.2 ''' /* cohort_calculation: */ SELECT count(DISTINCT person_id) @@ -1730,7 +1898,7 @@ AND version = 0 ''' # --- -# name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2.2 +# name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2.3 ''' SELECT groupArray(1)(date)[1] AS date, arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, @@ -3494,6 +3662,18 @@ ''' # --- # name: TestTrends.test_trends_any_event_total_count + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_any_event_total_count.1 ''' SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) @@ -3519,7 +3699,7 @@ max_bytes_before_external_group_by=0 ''' # --- -# name: TestTrends.test_trends_any_event_total_count.1 +# name: TestTrends.test_trends_any_event_total_count.2 ''' SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) @@ -3546,6 +3726,18 @@ ''' # --- # name: TestTrends.test_trends_breakdown_cumulative + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_breakdown_cumulative.1 ''' SELECT groupArray(1)(date)[1] AS date, arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, @@ -3599,6 +3791,18 @@ ''' # --- # name: TestTrends.test_trends_breakdown_cumulative_poe_v2 + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_breakdown_cumulative_poe_v2.1 ''' SELECT groupArray(1)(date)[1] AS date, arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, @@ -3891,6 +4095,18 @@ ''' # --- # name: TestTrends.test_trends_compare_day_interval_relative_range + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_compare_day_interval_relative_range.1 ''' SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) @@ -3916,7 +4132,7 @@ max_bytes_before_external_group_by=0 ''' # --- -# name: TestTrends.test_trends_compare_day_interval_relative_range.1 +# name: TestTrends.test_trends_compare_day_interval_relative_range.2 ''' SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-21 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-21 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 23:59:59', 6, 'UTC'))))), 1))) AS date, arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) @@ -3942,7 +4158,7 @@ max_bytes_before_external_group_by=0 ''' # --- -# name: TestTrends.test_trends_compare_day_interval_relative_range.2 +# name: TestTrends.test_trends_compare_day_interval_relative_range.3 ''' SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) @@ -4209,6 +4425,18 @@ ''' # --- # name: TestTrends.test_trends_per_day_cumulative + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_per_day_cumulative.1 ''' SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, arrayFill(x -> ifNull(greater(x, 0), 0), arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) @@ -4240,6 +4468,18 @@ ''' # --- # name: TestTrends.test_trends_per_day_dau_cumulative + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_per_day_dau_cumulative.1 ''' SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, arrayFill(x -> ifNull(greater(x, 0), 0), arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) From f85cbbc7e2b4be5825684748e87d1342be65965e Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Tue, 10 Sep 2024 21:01:58 +0200 Subject: [PATCH 26/32] Fix a couple assertions --- ee/api/test/test_billing.py | 2 +- ee/api/test/test_organization.py | 2 +- posthog/test/test_team.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ee/api/test/test_billing.py b/ee/api/test/test_billing.py index 00beee3f0a671..a053dd1ac9c1c 100644 --- a/ee/api/test/test_billing.py +++ b/ee/api/test/test_billing.py @@ -780,7 +780,7 @@ def mock_implementation(url: str, headers: Any = None, params: Any = None) -> Ma self.assertEqual(Team.objects.count(), 1) response = self.client.post("/api/projects/", {"name": "Test", "is_demo": True}) self.assertEqual(response.status_code, 201) - self.assertEqual(Team.objects.count(), 2) + self.assertEqual(Team.objects.count(), 3) demo_team = Team.objects.filter(is_demo=True).first() diff --git a/ee/api/test/test_organization.py b/ee/api/test/test_organization.py index ca0d68413cf4c..ed47558d1efc4 100644 --- a/ee/api/test/test_organization.py +++ b/ee/api/test/test_organization.py @@ -28,7 +28,7 @@ def test_create_organization(self): OrganizationMembership.Level.OWNER, ) - @patch("secrets.choice", return_value="Y") + @patch("posthog.models.utils.generate_random_short_suffix", return_value="YYYY") def test_create_two_similarly_named_organizations(self, mock_choice): response = self.client.post( "/api/organizations/", diff --git a/posthog/test/test_team.py b/posthog/test/test_team.py index b47eb70e016e2..6894fb6134642 100644 --- a/posthog/test/test_team.py +++ b/posthog/test/test_team.py @@ -99,7 +99,7 @@ def test_create_team_with_test_account_filters(self): user = User.objects.create(email="test@gmail.com") organization = Organization.objects.create() organization.members.set([user]) - team = Team.objects.create_with_data(initiating_user=self.user, organization=self.organization) + team = Team.objects.create_with_data(initiating_user=self.user, organization=organization) self.assertEqual( team.test_account_filters, [ From 2b4a18a3cf445688a8073e221e75c70735799dcf Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Tue, 10 Sep 2024 21:04:48 +0200 Subject: [PATCH 27/32] Add `autocapture_web_vitals_allowed_metrics` --- posthog/api/project.py | 1 + 1 file changed, 1 insertion(+) diff --git a/posthog/api/project.py b/posthog/api/project.py index ef1c54faae677..0909e2103242f 100644 --- a/posthog/api/project.py +++ b/posthog/api/project.py @@ -76,6 +76,7 @@ class Meta: "autocapture_opt_out", # Compat with TeamSerializer "autocapture_exceptions_opt_in", # Compat with TeamSerializer "autocapture_web_vitals_opt_in", # Compat with TeamSerializer + "autocapture_web_vitals_allowed_metrics", # Compat with TeamSerializer "autocapture_exceptions_errors_to_ignore", # Compat with TeamSerializer "capture_console_log_opt_in", # Compat with TeamSerializer "capture_performance_opt_in", # Compat with TeamSerializer From 9b47e03b47691bff4d97f9d2c0583afea8b1d9a0 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:24:01 +0000 Subject: [PATCH 28/32] Update UI snapshots for `chromium` (2) --- ...ights--funnel-left-to-right-edit--dark.png | Bin 155281 -> 154427 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/scenes-app-insights--funnel-left-to-right-edit--dark.png b/frontend/__snapshots__/scenes-app-insights--funnel-left-to-right-edit--dark.png index 667f5c839eea3bd665c9ad98bcb1a1bdd156c0de..24cfa930cc9e105726073d25bddc5d0d6f1f6d2d 100644 GIT binary patch literal 154427 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[pJ?tAL|e~#h~L*!IvTPk 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 From 6436b9869430becb71b35b4ff2e8a0117df598bb Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:41:26 +0000 Subject: [PATCH 29/32] Update query snapshots --- .../test/__snapshots__/test_trends.ambr | 116 ++++++++++++++++-- 1 file changed, 106 insertions(+), 10 deletions(-) diff --git a/posthog/queries/test/__snapshots__/test_trends.ambr b/posthog/queries/test/__snapshots__/test_trends.ambr index 6e60ae26b943e..81808cef8269b 100644 --- a/posthog/queries/test/__snapshots__/test_trends.ambr +++ b/posthog/queries/test/__snapshots__/test_trends.ambr @@ -853,6 +853,18 @@ # --- # name: TestTrends.test_dau_with_breakdown_filtering_with_sampling ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.1 + ''' SELECT replaceRegexpAll(JSONExtractRaw(properties, '$some_property'), '^"|"$', '') AS value, count(*) as count @@ -867,7 +879,7 @@ OFFSET 0 ''' # --- -# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.1 +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.2 ''' SELECT groupArray(day_start) as date, @@ -919,7 +931,7 @@ ORDER BY breakdown_value ''' # --- -# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.2 +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.3 ''' SELECT replaceRegexpAll(JSONExtractRaw(properties, '$some_property'), '^"|"$', '') AS value, @@ -935,7 +947,7 @@ OFFSET 0 ''' # --- -# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.3 +# name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.4 ''' SELECT groupArray(day_start) as date, @@ -1480,6 +1492,18 @@ # --- # name: TestTrends.test_person_filtering_in_cohort_in_action ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_person_filtering_in_cohort_in_action.1 + ''' SELECT replaceRegexpAll(JSONExtractRaw(properties, '$some_property'), '^"|"$', '') AS value, count(*) as count @@ -1513,7 +1537,7 @@ OFFSET 0 ''' # --- -# name: TestTrends.test_person_filtering_in_cohort_in_action.1 +# name: TestTrends.test_person_filtering_in_cohort_in_action.2 ''' SELECT groupArray(day_start) as date, @@ -1579,6 +1603,18 @@ # --- # name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2 ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2.1 + ''' SELECT replaceRegexpAll(JSONExtractRaw(properties, '$some_property'), '^"|"$', '') AS value, count(*) as count @@ -1613,7 +1649,7 @@ OFFSET 0 ''' # --- -# name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2.1 +# name: TestTrends.test_person_filtering_in_cohort_in_action_poe_v2.2 ''' SELECT groupArray(day_start) as date, @@ -3970,6 +4006,18 @@ # --- # name: TestTrends.test_trends_any_event_total_count ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_any_event_total_count.1 + ''' SELECT groupArray(day_start) as date, groupArray(count) AS total @@ -3994,7 +4042,7 @@ ORDER BY day_start) ''' # --- -# name: TestTrends.test_trends_any_event_total_count.1 +# name: TestTrends.test_trends_any_event_total_count.2 ''' SELECT groupArray(day_start) as date, @@ -4022,6 +4070,18 @@ # --- # name: TestTrends.test_trends_breakdown_cumulative ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_breakdown_cumulative.1 + ''' SELECT replaceRegexpAll(JSONExtractRaw(properties, '$some_property'), '^"|"$', '') AS value, count(*) as count @@ -4036,7 +4096,7 @@ OFFSET 0 ''' # --- -# name: TestTrends.test_trends_breakdown_cumulative.1 +# name: TestTrends.test_trends_breakdown_cumulative.2 ''' SELECT groupArray(day_start) as date, @@ -4098,6 +4158,18 @@ # --- # name: TestTrends.test_trends_breakdown_cumulative_poe_v2 ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_breakdown_cumulative_poe_v2.1 + ''' SELECT replaceRegexpAll(JSONExtractRaw(properties, '$some_property'), '^"|"$', '') AS value, count(*) as count @@ -4120,7 +4192,7 @@ OFFSET 0 ''' # --- -# name: TestTrends.test_trends_breakdown_cumulative_poe_v2.1 +# name: TestTrends.test_trends_breakdown_cumulative_poe_v2.2 ''' SELECT groupArray(day_start) as date, @@ -4298,6 +4370,18 @@ # --- # name: TestTrends.test_trends_compare_day_interval_relative_range ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_compare_day_interval_relative_range.1 + ''' SELECT groupArray(day_start) as date, groupArray(count) AS total @@ -4322,7 +4406,7 @@ ORDER BY day_start) ''' # --- -# name: TestTrends.test_trends_compare_day_interval_relative_range.1 +# name: TestTrends.test_trends_compare_day_interval_relative_range.2 ''' SELECT groupArray(day_start) as date, @@ -4348,7 +4432,7 @@ ORDER BY day_start) ''' # --- -# name: TestTrends.test_trends_compare_day_interval_relative_range.2 +# name: TestTrends.test_trends_compare_day_interval_relative_range.3 ''' SELECT groupArray(day_start) as date, @@ -4657,6 +4741,18 @@ # --- # name: TestTrends.test_trends_per_day_cumulative ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestTrends.test_trends_per_day_cumulative.1 + ''' SELECT groupArray(day_start) as date, groupArray(count) AS total From 83ab9f8bb2e4206a09eaebdbe0091974158e7dd5 Mon Sep 17 00:00:00 2001 From: Michael Matloka Date: Tue, 10 Sep 2024 23:37:13 +0200 Subject: [PATCH 30/32] Add `autocapture_web_vitals_allowed_metrics` bis --- posthog/api/project.py | 1 + 1 file changed, 1 insertion(+) diff --git a/posthog/api/project.py b/posthog/api/project.py index 0909e2103242f..d2e3e341228b0 100644 --- a/posthog/api/project.py +++ b/posthog/api/project.py @@ -135,6 +135,7 @@ class Meta: "autocapture_opt_out", "autocapture_exceptions_opt_in", "autocapture_web_vitals_opt_in", + "autocapture_web_vitals_allowed_metrics", "autocapture_exceptions_errors_to_ignore", "capture_console_log_opt_in", "capture_performance_opt_in", From 4c080a0c3b79f4dffe70ef5356685ca08d9eb027 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 07:45:24 +0000 Subject: [PATCH 31/32] Update query snapshots --- .../api/test/__snapshots__/test_decide.ambr | 4 ++ .../api/test/__snapshots__/test_event.ambr | 48 ++++++++++++++----- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/posthog/api/test/__snapshots__/test_decide.ambr b/posthog/api/test/__snapshots__/test_decide.ambr index de1db73c30ae8..2d1f760a286fb 100644 --- a/posthog/api/test/__snapshots__/test_decide.ambr +++ b/posthog/api/test/__snapshots__/test_decide.ambr @@ -98,6 +98,7 @@ "posthog_team"."ingested_event", "posthog_team"."autocapture_opt_out", "posthog_team"."autocapture_web_vitals_opt_in", + "posthog_team"."autocapture_web_vitals_allowed_metrics", "posthog_team"."autocapture_exceptions_opt_in", "posthog_team"."autocapture_exceptions_errors_to_ignore", "posthog_team"."session_recording_opt_in", @@ -162,6 +163,7 @@ "posthog_team"."ingested_event", "posthog_team"."autocapture_opt_out", "posthog_team"."autocapture_web_vitals_opt_in", + "posthog_team"."autocapture_web_vitals_allowed_metrics", "posthog_team"."autocapture_exceptions_opt_in", "posthog_team"."autocapture_exceptions_errors_to_ignore", "posthog_team"."session_recording_opt_in", @@ -227,6 +229,7 @@ "posthog_team"."ingested_event", "posthog_team"."autocapture_opt_out", "posthog_team"."autocapture_web_vitals_opt_in", + "posthog_team"."autocapture_web_vitals_allowed_metrics", "posthog_team"."autocapture_exceptions_opt_in", "posthog_team"."autocapture_exceptions_errors_to_ignore", "posthog_team"."session_recording_opt_in", @@ -570,6 +573,7 @@ "posthog_team"."ingested_event", "posthog_team"."autocapture_opt_out", "posthog_team"."autocapture_web_vitals_opt_in", + "posthog_team"."autocapture_web_vitals_allowed_metrics", "posthog_team"."autocapture_exceptions_opt_in", "posthog_team"."autocapture_exceptions_errors_to_ignore", "posthog_team"."session_recording_opt_in", diff --git a/posthog/api/test/__snapshots__/test_event.ambr b/posthog/api/test/__snapshots__/test_event.ambr index a8aaa175a427e..cae4ce7b8b045 100644 --- a/posthog/api/test/__snapshots__/test_event.ambr +++ b/posthog/api/test/__snapshots__/test_event.ambr @@ -1,5 +1,17 @@ # serializer version: 1 # name: TestEvents.test_event_property_values + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestEvents.test_event_property_values.1 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT replaceRegexpAll(JSONExtractRaw(properties, 'random_prop'), '^"|"$', '') @@ -11,7 +23,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values.1 +# name: TestEvents.test_event_property_values.2 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT replaceRegexpAll(JSONExtractRaw(properties, 'random_prop'), '^"|"$', '') @@ -25,7 +37,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values.2 +# name: TestEvents.test_event_property_values.3 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT replaceRegexpAll(JSONExtractRaw(properties, 'random_prop'), '^"|"$', '') @@ -39,7 +51,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values.3 +# name: TestEvents.test_event_property_values.4 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT replaceRegexpAll(JSONExtractRaw(properties, 'random_prop'), '^"|"$', '') @@ -53,7 +65,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values.4 +# name: TestEvents.test_event_property_values.5 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT replaceRegexpAll(JSONExtractRaw(properties, 'random_prop'), '^"|"$', '') @@ -68,7 +80,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values.5 +# name: TestEvents.test_event_property_values.6 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT replaceRegexpAll(JSONExtractRaw(properties, 'random_prop'), '^"|"$', '') @@ -84,7 +96,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values.6 +# name: TestEvents.test_event_property_values.7 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT replaceRegexpAll(JSONExtractRaw(properties, 'random_prop'), '^"|"$', '') @@ -100,6 +112,18 @@ ''' # --- # name: TestEvents.test_event_property_values_materialized + ''' + /* celery:posthog.tasks.tasks.sync_insight_caching_state */ + SELECT team_id, + date_diff('second', max(timestamp), now()) AS age + FROM events + WHERE timestamp > date_sub(DAY, 3, now()) + AND timestamp < now() + GROUP BY team_id + ORDER BY age; + ''' +# --- +# name: TestEvents.test_event_property_values_materialized.1 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT "mat_random_prop" @@ -111,7 +135,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values_materialized.1 +# name: TestEvents.test_event_property_values_materialized.2 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT "mat_random_prop" @@ -125,7 +149,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values_materialized.2 +# name: TestEvents.test_event_property_values_materialized.3 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT "mat_random_prop" @@ -139,7 +163,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values_materialized.3 +# name: TestEvents.test_event_property_values_materialized.4 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT "mat_random_prop" @@ -153,7 +177,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values_materialized.4 +# name: TestEvents.test_event_property_values_materialized.5 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT "mat_random_prop" @@ -168,7 +192,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values_materialized.5 +# name: TestEvents.test_event_property_values_materialized.6 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT "mat_random_prop" @@ -184,7 +208,7 @@ LIMIT 10 ''' # --- -# name: TestEvents.test_event_property_values_materialized.6 +# name: TestEvents.test_event_property_values_materialized.7 ''' /* user_id:0 request:_snapshot_ */ SELECT DISTINCT "mat_random_prop" From 205cb6bdd8c519930cdf424fea7b30ed0654537b Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:34:50 +0000 Subject: [PATCH 32/32] Update query snapshots --- .../test/__snapshots__/test_trends.ambr | 204 +++++++++++++++--- 1 file changed, 172 insertions(+), 32 deletions(-) diff --git a/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr b/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr index 0f3ec9882b914..2fe83c79dc067 100644 --- a/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr +++ b/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr @@ -853,14 +853,49 @@ # --- # name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.1 ''' - /* celery:posthog.tasks.tasks.sync_insight_caching_state */ - SELECT team_id, - date_diff('second', max(timestamp), now()) AS age - FROM events - WHERE timestamp > date_sub(DAY, 3, now()) - AND timestamp < now() - GROUP BY team_id - ORDER BY age; + SELECT groupArray(1)(date)[1] AS date, + arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, + if(ifNull(ifNull(greaterOrEquals(row_number, 25), 0), 0), '$$_posthog_breakdown_other_$$', breakdown_value) AS breakdown_value + FROM + (SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, + arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) + and isNull(_match_date)), _days_for_count), _index), 1))), date) AS total, + breakdown_value AS breakdown_value, + rowNumberInAllBlocks() AS row_number + FROM + (SELECT sum(total) AS count, + day_start AS day_start, + breakdown_value AS breakdown_value + FROM + (SELECT count(DISTINCT e__pdi.person_id) AS total, + toStartOfDay(toTimeZone(e.timestamp, 'UTC')) AS day_start, + ifNull(nullIf(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$some_property'), ''), 'null'), '^"|"$', '')), ''), '$$_posthog_breakdown_null_$$') AS breakdown_value + FROM events AS e SAMPLE 1.0 + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))), equals(e.event, 'sign up')) + GROUP BY day_start, + breakdown_value) + GROUP BY day_start, + breakdown_value + ORDER BY day_start ASC, breakdown_value ASC) + GROUP BY breakdown_value + ORDER BY if(ifNull(equals(breakdown_value, '$$_posthog_breakdown_other_$$'), 0), 2, if(ifNull(equals(breakdown_value, '$$_posthog_breakdown_null_$$'), 0), 1, 0)) ASC, arraySum(total) DESC, breakdown_value ASC) + WHERE isNotNull(breakdown_value) + GROUP BY breakdown_value + ORDER BY if(ifNull(equals(breakdown_value, '$$_posthog_breakdown_other_$$'), 0), 2, if(ifNull(equals(breakdown_value, '$$_posthog_breakdown_null_$$'), 0), 1, 0)) ASC, arraySum(total) DESC, breakdown_value ASC + LIMIT 50000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=0 ''' # --- # name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.10 @@ -1077,38 +1112,143 @@ # --- # name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.2 ''' - /* celery:posthog.tasks.tasks.sync_insight_caching_state */ - SELECT team_id, - date_diff('second', max(timestamp), now()) AS age - FROM events - WHERE timestamp > date_sub(DAY, 3, now()) - AND timestamp < now() - GROUP BY team_id - ORDER BY age; + SELECT groupArray(1)(date)[1] AS date, + arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, + if(ifNull(ifNull(greaterOrEquals(row_number, 25), 0), 0), '$$_posthog_breakdown_other_$$', breakdown_value) AS breakdown_value + FROM + (SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, + arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) + and isNull(_match_date)), _days_for_count), _index), 1))), date) AS total, + breakdown_value AS breakdown_value, + rowNumberInAllBlocks() AS row_number + FROM + (SELECT sum(total) AS count, + day_start AS day_start, + breakdown_value AS breakdown_value + FROM + (SELECT count(DISTINCT e__pdi.person_id) AS total, + toStartOfDay(toTimeZone(e.timestamp, 'UTC')) AS day_start, + ifNull(nullIf(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$some_property'), ''), 'null'), '^"|"$', '')), ''), '$$_posthog_breakdown_null_$$') AS breakdown_value + FROM events AS e SAMPLE 1.0 + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))), equals(e.event, 'sign up')) + GROUP BY day_start, + breakdown_value) + GROUP BY day_start, + breakdown_value + ORDER BY day_start ASC, breakdown_value ASC) + GROUP BY breakdown_value + ORDER BY if(ifNull(equals(breakdown_value, '$$_posthog_breakdown_other_$$'), 0), 2, if(ifNull(equals(breakdown_value, '$$_posthog_breakdown_null_$$'), 0), 1, 0)) ASC, arraySum(total) DESC, breakdown_value ASC) + WHERE isNotNull(breakdown_value) + GROUP BY breakdown_value + ORDER BY if(ifNull(equals(breakdown_value, '$$_posthog_breakdown_other_$$'), 0), 2, if(ifNull(equals(breakdown_value, '$$_posthog_breakdown_null_$$'), 0), 1, 0)) ASC, arraySum(total) DESC, breakdown_value ASC + LIMIT 50000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=0 ''' # --- # name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.3 ''' - /* celery:posthog.tasks.tasks.sync_insight_caching_state */ - SELECT team_id, - date_diff('second', max(timestamp), now()) AS age - FROM events - WHERE timestamp > date_sub(DAY, 3, now()) - AND timestamp < now() - GROUP BY team_id - ORDER BY age; + SELECT groupArray(1)(date)[1] AS date, + arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, + arrayMap(i -> if(ifNull(ifNull(greaterOrEquals(row_number, 25), 0), 0), '$$_posthog_breakdown_other_$$', i), breakdown_value) AS breakdown_value + FROM + (SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, + arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) + and isNull(_match_date)), _days_for_count), _index), 1))), date) AS total, + breakdown_value AS breakdown_value, + rowNumberInAllBlocks() AS row_number + FROM + (SELECT sum(total) AS count, + day_start AS day_start, + [ifNull(toString(breakdown_value_1), '$$_posthog_breakdown_null_$$')] AS breakdown_value + FROM + (SELECT count(DISTINCT e__pdi.person_id) AS total, + toStartOfDay(toTimeZone(e.timestamp, 'UTC')) AS day_start, + ifNull(nullIf(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$some_property'), ''), 'null'), '^"|"$', '')), ''), '$$_posthog_breakdown_null_$$') AS breakdown_value_1 + FROM events AS e SAMPLE 1.0 + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))), equals(e.event, 'sign up')) + GROUP BY day_start, + breakdown_value_1) + GROUP BY day_start, + breakdown_value_1 + ORDER BY day_start ASC, breakdown_value ASC) + GROUP BY breakdown_value + ORDER BY if(has(breakdown_value, '$$_posthog_breakdown_other_$$'), 2, if(has(breakdown_value, '$$_posthog_breakdown_null_$$'), 1, 0)) ASC, arraySum(total) DESC, breakdown_value ASC) + WHERE arrayExists(x -> isNotNull(x), breakdown_value) + GROUP BY breakdown_value + ORDER BY if(has(breakdown_value, '$$_posthog_breakdown_other_$$'), 2, if(has(breakdown_value, '$$_posthog_breakdown_null_$$'), 1, 0)) ASC, arraySum(total) DESC, breakdown_value ASC + LIMIT 50000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=0 ''' # --- # name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.4 ''' - /* celery:posthog.tasks.tasks.sync_insight_caching_state */ - SELECT team_id, - date_diff('second', max(timestamp), now()) AS age - FROM events - WHERE timestamp > date_sub(DAY, 3, now()) - AND timestamp < now() - GROUP BY team_id - ORDER BY age; + SELECT groupArray(1)(date)[1] AS date, + arrayFold((acc, x) -> arrayMap(i -> plus(acc[i], x[i]), range(1, plus(length(date), 1))), groupArray(total), arrayWithConstant(length(date), reinterpretAsFloat64(0))) AS total, + arrayMap(i -> if(ifNull(ifNull(greaterOrEquals(row_number, 25), 0), 0), '$$_posthog_breakdown_other_$$', i), breakdown_value) AS breakdown_value + FROM + (SELECT arrayMap(number -> plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toIntervalDay(number)), range(0, plus(coalesce(dateDiff('day', toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC'))), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))))), 1))) AS date, + arrayMap(_match_date -> arraySum(arraySlice(groupArray(count), indexOf(groupArray(day_start) AS _days_for_count, _match_date) AS _index, plus(minus(arrayLastIndex(x -> ifNull(equals(x, _match_date), isNull(x) + and isNull(_match_date)), _days_for_count), _index), 1))), date) AS total, + breakdown_value AS breakdown_value, + rowNumberInAllBlocks() AS row_number + FROM + (SELECT sum(total) AS count, + day_start AS day_start, + [ifNull(toString(breakdown_value_1), '$$_posthog_breakdown_null_$$')] AS breakdown_value + FROM + (SELECT count(DISTINCT e__pdi.person_id) AS total, + toStartOfDay(toTimeZone(e.timestamp, 'UTC')) AS day_start, + ifNull(nullIf(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, '$some_property'), ''), 'null'), '^"|"$', '')), ''), '$$_posthog_breakdown_null_$$') AS breakdown_value_1 + FROM events AS e SAMPLE 1.0 + INNER JOIN + (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, + person_distinct_id2.distinct_id AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 2) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE and(equals(e.team_id, 2), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))), equals(e.event, 'sign up')) + GROUP BY day_start, + breakdown_value_1) + GROUP BY day_start, + breakdown_value_1 + ORDER BY day_start ASC, breakdown_value ASC) + GROUP BY breakdown_value + ORDER BY if(has(breakdown_value, '$$_posthog_breakdown_other_$$'), 2, if(has(breakdown_value, '$$_posthog_breakdown_null_$$'), 1, 0)) ASC, arraySum(total) DESC, breakdown_value ASC) + WHERE arrayExists(x -> isNotNull(x), breakdown_value) + GROUP BY breakdown_value + ORDER BY if(has(breakdown_value, '$$_posthog_breakdown_other_$$'), 2, if(has(breakdown_value, '$$_posthog_breakdown_null_$$'), 1, 0)) ASC, arraySum(total) DESC, breakdown_value ASC + LIMIT 50000 SETTINGS readonly=2, + max_execution_time=60, + allow_experimental_object_type=1, + format_csv_allow_double_quotes=0, + max_ast_elements=4000000, + max_expanded_ast_elements=4000000, + max_bytes_before_external_group_by=0 ''' # --- # name: TestTrends.test_dau_with_breakdown_filtering_with_sampling.5