privaterelay/signals.py (75 lines of code) (raw):
import logging
from hashlib import sha256
from typing import Any
from django.contrib.auth.models import User
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from django.http import HttpRequest
from allauth.account.signals import user_logged_in, user_signed_up
from rest_framework.authtoken.models import Token
from emails.utils import incr_if_enabled, set_user_group
from .models import Profile
info_logger = logging.getLogger("eventsinfo")
@receiver(user_signed_up, dispatch_uid="privaterelay_record_user_signed_up")
def record_user_signed_up(request: HttpRequest, user: User, **kwargs: Any) -> None:
incr_if_enabled("user_signed_up", 1)
# the user_signed_up signal doesn't have access to the response object
# so we have to set a user_created session var for user_logged_in receiver
request.session["user_created"] = True
request.session.modified = True
@receiver(user_logged_in, dispatch_uid="privaterelay_record_user_logged_in")
def record_user_logged_in(request: HttpRequest, user: User, **kwargs: Any) -> None:
incr_if_enabled("user_logged_in", 1)
response = kwargs.get("response")
event = "user_logged_in"
# the user_signed_up signal doesn't have access to the response object
# so we have to check for user_created session var from user_signed_up
if request.session.get("user_created", False):
event = "user_signed_up"
if response:
response.set_cookie(f"server_ga_event:{event}", event, max_age=5)
@receiver(post_save, sender=User, dispatch_uid="privaterelay_create_user_profile")
def create_user_profile(
sender: type[User], instance: User, created: bool, **kwargs: Any
) -> None:
if created:
set_user_group(instance)
Profile.objects.create(user=instance)
@receiver(pre_save, sender=Profile, dispatch_uid="measure_feature_usage")
def measure_feature_usage(
sender: type[Profile], instance: Profile, **kwargs: Any
) -> None:
if instance._state.adding:
# if newly created Profile ignore the signal
return
curr_profile = Profile.objects.get(id=instance.id)
# measure tracker removal usage
changed_tracker_removal_setting = (
instance.remove_level_one_email_trackers
!= curr_profile.remove_level_one_email_trackers
)
if changed_tracker_removal_setting:
if instance.remove_level_one_email_trackers:
incr_if_enabled("tracker_removal_enabled")
if not instance.remove_level_one_email_trackers:
incr_if_enabled("tracker_removal_disabled")
if instance.fxa:
# TODO create a utility function or property for hashed fxa uid
hashed_uid = sha256(instance.fxa.uid.encode("utf-8")).hexdigest()
else:
hashed_uid = "_no_fxa_"
info_logger.info(
"tracker_removal_feature",
extra={
"enabled": instance.remove_level_one_email_trackers,
"hashed_uid": hashed_uid,
},
)
@receiver(post_save, sender=Profile, dispatch_uid="privaterelay_copy_auth_token")
def copy_auth_token(
sender: type[Profile],
instance: Profile | None = None,
created: bool = False,
**kwargs: Any,
) -> None:
if created and instance is not None:
# baker triggers created during tests
# so first check the user doesn't already have a Token
if not hasattr(Token, "objects"):
raise AttributeError("Token must have objects attribute.")
try:
Token.objects.get(user=instance.user)
return
except Token.DoesNotExist:
Token.objects.create(user=instance.user, key=instance.api_token)