django-allauth-cas/allauth_cas/providers.py
2024-01-25 14:33:24 +00:00

205 lines
6.1 KiB
Python

from urllib.parse import parse_qsl
from allauth.socialaccount.providers.base import Provider
from django.contrib import messages
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.http import urlencode
from django.utils.safestring import mark_safe
class CASProvider(Provider):
def get_auth_params(self, request, action):
settings = self.get_settings()
ret = dict(settings.get("AUTH_PARAMS", {}))
dynamic_auth_params = request.GET.get("auth_params")
if dynamic_auth_params:
ret.update(dict(parse_qsl(dynamic_auth_params)))
return ret
##
# Data extraction from CAS responses.
##
def extract_uid(self, data):
"""Extract the user uid.
Notes:
Each pair ``(provider_id, uid)`` is unique and related to a single
user.
Args:
data (uid (str), extra (dict)): CAS response. Example:
``('alice', {'name': 'Alice'})``
Returns:
str: Default to ``data[0]``, user identifier for the CAS server.
"""
uid, _ = data
return uid
def extract_common_fields(self, data):
"""Extract the data to pass to `SOCIALACCOUNT_ADAPTER.populate_user()`.
Args:
data (uid (str), extra (dict)): CAS response. Example:
``('alice', {'name': 'Alice'})``
Returns:
dict: Default::
{
'username': extra.get('username', uid),
'email': extra.get('email'),
'first_name': extra.get('first_name'),
'last_name': extra.get('last_name'),
'name': extra.get('name'),
}
"""
uid, extra = data
return {
"username": extra.get("username", uid),
"email": extra.get("email"),
"first_name": extra.get("first_name"),
"last_name": extra.get("last_name"),
"name": extra.get("name"),
}
def extract_email_addresses(self, data):
"""Extract the email addresses.
Args:
data (uid (str), extra (dict)): CAS response. Example:
``('alice', {'name': 'Alice'})``
Returns:
`list` of `EmailAddress`: By default, ``[]``.
Example::
[
EmailAddress(
email='user@domain.net',
verified=True, primary=True,
),
EmailAddress(
email='alias@domain.net',
verified=True, primary=False,
),
]
"""
return super().extract_email_addresses(data)
def extract_extra_data(self, data):
"""Extract the data to save to `SocialAccount.extra_data`.
Args:
data (uid (str), extra (dict)): CAS response. Example:
``('alice', {'name': 'Alice'})``
Returns:
dict: By default, ``data``.
"""
uid, extra = data
return dict(extra, uid=uid)
##
# Message to suggest users to logout of the CAS server.
##
def add_message_suggest_caslogout(
self,
request,
next_page=None,
level=None,
):
"""Add a message with a link for the user to logout of the CAS server.
It uses the template ``socialaccount/messages/suggest_caslogout.html``,
with the ``provider`` and the ``logout_url`` as context.
Args:
request: The request to which the message is added.
next_page (optional): Added to the logout link for the CAS server
to redirect the user to this url.
Default: ``request.get_full_path()``
level: The message level. Default: ``messages.INFO``
"""
if next_page is None:
next_page = request.get_full_path()
if level is None:
level = messages.INFO
logout_url = self.get_logout_url(request, next=next_page)
# DefaultAccountAdapter.add_message is unusable because it always
# escape the message content.
template = "socialaccount/messages/suggest_caslogout.html"
context = {
"provider": self,
"logout_url": logout_url,
}
messages.add_message(
request,
level,
mark_safe(render_to_string(template, context).strip()),
fail_silently=True,
)
def message_suggest_caslogout_on_logout(self, request):
"""Indicates whether the logout message should be sent on user logout.
By default, it returns
``settings.SOCIALACCOUNT_PROVIDERS[self.id]['MESSAGE_SUGGEST_CASLOGOUT_ON_LOGOUT']``
or ``False``.
Notes:
The ``request`` argument is the one trigerring the emission of the
signal ``user_logged_out``.
"""
return self.get_settings().get("MESSAGE_SUGGEST_CASLOGOUT_ON_LOGOUT", False)
def message_suggest_caslogout_on_logout_level(self, request):
"""Level of the logout message issued on user logout.
By default, it returns
``settings.SOCIALACCOUNT_PROVIDERS[self.id]['MESSAGE_SUGGEST_CASLOGOUT_ON_LOGOUT_LEVEL']``
or ``messages.INFO``.
Notes:
The ``request`` argument is the one trigerring the emission of the
signal ``user_logged_out``.
"""
return self.get_settings().get(
"MESSAGE_SUGGEST_CASLOGOUT_ON_LOGOUT_LEVEL", messages.INFO
)
##
# Shortcuts functions.
##
def get_login_url(self, request, **kwargs):
url = reverse(self.id + "_login")
if kwargs:
url += "?" + urlencode(kwargs)
return url
def get_callback_url(self, request, **kwargs):
url = reverse(self.id + "_callback")
if kwargs:
url += "?" + urlencode(kwargs)
return url
def get_logout_url(self, request, **kwargs):
url = reverse(self.id + "_logout")
if kwargs:
url += "?" + urlencode(kwargs)
return url