This commit is contained in:
Iliyan Angelov
2025-09-14 23:24:25 +03:00
commit c67067a2a4
71311 changed files with 6800714 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
from allauth.socialaccount.providers.base import ProviderAccount
from allauth.socialaccount.providers.oauth2.provider import OAuth2Provider
class StravaAccount(ProviderAccount):
def get_profile_url(self):
id = self.account.extra_data.get("id")
if id:
return "https://www.strava.com/athletes/{}".format(id)
return None
def get_avatar_url(self):
avatar = self.account.extra_data.get("profile")
if avatar and avatar != "avatar/athlete/large.png":
return avatar
return None
def to_str(self):
name = super(StravaAccount, self).to_str()
return self.account.extra_data.get("name", name)
class StravaProvider(OAuth2Provider):
id = "strava"
name = "Strava"
account_class = StravaAccount
def extract_uid(self, data):
return str(data["id"])
def extract_common_fields(self, data):
extra_common = super(StravaProvider, self).extract_common_fields(data)
firstname = data.get("firstname")
lastname = data.get("lastname")
name = " ".join(part for part in (firstname, lastname) if part)
extra_common.update(
username=data.get("username"),
email=data.get("email"),
first_name=firstname,
last_name=lastname,
name=name.strip(),
)
return extra_common
def get_default_scope(self):
return ["read,activity:read"]
provider_classes = [StravaProvider]

View File

@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib.auth.models import User
from allauth.socialaccount.models import SocialAccount
from allauth.socialaccount.tests import OAuth2TestsMixin
from allauth.tests import MockedResponse, TestCase
from .provider import StravaProvider
class StravaTests(OAuth2TestsMixin, TestCase):
provider_id = StravaProvider.id
def get_mocked_response(self):
return MockedResponse(
200,
"""{
"id": 32641234,
"username": null,
"resource_state": 2,
"firstname": "georges",
"lastname": "camembert",
"city": "London",
"state": "England",
"country": "United Kingdom",
"sex": "M",
"premium": false,
"summit": false,
"created_at": "2017-07-12T12:42:52Z",
"updated_at": "2017-10-21T11:01:23Z",
"badge_type_id": 0,
"profile_medium": "avatar/athlete/medium.png",
"profile": "avatar/athlete/large.png",
"friend": null,
"follower": null,
"email": "bill@example.com"
}""",
) # noqa
def get_mocked_response_avatar_invalid_id(self):
"""Profile including realistic avatar URL
user ID set to 0 to test edge case where id would be missing"""
return MockedResponse(
200,
"""{
"id": 0,
"username": null,
"resource_state": 2,
"firstname": "georges",
"lastname": "camembert",
"city": "London",
"state": "England",
"country": "United Kingdom",
"sex": "M",
"premium": false,
"summit": false,
"created_at": "2017-07-12T12:42:52Z",
"updated_at": "2017-10-21T11:01:23Z",
"badge_type_id": 0,
"profile_medium": "https://cloudfront.net/1/medium.jpg",
"profile": "https://cloudfront.net/1/large.jpg",
"friend": null,
"follower": null,
"email": "bill@example.com"
}""",
) # noqa
def test_valid_avatar(self):
"""test response with Avatar URL"""
self.login(self.get_mocked_response_avatar_invalid_id())
user = User.objects.get(email="bill@example.com")
soc_acc = SocialAccount.objects.filter(
user=user, provider=self.provider.id
).get()
provider_account = soc_acc.get_provider_account()
self.assertEqual(
provider_account.get_avatar_url(),
"https://cloudfront.net/1/large.jpg",
)
self.assertIsNone(provider_account.get_profile_url())
def get_login_response_json(self, with_refresh_token=True):
rt = ""
if with_refresh_token:
rt = ',"refresh_token": "testrf"'
return (
"""{
"uid":"weibo",
"access_token":"testac",
"livemode": false,
"token_type": "bearer",
"strava_publishable_key": "pk_test_someteskey",
"strava_user_id": "acct_sometestid",
"scope": "read_write"
%s }"""
% rt
)

View File

@@ -0,0 +1,6 @@
from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns
from .provider import StravaProvider
urlpatterns = default_urlpatterns(StravaProvider)

View File

@@ -0,0 +1,26 @@
import requests
from allauth.socialaccount.providers.oauth2.views import (
OAuth2Adapter,
OAuth2CallbackView,
OAuth2LoginView,
)
from .provider import StravaProvider
class StravaOauth2Adapter(OAuth2Adapter):
provider_id = StravaProvider.id
access_token_url = "https://www.strava.com/oauth/token"
authorize_url = "https://www.strava.com/oauth/authorize"
profile_url = "https://www.strava.com/api/v3/athlete"
def complete_login(self, request, app, token, **kwargs):
headers = {"Authorization": "Bearer {0}".format(token.token)}
resp = requests.get(self.profile_url, headers=headers)
extra_data = resp.json()
return self.get_provider().sociallogin_from_response(request, extra_data)
oauth2_login = OAuth2LoginView.adapter_view(StravaOauth2Adapter)
oauth2_callback = OAuth2CallbackView.adapter_view(StravaOauth2Adapter)