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,36 @@
from allauth.socialaccount.providers.base import ProviderAccount
from allauth.socialaccount.providers.oauth2.provider import OAuth2Provider
class LineAccount(ProviderAccount):
def get_avatar_url(self):
return self.account.extra_data.get("pictureUrl") or self.account.extra_data.get(
"picture"
)
def to_str(self):
return self.account.extra_data.get("displayName", self.account.uid)
class LineProvider(OAuth2Provider):
id = "line"
name = "Line"
account_class = LineAccount
def get_default_scope(self):
return []
def extract_uid(self, data):
return str(data.get("userId") or data.get("sub"))
def extract_common_fields(self, data):
return dict(
email=data.get("email"),
username=data.get("email") or self.extract_uid(data),
first_name=data.get("first_name"),
last_name=data.get("last_name"),
name=data.get("name"),
)
provider_classes = [LineProvider]

View File

@@ -0,0 +1,20 @@
from allauth.socialaccount.tests import OAuth2TestsMixin
from allauth.tests import MockedResponse, TestCase
from .provider import LineProvider
class LineTests(OAuth2TestsMixin, TestCase):
provider_id = LineProvider.id
def get_mocked_response(self):
return MockedResponse(
200,
"""
{
"userId": "u7d47d26a6bab09b95695ff02d1a36e38",
"displayName": "\uc774\uc0c1\ud601",
"pictureUrl":
"http://dl.profile.line-cdn.net/0m055ab14d725138288331268c45ac5286a35482fb794a"
}""",
)

View File

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

View File

@@ -0,0 +1,54 @@
import requests
from datetime import timedelta
from django.utils import timezone
from allauth.socialaccount import app_settings
from allauth.socialaccount.models import SocialToken
from allauth.socialaccount.providers.oauth2.views import (
OAuth2Adapter,
OAuth2CallbackView,
OAuth2LoginView,
)
from .provider import LineProvider
class LineOAuth2Adapter(OAuth2Adapter):
provider_id = LineProvider.id
access_token_url = "https://api.line.me/oauth2/v2.1/token"
authorize_url = "https://access.line.me/oauth2/v2.1/authorize"
profile_url = "https://api.line.me/v2/profile" # https://developers.line.biz/en/reference/line-login/#get-user-profile
id_token_url = "https://api.line.me/oauth2/v2.1/verify" # https://developers.line.biz/en/reference/line-login/#verify-id-token
def parse_token(self, data):
"""
data: access_token data from line
"""
settings = app_settings.PROVIDERS.get(self.provider_id, {})
if "email" in settings.get("SCOPE", ""):
token = SocialToken(token=data["id_token"])
else:
token = SocialToken(token=data["access_token"])
token.token_secret = data.get("refresh_token", "")
expires_in = data.get(self.expires_in_key, None)
if expires_in:
token.expires_at = timezone.now() + timedelta(seconds=int(expires_in))
return token
def complete_login(self, request, app, token, **kwargs):
settings = app_settings.PROVIDERS.get(self.provider_id, {})
if "email" in settings.get("SCOPE", ""):
payload = {"client_id": app.client_id, "id_token": token.token}
resp = requests.post(self.id_token_url, payload)
else:
headers = {"Authorization": "Bearer {0}".format(token.token)}
resp = requests.get(self.profile_url, headers=headers)
resp.raise_for_status()
extra_data = resp.json()
return self.get_provider().sociallogin_from_response(request, extra_data)
oauth2_login = OAuth2LoginView.adapter_view(LineOAuth2Adapter)
oauth2_callback = OAuth2CallbackView.adapter_view(LineOAuth2Adapter)