🔥(backend) vendor analytics code
Analytics code is now useless, we mostly use frontend tracking.
This commit is contained in:
committed by
aleb_the_flash
parent
b69f777e5a
commit
15e922f9df
@@ -1,58 +0,0 @@
|
|||||||
"""
|
|
||||||
Meet analytics class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from june import analytics as jAnalytics
|
|
||||||
|
|
||||||
|
|
||||||
class Analytics:
|
|
||||||
"""Analytics integration
|
|
||||||
|
|
||||||
This class wraps the June analytics code to avoid coupling our code directly
|
|
||||||
with this third-party library. By doing so, we create a generic interface
|
|
||||||
for analytics that can be easily modified or replaced in the future.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
key = getattr(settings, "ANALYTICS_KEY", None)
|
|
||||||
|
|
||||||
if key is not None:
|
|
||||||
jAnalytics.write_key = key
|
|
||||||
|
|
||||||
self._enabled = key is not None
|
|
||||||
|
|
||||||
def _is_anonymous_user(self, user):
|
|
||||||
"""Check if the user is anonymous."""
|
|
||||||
return user is None or user.is_anonymous
|
|
||||||
|
|
||||||
def identify(self, user, **kwargs):
|
|
||||||
"""Identify a user"""
|
|
||||||
|
|
||||||
if self._is_anonymous_user(user) or not self._enabled:
|
|
||||||
return
|
|
||||||
|
|
||||||
traits = kwargs.pop("traits", {})
|
|
||||||
traits.update({"email": user.email_anonymized})
|
|
||||||
|
|
||||||
jAnalytics.identify(user_id=user.sub, traits=traits, **kwargs)
|
|
||||||
|
|
||||||
def track(self, user, **kwargs):
|
|
||||||
"""Track an event"""
|
|
||||||
|
|
||||||
if not self._enabled:
|
|
||||||
return
|
|
||||||
|
|
||||||
event_data = {}
|
|
||||||
if self._is_anonymous_user(user):
|
|
||||||
event_data["anonymous_id"] = str(uuid.uuid4())
|
|
||||||
else:
|
|
||||||
event_data["user_id"] = user.sub
|
|
||||||
|
|
||||||
jAnalytics.track(**event_data, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
analytics = Analytics()
|
|
||||||
@@ -20,7 +20,6 @@ from rest_framework import (
|
|||||||
|
|
||||||
from core import models, utils
|
from core import models, utils
|
||||||
|
|
||||||
from ..analytics import analytics
|
|
||||||
from . import permissions, serializers
|
from . import permissions, serializers
|
||||||
|
|
||||||
# pylint: disable=too-many-ancestors
|
# pylint: disable=too-many-ancestors
|
||||||
@@ -203,11 +202,6 @@ class RoomViewSet(
|
|||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
data = self.get_serializer(instance).data
|
data = self.get_serializer(instance).data
|
||||||
analytics.track(
|
|
||||||
user=self.request.user,
|
|
||||||
event="Get Room",
|
|
||||||
properties={"slug": instance.slug},
|
|
||||||
)
|
|
||||||
|
|
||||||
return drf_response.Response(data)
|
return drf_response.Response(data)
|
||||||
|
|
||||||
@@ -239,14 +233,6 @@ class RoomViewSet(
|
|||||||
role=models.RoleChoices.OWNER,
|
role=models.RoleChoices.OWNER,
|
||||||
)
|
)
|
||||||
|
|
||||||
analytics.track(
|
|
||||||
user=self.request.user,
|
|
||||||
event="Create Room",
|
|
||||||
properties={
|
|
||||||
"slug": room.slug,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ResourceAccessListModelMixin:
|
class ResourceAccessListModelMixin:
|
||||||
"""List mixin for resource access API."""
|
"""List mixin for resource access API."""
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ from mozilla_django_oidc.auth import (
|
|||||||
|
|
||||||
from core.models import User
|
from core.models import User
|
||||||
|
|
||||||
from ..analytics import analytics
|
|
||||||
|
|
||||||
|
|
||||||
class OIDCAuthenticationBackend(MozillaOIDCAuthenticationBackend):
|
class OIDCAuthenticationBackend(MozillaOIDCAuthenticationBackend):
|
||||||
"""Custom OpenID Connect (OIDC) Authentication Backend.
|
"""Custom OpenID Connect (OIDC) Authentication Backend.
|
||||||
@@ -81,7 +79,6 @@ class OIDCAuthenticationBackend(MozillaOIDCAuthenticationBackend):
|
|||||||
else:
|
else:
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
analytics.identify(user=user)
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def create_user(self, claims):
|
def create_user(self, claims):
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ from mozilla_django_oidc.views import (
|
|||||||
OIDCLogoutView as MozillaOIDCOIDCLogoutView,
|
OIDCLogoutView as MozillaOIDCOIDCLogoutView,
|
||||||
)
|
)
|
||||||
|
|
||||||
from ..analytics import analytics
|
|
||||||
|
|
||||||
|
|
||||||
class OIDCLogoutView(MozillaOIDCOIDCLogoutView):
|
class OIDCLogoutView(MozillaOIDCOIDCLogoutView):
|
||||||
"""Custom logout view for handling OpenID Connect (OIDC) logout flow.
|
"""Custom logout view for handling OpenID Connect (OIDC) logout flow.
|
||||||
@@ -100,10 +98,6 @@ class OIDCLogoutView(MozillaOIDCOIDCLogoutView):
|
|||||||
|
|
||||||
logout_url = self.redirect_url
|
logout_url = self.redirect_url
|
||||||
|
|
||||||
analytics.track(
|
|
||||||
user=request.user,
|
|
||||||
event="Signed Out",
|
|
||||||
)
|
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
logout_url = self.construct_oidc_logout_url(request)
|
logout_url = self.construct_oidc_logout_url(request)
|
||||||
|
|
||||||
|
|||||||
@@ -1,132 +0,0 @@
|
|||||||
"""
|
|
||||||
Test for the Analytics class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# pylint: disable=W0212
|
|
||||||
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from django.contrib.auth.models import AnonymousUser
|
|
||||||
from django.test.utils import override_settings
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from core.analytics import Analytics
|
|
||||||
from core.factories import UserFactory
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.django_db
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="mock_june_analytics")
|
|
||||||
def _mock_june_analytics():
|
|
||||||
with patch("core.analytics.jAnalytics") as mock:
|
|
||||||
yield mock
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY="test_key")
|
|
||||||
def test_analytics_init_enabled(mock_june_analytics):
|
|
||||||
"""Should enable analytics and set the write key correctly when ANALYTICS_KEY is set."""
|
|
||||||
analytics = Analytics()
|
|
||||||
assert analytics._enabled is True
|
|
||||||
assert mock_june_analytics.write_key == "test_key"
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY=None)
|
|
||||||
def test_analytics_init_disabled():
|
|
||||||
"""Should disable analytics when ANALYTICS_KEY is not set."""
|
|
||||||
analytics = Analytics()
|
|
||||||
assert analytics._enabled is False
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY="test_key")
|
|
||||||
def test_analytics_identify_user(mock_june_analytics):
|
|
||||||
"""Should identify a user with the correct traits when analytics is enabled."""
|
|
||||||
user = UserFactory(sub="12345", email="user@example.com")
|
|
||||||
analytics = Analytics()
|
|
||||||
analytics.identify(user)
|
|
||||||
mock_june_analytics.identify.assert_called_once_with(
|
|
||||||
user_id="12345", traits={"email": "***@example.com"}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY="test_key")
|
|
||||||
def test_analytics_identify_user_with_traits(mock_june_analytics):
|
|
||||||
"""Should identify a user with additional traits when analytics is enabled."""
|
|
||||||
user = UserFactory(sub="12345", email="user@example.com")
|
|
||||||
analytics = Analytics()
|
|
||||||
analytics.identify(user, traits={"email": "user@example.com", "foo": "foo"})
|
|
||||||
mock_june_analytics.identify.assert_called_once_with(
|
|
||||||
user_id="12345", traits={"email": "***@example.com", "foo": "foo"}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY=None)
|
|
||||||
def test_analytics_identify_not_enabled(mock_june_analytics):
|
|
||||||
"""Should not call identify when analytics is not enabled."""
|
|
||||||
user = UserFactory(sub="12345", email="user@example.com")
|
|
||||||
analytics = Analytics()
|
|
||||||
analytics.identify(user)
|
|
||||||
mock_june_analytics.identify.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY="test_key")
|
|
||||||
def test_analytics_identify_no_user(mock_june_analytics):
|
|
||||||
"""Should not call identify when the user is None."""
|
|
||||||
analytics = Analytics()
|
|
||||||
analytics.identify(None)
|
|
||||||
mock_june_analytics.identify.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY="test_key")
|
|
||||||
def test_analytics_identify_anonymous_user(mock_june_analytics):
|
|
||||||
"""Should not call identify when the user is anonymous."""
|
|
||||||
user = AnonymousUser()
|
|
||||||
analytics = Analytics()
|
|
||||||
analytics.identify(user)
|
|
||||||
mock_june_analytics.identify.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY="test_key")
|
|
||||||
def test_analytics_track_event(mock_june_analytics):
|
|
||||||
"""Should track an event with the correct user and event details when analytics is enabled."""
|
|
||||||
user = UserFactory(sub="12345")
|
|
||||||
analytics = Analytics()
|
|
||||||
analytics.track(user, event="test_event", foo="foo")
|
|
||||||
mock_june_analytics.track.assert_called_once_with(
|
|
||||||
user_id="12345", event="test_event", foo="foo"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY=None)
|
|
||||||
def test_analytics_track_event_not_enabled(mock_june_analytics):
|
|
||||||
"""Should not call track when analytics is not enabled."""
|
|
||||||
user = UserFactory(sub="12345")
|
|
||||||
analytics = Analytics()
|
|
||||||
analytics.track(user, event="test_event", foo="foo")
|
|
||||||
|
|
||||||
mock_june_analytics.track.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY="test_key")
|
|
||||||
@patch("uuid.uuid4", return_value="test_uuid4")
|
|
||||||
def test_analytics_track_event_no_user(mock_uuid4, mock_june_analytics):
|
|
||||||
"""Should track an event with a random anonymous user ID when the user is None."""
|
|
||||||
analytics = Analytics()
|
|
||||||
analytics.track(None, event="test_event", foo="foo")
|
|
||||||
mock_june_analytics.track.assert_called_once_with(
|
|
||||||
anonymous_id="test_uuid4", event="test_event", foo="foo"
|
|
||||||
)
|
|
||||||
mock_uuid4.assert_called_once()
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ANALYTICS_KEY="test_key")
|
|
||||||
@patch("uuid.uuid4", return_value="test_uuid4")
|
|
||||||
def test_analytics_track_event_anonymous_user(mock_uuid4, mock_june_analytics):
|
|
||||||
"""Should track an event with a random anonymous user ID when the user is anonymous."""
|
|
||||||
user = AnonymousUser()
|
|
||||||
analytics = Analytics()
|
|
||||||
analytics.track(user, event="test_event", foo="foo")
|
|
||||||
mock_june_analytics.track.assert_called_once_with(
|
|
||||||
anonymous_id="test_uuid4", event="test_event", foo="foo"
|
|
||||||
)
|
|
||||||
mock_uuid4.assert_called_once()
|
|
||||||
@@ -505,8 +505,6 @@ class Test(Base):
|
|||||||
|
|
||||||
CELERY_TASK_ALWAYS_EAGER = values.BooleanValue(True)
|
CELERY_TASK_ALWAYS_EAGER = values.BooleanValue(True)
|
||||||
|
|
||||||
ANALYTICS_KEY = None
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
self.INSTALLED_APPS += ["drf_spectacular_sidecar"]
|
self.INSTALLED_APPS += ["drf_spectacular_sidecar"]
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ backend:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
LIVEKIT_API_URL: https://livekit.127.0.0.1.nip.io/
|
LIVEKIT_API_URL: https://livekit.127.0.0.1.nip.io/
|
||||||
ANALYTICS_KEY: xwhoIMCZ8PBRjQ2t
|
|
||||||
ALLOW_UNREGISTERED_ROOMS: False
|
ALLOW_UNREGISTERED_ROOMS: False
|
||||||
FRONTEND_SILENCE_LIVEKIT_DEBUG: False
|
FRONTEND_SILENCE_LIVEKIT_DEBUG: False
|
||||||
FRONTEND_SUPPORT: "{'id': '58ea6697-8eba-4492-bc59-ad6562585041'}"
|
FRONTEND_SUPPORT: "{'id': '58ea6697-8eba-4492-bc59-ad6562585041'}"
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ backend:
|
|||||||
name: backend
|
name: backend
|
||||||
key: LIVEKIT_API_KEY
|
key: LIVEKIT_API_KEY
|
||||||
LIVEKIT_API_URL: https://livekit-preprod.beta.numerique.gouv.fr
|
LIVEKIT_API_URL: https://livekit-preprod.beta.numerique.gouv.fr
|
||||||
ANALYTICS_KEY: mwuxTKi8o2xzWH54
|
|
||||||
ALLOW_UNREGISTERED_ROOMS: False
|
ALLOW_UNREGISTERED_ROOMS: False
|
||||||
FRONTEND_SILENCE_LIVEKIT_DEBUG: False
|
FRONTEND_SILENCE_LIVEKIT_DEBUG: False
|
||||||
FRONTEND_ANALYTICS: "{'id': 'phc_RPYko028Oqtj0c9exLIWwrlrjLxSdxT0ntW0Lam4iom', 'host': 'https://product.visio.numerique.gouv.fr'}"
|
FRONTEND_ANALYTICS: "{'id': 'phc_RPYko028Oqtj0c9exLIWwrlrjLxSdxT0ntW0Lam4iom', 'host': 'https://product.visio.numerique.gouv.fr'}"
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ backend:
|
|||||||
name: backend
|
name: backend
|
||||||
key: LIVEKIT_API_KEY
|
key: LIVEKIT_API_KEY
|
||||||
LIVEKIT_API_URL: https://livekit-staging.beta.numerique.gouv.fr
|
LIVEKIT_API_URL: https://livekit-staging.beta.numerique.gouv.fr
|
||||||
ANALYTICS_KEY: Roi1k6IAc2DEqHB0
|
|
||||||
ALLOW_UNREGISTERED_ROOMS: False
|
ALLOW_UNREGISTERED_ROOMS: False
|
||||||
FRONTEND_ANALYTICS: "{'id': 'phc_RPYko028Oqtj0c9exLIWwrlrjLxSdxT0ntW0Lam4iom', 'host': 'https://product.visio-staging.beta.numerique.gouv.fr'}"
|
FRONTEND_ANALYTICS: "{'id': 'phc_RPYko028Oqtj0c9exLIWwrlrjLxSdxT0ntW0Lam4iom', 'host': 'https://product.visio-staging.beta.numerique.gouv.fr'}"
|
||||||
FRONTEND_SUPPORT: "{'id': '58ea6697-8eba-4492-bc59-ad6562585041'}"
|
FRONTEND_SUPPORT: "{'id': '58ea6697-8eba-4492-bc59-ad6562585041'}"
|
||||||
|
|||||||
Reference in New Issue
Block a user