Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

MPP-3636: Add type hints to Profile.fxa, handle null cases #4342

Merged
merged 2 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion emails/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
get_supported_language_variant,
)

from allauth.socialaccount.models import SocialAccount
from rest_framework.authtoken.models import Token

from api.exceptions import ErrorContextType, RelayAPIException
Expand Down Expand Up @@ -276,10 +277,11 @@ def at_max_free_aliases(self) -> bool:
return relay_addresses_count >= settings.MAX_NUM_FREE_ALIASES

@property
def fxa(self):
def fxa(self) -> SocialAccount | None:
# Note: we are NOT using .filter() here because it invalidates
# any profile instances that were queried with prefetch_related, which
# we use in at least the profile view to minimize queries
assert hasattr(self.user, "socialaccount_set")
for sa in self.user.socialaccount_set.all():
if sa.provider == "fxa":
return sa
Expand Down
9 changes: 8 additions & 1 deletion emails/tests/models_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ def make_free_test_user(email: str = "") -> User:
user_profile.server_storage = True
user_profile.save()
baker.make(
SocialAccount, user=user, provider="fxa", extra_data={"avatar": "avatar.png"}
SocialAccount,
user=user,
uid=str(uuid4()),
provider="fxa",
extra_data={"avatar": "avatar.png"},
)
return user

Expand Down Expand Up @@ -83,6 +87,7 @@ def upgrade_test_user_to_premium(user):
baker.make(
SocialAccount,
user=user,
uid=str(uuid4()),
provider="fxa",
extra_data={"avatar": "avatar.png", "subscriptions": [random_sub]},
)
Expand Down Expand Up @@ -1116,6 +1121,7 @@ def test_flags_profile_when_emails_forwarded_abuse_threshold_met(self) -> None:
self.profile.update_abuse_metric(email_forwarded=True)
self.abuse_metric.refresh_from_db()

assert self.profile.fxa
self.mocked_abuse_info.assert_called_once_with(
"Abuse flagged",
extra={
Expand All @@ -1139,6 +1145,7 @@ def test_flags_profile_when_forwarded_email_size_abuse_threshold_met(self) -> No
self.profile.update_abuse_metric(forwarded_email_size=50)
self.abuse_metric.refresh_from_db()

assert self.profile.fxa
self.mocked_abuse_info.assert_called_once_with(
"Abuse flagged",
extra={
Expand Down
2 changes: 2 additions & 0 deletions emails/tests/signals_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def test_remove_level_one_email_trackers_enabled(self) -> None:
self.profile.remove_level_one_email_trackers = True
self.profile.save()

assert self.profile.fxa
expected_hashed_uid = sha256(self.profile.fxa.uid.encode("utf-8")).hexdigest()
self.mocked_incr.assert_called_once_with("tracker_removal_enabled")
self.mocked_events_info.assert_called_once_with(
Expand All @@ -45,6 +46,7 @@ def test_remove_level_one_email_trackers_disabled(self) -> None:
self.profile.remove_level_one_email_trackers = False
self.profile.save()

assert self.profile.fxa
expected_hashed_uid = sha256(self.profile.fxa.uid.encode("utf-8")).hexdigest()
self.mocked_incr.assert_called_once_with("tracker_removal_disabled")
self.mocked_events_info.assert_called_once_with(
Expand Down
2 changes: 1 addition & 1 deletion emails/tests/views_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ def test_block_list_email_former_premium_user(self) -> None:
self.ra.save()

# Remove premium from the user
fxa_account = self.premium_user.profile.fxa
assert (fxa_account := self.premium_user.profile.fxa)
fxa_account.extra_data["subscriptions"] = []
fxa_account.save()
assert not self.premium_user.profile.has_premium
Expand Down
8 changes: 8 additions & 0 deletions phones/tests/mgmt_delete_phone_data_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def test_active_user(phone_user: User) -> None:
assert RealPhone.objects.filter(user=phone_user).exists()
relay_number = RelayNumber.objects.get(user=phone_user)
assert InboundContact.objects.filter(relay_number=relay_number).count() == 2
assert phone_user.profile.fxa

stdout = StringIO()
call_command(THE_COMMAND, phone_user.profile.fxa.uid, "--force", stdout=stdout)
Expand Down Expand Up @@ -105,6 +106,7 @@ def test_no_contacts(phone_user: User) -> None:
"""A user's real phone and relay phone are deleted, even without contacts."""
relay_number = RelayNumber.objects.get(user=phone_user)
InboundContact.objects.filter(relay_number=relay_number).delete()
assert phone_user.profile.fxa

stdout = StringIO()
call_command(THE_COMMAND, phone_user.profile.fxa.uid, "--force", stdout=stdout)
Expand Down Expand Up @@ -133,6 +135,7 @@ def test_no_contacts(phone_user: User) -> None:
def test_no_relay_phone(phone_user: User) -> None:
"""A user's real phone is deleted, even without a relay phone setup."""
RelayNumber.objects.filter(user=phone_user).delete()
assert phone_user.profile.fxa

stdout = StringIO()
call_command(THE_COMMAND, phone_user.profile.fxa.uid, "--force", stdout=stdout)
Expand Down Expand Up @@ -160,6 +163,7 @@ def test_no_real_phone(phone_user: User) -> None:
"""Nothing is done if a user doesn't have a real phone setup."""
RelayNumber.objects.filter(user=phone_user).delete()
RealPhone.objects.filter(user=phone_user).delete()
assert phone_user.profile.fxa

stdout = StringIO()
call_command(THE_COMMAND, phone_user.profile.fxa.uid, "--force", stdout=stdout)
Expand Down Expand Up @@ -195,6 +199,7 @@ def test_user_not_found() -> None:

def test_confirm_yes_active_user(phone_user: User) -> None:
"""When the user confirms yes, the data is deleted."""
assert phone_user.profile.fxa
stdout = StringIO()
with patch("builtins.input", return_value="Y"):
call_command(THE_COMMAND, phone_user.profile.fxa.uid, stdout=stdout)
Expand All @@ -221,6 +226,7 @@ def test_confirm_yes_active_user(phone_user: User) -> None:

def test_confirm_no_active_user(phone_user: User) -> None:
"""When the user confirms no, the data is not deleted."""
assert phone_user.profile.fxa
stdout = StringIO()
with patch("builtins.input", return_value="n"):
call_command(THE_COMMAND, phone_user.profile.fxa.uid, stdout=stdout)
Expand Down Expand Up @@ -248,6 +254,7 @@ def test_confirm_no_active_user(phone_user: User) -> None:

def test_confirm_retry_active_user(phone_user: User) -> None:
"""The user keeps trying until they answer Y or N."""
assert phone_user.profile.fxa
stdout = StringIO()
with patch("builtins.input", side_effect=("maybe", "ok no", "no", "n")):
call_command(THE_COMMAND, phone_user.profile.fxa.uid, stdout=stdout)
Expand Down Expand Up @@ -278,6 +285,7 @@ def test_confirm_retry_active_user(phone_user: User) -> None:

def test_confirmation_skipped_when_no_data(phone_user: User) -> None:
"""When the user does not have data, confirmation is skipped."""
assert phone_user.profile.fxa
RelayNumber.objects.filter(user=phone_user).delete()
RealPhone.objects.filter(user=phone_user).delete()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@ def get_next_reset_date(profile: Profile) -> datetime:
if profile.date_phone_subscription_reset is None:
# there is a problem with the sync_phone_related_dates_on_profile
# or a new foxfooder whose date_phone_subscription_reset did not get set in
if profile.fxa:
fxa_uid = profile.fxa.uid
else:
fxa_uid = "None"
logger.error(
"phone_user_profile_dates_not_set",
extra={
"fxa_uid": profile.fxa.uid,
"fxa_uid": fxa_uid,
"date_subscribed_phone": profile.date_phone_subscription_end,
"date_phone_subscription_start": profile.date_phone_subscription_start,
"date_phone_subscription_reset": profile.date_phone_subscription_reset,
Expand Down