diff --git a/ee/api/test/__snapshots__/test_organization_resource_access.ambr b/ee/api/test/__snapshots__/test_organization_resource_access.ambr index 98e6953f9694f..735b995e23ca1 100644 --- a/ee/api/test/__snapshots__/test_organization_resource_access.ambr +++ b/ee/api/test/__snapshots__/test_organization_resource_access.ambr @@ -17,6 +17,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -232,6 +233,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/frontend/src/layout.html b/frontend/src/layout.html index 73a3be28423f9..f3468333c3d5a 100644 --- a/frontend/src/layout.html +++ b/frontend/src/layout.html @@ -1,119 +1,289 @@ - - - PostHog - {% include "head.html" %} - - - - - - {% block head %} {% endblock %} - - - {% include "overlays.html" %} {% block content %} {% endblock %} - - + + + + PostHog + {% include "head.html" %} + + + + + + + + {% block head %} {% endblock %} + + + + {% include "overlays.html" %} {% block content %} {% endblock %} + + + \ No newline at end of file diff --git a/latest_migrations.manifest b/latest_migrations.manifest index 988a599c74b76..19b1ed1ff968b 100644 --- a/latest_migrations.manifest +++ b/latest_migrations.manifest @@ -5,7 +5,7 @@ contenttypes: 0002_remove_content_type_name ee: 0015_add_verified_properties otp_static: 0002_throttling otp_totp: 0002_auto_20190420_0723 -posthog: 0381_alter_externaldatasource_source_type +posthog: 0382_user_strapi_id sessions: 0001_initial social_django: 0010_uid_db_index two_factor: 0007_auto_20201201_1019 diff --git a/posthog/admin.py b/posthog/admin.py index 1b4ab747135a4..a0495f0e765b7 100644 --- a/posthog/admin.py +++ b/posthog/admin.py @@ -480,6 +480,7 @@ class UserAdmin(DjangoUserAdmin): "current_organization", "is_email_verified", "pending_email", + "strapi_id", ) }, ), diff --git a/posthog/api/test/__snapshots__/test_action.ambr b/posthog/api/test/__snapshots__/test_action.ambr index f5e8136daefff..d12e99524a0c9 100644 --- a/posthog/api/test/__snapshots__/test_action.ambr +++ b/posthog/api/test/__snapshots__/test_action.ambr @@ -17,6 +17,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -114,6 +115,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -175,6 +177,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -326,6 +329,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -468,6 +472,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -505,6 +510,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_annotation.ambr b/posthog/api/test/__snapshots__/test_annotation.ambr index fbef97f48826e..ce84928133d9a 100644 --- a/posthog/api/test/__snapshots__/test_annotation.ambr +++ b/posthog/api/test/__snapshots__/test_annotation.ambr @@ -17,6 +17,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -98,6 +99,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -261,6 +263,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -426,6 +429,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -589,6 +593,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_decide.ambr b/posthog/api/test/__snapshots__/test_decide.ambr index 79f2ae80438a2..7cfe7fc4886d1 100644 --- a/posthog/api/test/__snapshots__/test_decide.ambr +++ b/posthog/api/test/__snapshots__/test_decide.ambr @@ -20,6 +20,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -195,6 +196,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -264,6 +266,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -423,6 +426,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_early_access_feature.ambr b/posthog/api/test/__snapshots__/test_early_access_feature.ambr index b897f4cd38c24..3892cdf5a24dd 100644 --- a/posthog/api/test/__snapshots__/test_early_access_feature.ambr +++ b/posthog/api/test/__snapshots__/test_early_access_feature.ambr @@ -121,6 +121,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_element.ambr b/posthog/api/test/__snapshots__/test_element.ambr index 860921b938e23..44e1f20f086b6 100644 --- a/posthog/api/test/__snapshots__/test_element.ambr +++ b/posthog/api/test/__snapshots__/test_element.ambr @@ -17,6 +17,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_feature_flag.ambr b/posthog/api/test/__snapshots__/test_feature_flag.ambr index 822f395d4a690..e6e9c597b21f8 100644 --- a/posthog/api/test/__snapshots__/test_feature_flag.ambr +++ b/posthog/api/test/__snapshots__/test_feature_flag.ambr @@ -1499,6 +1499,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1920,6 +1921,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_insight.ambr b/posthog/api/test/__snapshots__/test_insight.ambr index 6c6c7ca4b888a..409e1bd46dd5b 100644 --- a/posthog/api/test/__snapshots__/test_insight.ambr +++ b/posthog/api/test/__snapshots__/test_insight.ambr @@ -607,6 +607,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1017,6 +1018,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1242,6 +1244,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1266,6 +1269,7 @@ T4."is_email_verified", T4."requested_password_reset_at", T4."has_seen_product_intro_for", + T4."strapi_id", T4."email_opt_in", T4."theme_mode", T4."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr b/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr index f049fa11b9a0e..06422e173c614 100644 --- a/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr +++ b/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr @@ -17,6 +17,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1589,6 +1590,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1741,6 +1743,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1772,6 +1775,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_plugin.ambr b/posthog/api/test/__snapshots__/test_plugin.ambr index 12888a4afdf3b..9824b517236aa 100644 --- a/posthog/api/test/__snapshots__/test_plugin.ambr +++ b/posthog/api/test/__snapshots__/test_plugin.ambr @@ -17,6 +17,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -140,6 +141,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -296,6 +298,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -509,6 +512,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_preflight.ambr b/posthog/api/test/__snapshots__/test_preflight.ambr index 4c09f1c4e1c49..7a687741a3e40 100644 --- a/posthog/api/test/__snapshots__/test_preflight.ambr +++ b/posthog/api/test/__snapshots__/test_preflight.ambr @@ -17,6 +17,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/__snapshots__/test_survey.ambr b/posthog/api/test/__snapshots__/test_survey.ambr index 60b3a63676a7f..d9c31db6fc9e2 100644 --- a/posthog/api/test/__snapshots__/test_survey.ambr +++ b/posthog/api/test/__snapshots__/test_survey.ambr @@ -96,6 +96,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr b/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr index f83d0b0b2ec0e..7f55ce88d93ee 100644 --- a/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr +++ b/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr @@ -17,6 +17,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -144,6 +145,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -364,6 +366,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -560,6 +563,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -584,6 +588,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -908,6 +913,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -932,6 +938,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -1448,6 +1455,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -2401,6 +2409,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -2629,6 +2638,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -2791,6 +2801,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -3221,6 +3232,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -3245,6 +3257,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -3726,6 +3739,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -4006,6 +4020,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -5149,6 +5164,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -6154,6 +6170,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -6178,6 +6195,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -6483,6 +6501,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -6564,6 +6583,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -6733,6 +6753,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -6899,6 +6920,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -6923,6 +6945,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -7298,6 +7321,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -7322,6 +7346,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -9648,6 +9673,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -9845,6 +9871,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -9966,6 +9993,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -9990,6 +10018,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -10244,6 +10273,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -10410,6 +10440,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -10434,6 +10465,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -10489,6 +10521,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -10675,6 +10708,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -10699,6 +10733,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -10757,6 +10792,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -11129,6 +11165,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -11153,6 +11190,7 @@ T6."is_email_verified", T6."requested_password_reset_at", T6."has_seen_product_intro_for", + T6."strapi_id", T6."email_opt_in", T6."theme_mode", T6."partial_notification_settings", @@ -11211,6 +11249,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -11450,6 +11489,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr b/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr index ea83d38195a8f..4c9660eb664b3 100644 --- a/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr +++ b/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr @@ -17,6 +17,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -139,6 +140,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -169,6 +171,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -310,6 +313,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -392,6 +396,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -436,6 +441,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -622,6 +628,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -646,6 +653,7 @@ T4."is_email_verified", T4."requested_password_reset_at", T4."has_seen_product_intro_for", + T4."strapi_id", T4."email_opt_in", T4."theme_mode", T4."partial_notification_settings", diff --git a/posthog/api/user.py b/posthog/api/user.py index 26e887237906b..df5ea0c3d92ee 100644 --- a/posthog/api/user.py +++ b/posthog/api/user.py @@ -27,6 +27,9 @@ from two_factor.forms import TOTPDeviceForm from two_factor.utils import default_device +import time +import jwt +from datetime import datetime, timedelta from posthog.api.decide import hostname_in_allowed_url_list from posthog.api.email_verification import EmailVerifier from posthog.api.organization import OrganizationSerializer @@ -46,6 +49,7 @@ from posthog.tasks.email import send_email_change_emails from posthog.user_permissions import UserPermissions from posthog.utils import get_js_url +from posthog.constants import PERMITTED_FORUM_DOMAINS class UserAuthenticationThrottle(UserRateThrottle): @@ -456,6 +460,58 @@ def redirect_to_site(request): return redirect("{}#__posthog={}".format(app_url, state)) +@authenticate_secondarily +def redirect_to_website(request): + team = request.user.team + app_url = request.GET.get("appUrl") or (team.app_urls and team.app_urls[0]) + + if not app_url: + return HttpResponse(status=404) + + if not team or urllib.parse.urlparse(app_url).hostname not in PERMITTED_FORUM_DOMAINS: + return HttpResponse(f"Can only redirect to a permitted domain.", status=403) + + token = "" + + # check if a strapi id is attached + if request.user.strapi_id is None: + response = requests.request( + "POST", + "https://squeak.posthog.cc/api/auth/local/register", + json={ + "username": request.user.email, + "email": request.user.email, + "password": secrets.token_hex(32), + "firstName": request.user.first_name, + "lastName": request.user.last_name, + }, + headers={"Content-Type": "application/json"}, + ) + + if response.status_code == 200: + json_data = response.json() + token = json_data["jwt"] + strapi_id = json_data["user"]["id"] + request.user.strapi_id = strapi_id + request.user.save() + else: + token = jwt.encode( + { + "id": request.user.strapi_id, + "iat": int(time.time()), + "exp": int((datetime.now() + timedelta(days=30)).timestamp()), + }, + os.environ.get("JWT_SECRET_STRAPI", "random_fallback_secret"), + algorithm="HS256", + ) + + # pass the empty string as the safe param so that `//` is encoded correctly. + # see https://github.com/PostHog/posthog/issues/9671 + userData = urllib.parse.quote(json.dumps({"jwt": token}), safe="") + + return redirect("{}?userData={}&redirect={}".format("https://posthog.com/auth", userData, app_url)) + + @require_http_methods(["POST"]) @authenticate_secondarily def test_slack_webhook(request): diff --git a/posthog/constants.py b/posthog/constants.py index 3110b3ff2da9c..a47116f77263a 100644 --- a/posthog/constants.py +++ b/posthog/constants.py @@ -303,3 +303,5 @@ class FlagRequestType(str, Enum): ENRICHED_DASHBOARD_INSIGHT_IDENTIFIER = "Feature Viewed" DATA_WAREHOUSE_TASK_QUEUE = "data-warehouse-task-queue" BATCH_EXPORTS_TASK_QUEUE = "no-sandbox-python-django" + +PERMITTED_FORUM_DOMAINS = ["localhost", "posthog.com"] diff --git a/posthog/migrations/0382_user_strapi_id.py b/posthog/migrations/0382_user_strapi_id.py new file mode 100644 index 0000000000000..211d03e1a57c3 --- /dev/null +++ b/posthog/migrations/0382_user_strapi_id.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.19 on 2024-01-05 10:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("posthog", "0381_alter_externaldatasource_source_type"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="strapi_id", + field=models.PositiveSmallIntegerField(blank=True, null=True), + ), + ] diff --git a/posthog/models/test/test_user_model.py b/posthog/models/test/test_user_model.py index 9c07f36b16466..76356c6049f3b 100644 --- a/posthog/models/test/test_user_model.py +++ b/posthog/models/test/test_user_model.py @@ -40,6 +40,7 @@ def test_analytics_metadata(self): "joined_at": user.date_joined, "has_social_auth": False, "social_providers": [], + "strapi_id": None, "instance_url": "http://localhost:8000", "instance_tag": "none", "is_email_verified": None, @@ -76,6 +77,7 @@ def test_analytics_metadata(self): "joined_at": user_2.date_joined, "has_social_auth": False, "social_providers": [], + "strapi_id": None, "instance_url": "http://localhost:8000", "instance_tag": "none", "is_email_verified": None, diff --git a/posthog/models/user.py b/posthog/models/user.py index 17a7e176a71bc..04fa79ef3da45 100644 --- a/posthog/models/user.py +++ b/posthog/models/user.py @@ -143,6 +143,7 @@ class User(AbstractUser, UUIDClassicModel): is_email_verified: models.BooleanField = models.BooleanField(null=True, blank=True) requested_password_reset_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) has_seen_product_intro_for: models.JSONField = models.JSONField(null=True, blank=True) + strapi_id: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField(null=True, blank=True) # Preferences / configuration options email_opt_in: models.BooleanField = models.BooleanField(default=False, null=True, blank=True) @@ -317,6 +318,7 @@ def get_analytics_metadata(self): "instance_tag": INSTANCE_TAG, "is_email_verified": self.is_email_verified, "has_seen_product_intro_for": self.has_seen_product_intro_for, + "strapi_id": self.strapi_id, } __repr__ = sane_repr("email", "first_name", "distinct_id") diff --git a/posthog/queries/app_metrics/test/__snapshots__/test_historical_exports.ambr b/posthog/queries/app_metrics/test/__snapshots__/test_historical_exports.ambr index eb8d4d3065382..4883d5bf60349 100644 --- a/posthog/queries/app_metrics/test/__snapshots__/test_historical_exports.ambr +++ b/posthog/queries/app_metrics/test/__snapshots__/test_historical_exports.ambr @@ -90,6 +90,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -144,6 +145,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -198,6 +200,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -252,6 +255,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr b/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr index 316dfa79893ba..c0ddaa28bbc82 100644 --- a/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr +++ b/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr @@ -307,6 +307,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1078,6 +1079,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1228,6 +1230,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1586,6 +1589,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -1957,6 +1961,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -2374,6 +2379,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -2540,6 +2546,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -2757,6 +2764,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -3606,6 +3614,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -3967,6 +3976,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -4319,6 +4329,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -4684,6 +4695,7 @@ "posthog_user"."distinct_id", "posthog_user"."is_email_verified", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr b/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr index e0f024e21038f..8797637ca1f61 100644 --- a/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr +++ b/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr @@ -261,6 +261,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", @@ -419,6 +420,7 @@ "posthog_user"."is_email_verified", "posthog_user"."requested_password_reset_at", "posthog_user"."has_seen_product_intro_for", + "posthog_user"."strapi_id", "posthog_user"."email_opt_in", "posthog_user"."theme_mode", "posthog_user"."partial_notification_settings", diff --git a/posthog/templates/authorize_and_link.html b/posthog/templates/authorize_and_link.html new file mode 100644 index 0000000000000..3af72f40d16eb --- /dev/null +++ b/posthog/templates/authorize_and_link.html @@ -0,0 +1,43 @@ +{% extends 'layout.html' %} + +{% block content %} +
+
+ + + + + + + + + + +
+ +
+ +

Link accounts

+

Do you want to link {{ domain }} using your PostHog Cloud ({{ email}}) account?

+ + + + Authorize + {{ domain }} + + +
+
+{% endblock %} \ No newline at end of file diff --git a/posthog/templates/authorize_and_redirect.html b/posthog/templates/authorize_and_redirect.html index ab06dda575064..e76df0c93162d 100644 --- a/posthog/templates/authorize_and_redirect.html +++ b/posthog/templates/authorize_and_redirect.html @@ -1,18 +1,50 @@ {% extends 'layout.html' %} {% block content %} +
+
+ + + + + + + + + + +
+
- Do you want to give the PostHog toolbar on {{ redirect_url }} access to your PostHog data? -

- With the toolbar, you can: + +

Link URL

+

Do you want to give the PostHog toolbar on {{ redirect_url }} access to your PostHog data? +

+

With the toolbar, you can:

- - Authorize - {{ domain }} + + + + Authorize + {{ domain }} +
-{% endblock %} +
+{% endblock %} \ No newline at end of file diff --git a/posthog/urls.py b/posthog/urls.py index 57dfd0feca942..17c2751a745c9 100644 --- a/posthog/urls.py +++ b/posthog/urls.py @@ -55,6 +55,7 @@ stats, ) from .year_in_posthog import year_in_posthog +from posthog.constants import PERMITTED_FORUM_DOMAINS import structlog @@ -108,8 +109,13 @@ def authorize_and_redirect(request: HttpRequest) -> HttpResponse: current_team = cast(User, request.user).team referer_url = urlparse(request.META["HTTP_REFERER"]) redirect_url = urlparse(request.GET["redirect"]) + is_forum_login = request.GET.get("forum_login", "").lower() == "true" - if not current_team or not hostname_in_allowed_url_list(current_team.app_urls, redirect_url.hostname): + if ( + not current_team + or (redirect_url.hostname not in PERMITTED_FORUM_DOMAINS and is_forum_login) + or (not is_forum_login and not hostname_in_allowed_url_list(current_team.app_urls, redirect_url.hostname)) + ): return HttpResponse(f"Can only redirect to a permitted domain.", status=403) if referer_url.hostname != redirect_url.hostname: @@ -131,9 +137,10 @@ def authorize_and_redirect(request: HttpRequest) -> HttpResponse: ) return render_template( - "authorize_and_redirect.html", + "authorize_and_link.html" if is_forum_login else "authorize_and_redirect.html", request=request, context={ + "email": request.user, "domain": redirect_url.hostname, "redirect_url": request.GET["redirect"], }, @@ -173,6 +180,7 @@ def opt_slash_path(route: str, view: Callable, name: Optional[str] = None) -> UR path("api/", include(router.urls)), path("", include(tf_urls)), opt_slash_path("api/user/redirect_to_site", user.redirect_to_site), + opt_slash_path("api/user/redirect_to_website", user.redirect_to_website), opt_slash_path("api/user/test_slack_webhook", user.test_slack_webhook), opt_slash_path("api/prompts/webhook", prompt_webhook), opt_slash_path("api/early_access_features", early_access_features),