Files
GNX-mailEnterprise/venv/lib/python3.12/site-packages/allauth/socialaccount/providers/oauth/views.py
Iliyan Angelov c67067a2a4 Mail
2025-09-14 23:24:25 +03:00

131 lines
4.3 KiB
Python

from __future__ import absolute_import
import logging
from django.urls import reverse
from allauth.socialaccount.adapter import get_adapter
from allauth.socialaccount.helpers import (
complete_social_login,
render_authentication_error,
)
from allauth.socialaccount.models import SocialLogin, SocialToken
from allauth.socialaccount.providers.base.constants import (
AuthAction,
AuthError,
)
from allauth.socialaccount.providers.base.mixins import OAuthLoginMixin
from allauth.socialaccount.providers.oauth.client import (
OAuthClient,
OAuthError,
)
logger = logging.getLogger(__name__)
class OAuthAdapter(object):
def __init__(self, request):
self.request = request
def complete_login(self, request, app):
"""
Returns a SocialLogin instance
"""
raise NotImplementedError
def get_provider(self):
adapter = get_adapter(self.request)
app = adapter.get_app(self.request, provider=self.provider_id)
return app.get_provider(self.request)
class OAuthView(object):
@classmethod
def adapter_view(cls, adapter):
def view(request, *args, **kwargs):
self = cls()
self.request = request
self.adapter = adapter(request)
return self.dispatch(request, *args, **kwargs)
return view
def _get_client(self, request, callback_url):
provider = self.adapter.get_provider()
app = provider.app
scope = " ".join(provider.get_scope(request))
parameters = {}
if scope:
parameters["scope"] = scope
client = OAuthClient(
request,
app.client_id,
app.secret,
self.adapter.request_token_url,
self.adapter.access_token_url,
callback_url,
parameters=parameters,
provider=provider,
)
return client
class OAuthLoginView(OAuthLoginMixin, OAuthView):
def login(self, request, *args, **kwargs):
callback_url = reverse(self.adapter.provider_id + "_callback")
SocialLogin.stash_state(request)
action = request.GET.get("action", AuthAction.AUTHENTICATE)
provider = self.adapter.get_provider()
auth_url = provider.get_auth_url(request, action) or self.adapter.authorize_url
auth_params = provider.get_auth_params(request, action)
client = self._get_client(request, callback_url)
try:
return client.get_redirect(auth_url, auth_params)
except OAuthError as e:
logger.error("OAuth authentication error", exc_info=True)
return render_authentication_error(
request, self.adapter.provider_id, exception=e
)
class OAuthCallbackView(OAuthView):
def dispatch(self, request):
"""
View to handle final steps of OAuth based authentication where the user
gets redirected back to from the service provider
"""
login_done_url = reverse(self.adapter.provider_id + "_callback")
client = self._get_client(request, login_done_url)
if not client.is_valid():
if "denied" in request.GET:
error = AuthError.CANCELLED
else:
error = AuthError.UNKNOWN
extra_context = dict(oauth_client=client)
return render_authentication_error(
request,
self.adapter.provider_id,
error=error,
extra_context=extra_context,
)
app = self.adapter.get_provider().app
try:
access_token = client.get_access_token()
token = SocialToken(
app=app,
token=access_token["oauth_token"],
# .get() -- e.g. Evernote does not feature a secret
token_secret=access_token.get("oauth_token_secret", ""),
)
login = self.adapter.complete_login(
request, app, token, response=access_token
)
login.token = token
login.state = SocialLogin.unstash_state(request)
return complete_social_login(request, login)
except OAuthError as e:
return render_authentication_error(
request, self.adapter.provider_id, exception=e
)