diff --git a/pontoon/base/models/comment.py b/pontoon/base/models/comment.py
index 30aba44118..f2d653f5c7 100644
--- a/pontoon/base/models/comment.py
+++ b/pontoon/base/models/comment.py
@@ -32,7 +32,7 @@ def serialize(self, project_contact):
"author": self.author.name_or_email,
"username": self.author.username,
"user_banner": self.author.banner(locale, project_contact),
- "user_gravatar_url_small": self.author.gravatar_url(88),
+ "user_gravatar_url_small": self.author.avatar_url(88),
"created_at": self.timestamp.strftime("%b %d, %Y %H:%M"),
"date_iso": self.timestamp.isoformat(),
"content": self.content,
diff --git a/pontoon/base/models/translation.py b/pontoon/base/models/translation.py
index 82682a7fbd..0e0594cf5a 100644
--- a/pontoon/base/models/translation.py
+++ b/pontoon/base/models/translation.py
@@ -90,7 +90,7 @@ def authors(self):
"email": user.email,
"display_name": user.name_or_email,
"id": user.id,
- "gravatar_url": user.gravatar_url(88),
+ "gravatar_url": user.avatar_url(88),
"translation_count": user.translations_count,
"role": user.user_role,
}
diff --git a/pontoon/base/models/user.py b/pontoon/base/models/user.py
index 9f89a208ef..464f8a5f23 100644
--- a/pontoon/base/models/user.py
+++ b/pontoon/base/models/user.py
@@ -22,7 +22,13 @@ def user_profile_url(self):
)
-def user_gravatar_url(self, size):
+def user_avatar_url(self, size):
+ fxa_account = self.socialaccount_set.filter(provider="fxa").first()
+ if fxa_account:
+ fxa_avatar = fxa_account.extra_data.get("avatar")
+ if fxa_avatar:
+ return fxa_avatar
+
email = md5(self.email.lower().encode("utf-8")).hexdigest()
data = {
"s": str(size),
@@ -40,8 +46,8 @@ def user_gravatar_url(self, size):
@property
-def user_gravatar_url_small(self):
- return user_gravatar_url(self, 88)
+def user_avatar_url_small(self):
+ return user_avatar_url(self, 88)
@property
@@ -512,7 +518,7 @@ def user_serialize(self):
"""Serialize Project contact"""
return {
- "avatar": self.gravatar_url_small,
+ "avatar": self.avatar_url_small,
"name": self.name_or_email,
"url": self.profile_url,
}
@@ -533,8 +539,8 @@ def latest_action(self):
User.add_to_class("profile_url", user_profile_url)
-User.add_to_class("gravatar_url", user_gravatar_url)
-User.add_to_class("gravatar_url_small", user_gravatar_url_small)
+User.add_to_class("avatar_url", user_avatar_url)
+User.add_to_class("avatar_url_small", user_avatar_url_small)
User.add_to_class("name_or_email", user_name_or_email)
User.add_to_class("contact_email", user_contact_email)
User.add_to_class("display_name", user_display_name)
diff --git a/pontoon/base/templates/allauth/layouts/base.html b/pontoon/base/templates/allauth/layouts/base.html
index b8bf445348..a2e80b50c3 100644
--- a/pontoon/base/templates/allauth/layouts/base.html
+++ b/pontoon/base/templates/allauth/layouts/base.html
@@ -100,7 +100,7 @@
{% if user.is_authenticated %}
diff --git a/pontoon/base/templates/widgets/latest_activity.html b/pontoon/base/templates/widgets/latest_activity.html
index 6dba6ccbbd..3eca62f1b2 100644
--- a/pontoon/base/templates/widgets/latest_activity.html
+++ b/pontoon/base/templates/widgets/latest_activity.html
@@ -5,7 +5,7 @@
{% set action = latest_activity.type + ' by' %}
{% set user = latest_activity.user.name_or_email %}
{% set link = url('pontoon.contributors.contributor.username', latest_activity.user.username) %}
- {% set avatar = latest_activity.user.gravatar_url(88) %}
+ {% set avatar = latest_activity.user.avatar_url(88) %}
{% else %}
{% set action = 'imported' %}
{% set user = '' %}
diff --git a/pontoon/base/templates/widgets/profile.html b/pontoon/base/templates/widgets/profile.html
index 44963b706d..c74dcb615f 100644
--- a/pontoon/base/templates/widgets/profile.html
+++ b/pontoon/base/templates/widgets/profile.html
@@ -3,7 +3,7 @@
{% if user.is_authenticated %}
@@ -21,7 +21,7 @@
>
diff --git a/pontoon/base/tests/models/test_comment.py b/pontoon/base/tests/models/test_comment.py
index e622cf16e5..effa277bcf 100644
--- a/pontoon/base/tests/models/test_comment.py
+++ b/pontoon/base/tests/models/test_comment.py
@@ -13,7 +13,7 @@ def test_serialize_comments(comment_a, team_comment_a):
"user_banner": comment_a.author.banner(
comment_a.translation.locale, project.contact
),
- "user_gravatar_url_small": comment_a.author.gravatar_url(88),
+ "user_gravatar_url_small": comment_a.author.avatar_url(88),
"created_at": comment_a.timestamp.strftime("%b %d, %Y %H:%M"),
"date_iso": comment_a.timestamp.isoformat(),
"content": comment_a.content,
@@ -27,7 +27,7 @@ def test_serialize_comments(comment_a, team_comment_a):
"user_banner": team_comment_a.author.banner(
team_comment_a.locale, project.contact
),
- "user_gravatar_url_small": team_comment_a.author.gravatar_url(88),
+ "user_gravatar_url_small": team_comment_a.author.avatar_url(88),
"created_at": team_comment_a.timestamp.strftime("%b %d, %Y %H:%M"),
"date_iso": team_comment_a.timestamp.isoformat(),
"content": team_comment_a.content,
diff --git a/pontoon/base/tests/models/test_user.py b/pontoon/base/tests/models/test_user.py
index 7b573c4278..18a3b9bed9 100644
--- a/pontoon/base/tests/models/test_user.py
+++ b/pontoon/base/tests/models/test_user.py
@@ -2,6 +2,7 @@
import pytest
+from allauth.socialaccount.models import SocialAccount
from notifications.models import Notification
from notifications.signals import notify
@@ -199,3 +200,32 @@ def test_serialized_notifications_new_string_without_created_time(user_a, projec
assert notification["actor"]["url"] == (
f"/projects/{project_a.slug}/all-resources/?status=missing,pretranslated"
)
+
+
+@pytest.mark.django_db
+def test_gravatar_url_returns_fxa_avatar_when_linked(user_a):
+ SocialAccount.objects.create(
+ user=user_a,
+ provider="fxa",
+ uid="1234",
+ extra_data={"avatar": "https://profile.accounts.firefox.com/v1/avatar/abc"},
+ )
+ assert user_a.avatar_url(88) == "https://profile.accounts.firefox.com/v1/avatar/abc"
+
+
+@pytest.mark.django_db
+def test_gravatar_url_falls_back_to_gravatar_when_no_fxa(user_a):
+ url = user_a.avatar_url(88)
+ assert "gravatar.com/avatar/" in url
+
+
+@pytest.mark.django_db
+def test_gravatar_url_falls_back_to_gravatar_when_fxa_has_no_avatar(user_a):
+ SocialAccount.objects.create(
+ user=user_a,
+ provider="fxa",
+ uid="1234",
+ extra_data={},
+ )
+ url = user_a.avatar_url(88)
+ assert "gravatar.com/avatar/" in url
diff --git a/pontoon/base/views.py b/pontoon/base/views.py
index 0b7b444b75..c8f97e9b24 100755
--- a/pontoon/base/views.py
+++ b/pontoon/base/views.py
@@ -474,7 +474,7 @@ def get_translation_history(request):
"user": u.name_or_email,
"uid": u.id,
"username": u.username,
- "user_gravatar_url_small": u.gravatar_url(88),
+ "user_gravatar_url_small": u.avatar_url(88),
"user_banner": u.banner(locale, project_contact),
"date": t.date,
"approved_user": User.display_name_or_blank(t.approved_user),
@@ -834,7 +834,7 @@ def get_users(request):
for u in users:
payload.append(
{
- "gravatar": u.gravatar_url(44),
+ "gravatar": u.avatar_url(44),
"name": u.name_or_email,
"url": u.profile_url,
"username": u.profile.username,
@@ -1051,8 +1051,8 @@ def user_data(request):
"tour_status": user.profile.tour_status,
"has_dismissed_addon_promotion": user.profile.has_dismissed_addon_promotion,
"logout_url": logout_url,
- "gravatar_url_small": user.gravatar_url(88),
- "gravatar_url_big": user.gravatar_url(176),
+ "gravatar_url_small": user.avatar_url(88),
+ "gravatar_url_big": user.avatar_url(176),
"notifications": user.serialized_notifications,
"theme": user.profile.theme,
}
diff --git a/pontoon/contributors/templates/contributors/contributors.html b/pontoon/contributors/templates/contributors/contributors.html
index 4c0848dbd5..074bc86eb3 100644
--- a/pontoon/contributors/templates/contributors/contributors.html
+++ b/pontoon/contributors/templates/contributors/contributors.html
@@ -60,7 +60,7 @@