From 635adf1360c97aa4a6c60c6164af83119b133df5 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 3 Mar 2021 18:13:33 +0100 Subject: [PATCH 01/12] Use cas server to use authentication in other services Signed-off-by: Yohann D'ANELLO --- apps/member/auth.py | 15 +++++++++++++++ note_kfet/admin.py | 6 ++++++ note_kfet/urls.py | 5 +++++ requirements.txt | 1 + 4 files changed, 27 insertions(+) create mode 100644 apps/member/auth.py diff --git a/apps/member/auth.py b/apps/member/auth.py new file mode 100644 index 00000000..0f9e42e8 --- /dev/null +++ b/apps/member/auth.py @@ -0,0 +1,15 @@ +from cas_server.auth import DjangoAuthUser # pragma: no cover + +from note.models import Alias + + +class CustomAuthUser(DjangoAuthUser): # pragma: no cover + """ + Override Django Auth User model to define a custom Matrix username. + """ + + def attributs(self): + d = super().attributs() + if self.user: + d["normalized_name"] = Alias.normalize(self.user.username) + return d diff --git a/note_kfet/admin.py b/note_kfet/admin.py index fa192b57..06543102 100644 --- a/note_kfet/admin.py +++ b/note_kfet/admin.py @@ -52,3 +52,9 @@ if "rest_framework" in settings.INSTALLED_APPS: from rest_framework.authtoken.admin import * from rest_framework.authtoken.models import * admin_site.register(Token, TokenAdmin) + +if "cas_server" in settings.INSTALLED_APPS: + from cas_server.admin import * + from cas_server.models import * + admin_site.register(ServicePattern, ServicePatternAdmin) + admin_site.register(FederatedIendityProvider, FederatedIendityProviderAdmin) diff --git a/note_kfet/urls.py b/note_kfet/urls.py index d4341bc6..ab19d763 100644 --- a/note_kfet/urls.py +++ b/note_kfet/urls.py @@ -45,6 +45,11 @@ if "oauth2_provider" in settings.INSTALLED_APPS: path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')) ) +if "cas_server" in settings.INSTALLED_APPS: + urlpatterns.append( + path('cas/', include('cas_server.urls', namespace='cas_server')) + ) + if "debug_toolbar" in settings.INSTALLED_APPS: import debug_toolbar urlpatterns = [ diff --git a/requirements.txt b/requirements.txt index d889dd54..0071bc83 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ beautifulsoup4~=4.7.1 Django~=2.2.15 django-bootstrap-datepicker-plus~=3.0.5 +django-cas-server~=1.2.0 django-colorfield~=0.3.2 django-crispy-forms~=1.7.2 django-extensions~=2.1.4 From e95a8b6e18523b42c2e4408049f8cf71c05b5acf Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 3 Mar 2021 18:42:51 +0100 Subject: [PATCH 02/12] Add normalized name to services Signed-off-by: Yohann D'ANELLO --- note_kfet/settings/base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 982634c8..23bfe118 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -273,3 +273,6 @@ PIC_RATIO = 1 # Custom phone number format PHONENUMBER_DB_FORMAT = 'NATIONAL' PHONENUMBER_DEFAULT_REGION = 'FR' + +# We add custom information to CAS, in order to give a normalized name to other services +CAS_AUTH_CLASS = 'member.auth.CustomAuthUser' From b5ef937a03f01fb557bd7e7ba60f040ee5411722 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 09:39:57 +0100 Subject: [PATCH 03/12] Environment file path is absolute Signed-off-by: Yohann D'ANELLO --- note_kfet/settings/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/note_kfet/settings/__init__.py b/note_kfet/settings/__init__.py index 3d995367..3aa115f9 100644 --- a/note_kfet/settings/__init__.py +++ b/note_kfet/settings/__init__.py @@ -12,7 +12,7 @@ def read_env(): directory. """ try: - with open('.env') as f: + with open(os.path.join(BASE_DIR, '.env')) as f: content = f.read() except IOError: content = '' @@ -30,6 +30,7 @@ def read_env(): # Try to load environment variables from project .env +BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) read_env() # Load base settings From 56c5fa4057b1335d13e2e2779f962c65350fefc8 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 09:41:27 +0100 Subject: [PATCH 04/12] We don't need a session to have permissions Signed-off-by: Yohann D'ANELLO --- apps/permission/backends.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/permission/backends.py b/apps/permission/backends.py index cde6998d..4b044d80 100644 --- a/apps/permission/backends.py +++ b/apps/permission/backends.py @@ -134,8 +134,6 @@ class PermissionBackend(ModelBackend): return False sess = get_current_session() - if sess is not None and sess.session_key is None: - return False if user_obj.is_superuser and sess.get("permission_mask", -1) >= 42: return True From 76d1784aeabfa65f96f429593f0ea7ca0d3092c6 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 09:44:25 +0100 Subject: [PATCH 05/12] Add OAuth2 authentication for Django Rest Framework Signed-off-by: Yohann D'ANELLO --- note_kfet/settings/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 23bfe118..67948f09 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -239,6 +239,7 @@ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', + 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', ], 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 20, From b244e01231cfdaca51aaa809a9e98b23fce7b64e Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 10:41:43 +0100 Subject: [PATCH 06/12] Add simple view to give OAuth information Signed-off-by: Yohann D'ANELLO --- apps/api/urls.py | 2 ++ apps/api/views.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 apps/api/views.py diff --git a/apps/api/urls.py b/apps/api/urls.py index 7131c657..8b0e1a6e 100644 --- a/apps/api/urls.py +++ b/apps/api/urls.py @@ -5,6 +5,7 @@ from django.conf import settings from django.conf.urls import url, include from rest_framework import routers +from .views import UserInformationView from .viewsets import ContentTypeViewSet, UserViewSet # Routers provide an easy way of automatically determining the URL conf. @@ -47,5 +48,6 @@ app_name = 'api' # Additionally, we include login URLs for the browsable API. urlpatterns = [ url('^', include(router.urls)), + url('me', UserInformationView.as_view()), url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), ] diff --git a/apps/api/views.py b/apps/api/views.py new file mode 100644 index 00000000..c8ccd442 --- /dev/null +++ b/apps/api/views.py @@ -0,0 +1,17 @@ +# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +from django.contrib.auth.models import User +from rest_framework.generics import RetrieveAPIView + +from .serializers import UserSerializer + + +class UserInformationView(RetrieveAPIView): + serializer_class = UserSerializer + + def get_queryset(self): + return User.objects.filter(pk=self.request.user.pk) + + def get_object(self): + return self.request.user From 72806f0aceb08e61600226a63583e440f94619fe Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 10:57:35 +0100 Subject: [PATCH 07/12] Add profile and membership information to OAuth views Signed-off-by: Yohann D'ANELLO --- apps/api/serializers.py | 46 ++++++++++++++++++++++++++++++++++++++--- apps/api/views.py | 7 +++++-- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/apps/api/serializers.py b/apps/api/serializers.py index d59bdc43..c417ccc6 100644 --- a/apps/api/serializers.py +++ b/apps/api/serializers.py @@ -4,10 +4,14 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.auth.models import User -from rest_framework.serializers import ModelSerializer +from django.utils import timezone +from rest_framework import serializers + +from member.api.serializers import ProfileSerializer, MembershipSerializer +from note.models import Alias -class UserSerializer(ModelSerializer): +class UserSerializer(serializers.ModelSerializer): """ REST API Serializer for Users. The djangorestframework plugin will analyse the model `User` and parse all fields in the API. @@ -22,7 +26,7 @@ class UserSerializer(ModelSerializer): ) -class ContentTypeSerializer(ModelSerializer): +class ContentTypeSerializer(serializers.ModelSerializer): """ REST API Serializer for Users. The djangorestframework plugin will analyse the model `User` and parse all fields in the API. @@ -31,3 +35,39 @@ class ContentTypeSerializer(ModelSerializer): class Meta: model = ContentType fields = '__all__' + + +class OAuthSerializer(serializers.ModelSerializer): + """ + Informations that are transmitted by OAuth. + For now, this includes user, profile and valid memberships. + This should be better managed later. + """ + normalized_name = serializers.SerializerMethodField() + + profile = ProfileSerializer() + + memberships = serializers.SerializerMethodField() + + def get_normalized_name(self, obj): + return Alias.normalize(obj.username) + + def get_memberships(self, obj): + return serializers.ListSerializer(child=MembershipSerializer()).to_representation( + obj.memberships.filter(date_start__lte=timezone.now(), date_end__gte=timezone.now())) + + class Meta: + model = User + fields = ( + 'id', + 'username', + 'normalized_name', + 'first_name', + 'last_name', + 'email', + 'is_superuser', + 'is_active', + 'is_staff', + 'profile', + 'memberships', + ) diff --git a/apps/api/views.py b/apps/api/views.py index c8ccd442..9718336d 100644 --- a/apps/api/views.py +++ b/apps/api/views.py @@ -4,11 +4,14 @@ from django.contrib.auth.models import User from rest_framework.generics import RetrieveAPIView -from .serializers import UserSerializer +from .serializers import OAuthSerializer class UserInformationView(RetrieveAPIView): - serializer_class = UserSerializer + """ + These fields are give to OAuth authenticators. + """ + serializer_class = OAuthSerializer def get_queryset(self): return User.objects.filter(pk=self.request.user.pk) From 40e1b42078572eb6d69bf5cf1fab13cca1af0e69 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 12:54:57 +0100 Subject: [PATCH 08/12] Fix API path Signed-off-by: Yohann D'ANELLO --- apps/api/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/api/urls.py b/apps/api/urls.py index 8b0e1a6e..3e61d587 100644 --- a/apps/api/urls.py +++ b/apps/api/urls.py @@ -48,6 +48,6 @@ app_name = 'api' # Additionally, we include login URLs for the browsable API. urlpatterns = [ url('^', include(router.urls)), - url('me', UserInformationView.as_view()), + url('^me/', UserInformationView.as_view()), url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), ] From 73d27e820bb0be3f0286c665f9af6b459f7c4a7d Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 12:55:19 +0100 Subject: [PATCH 09/12] Provide also note information (with balance and picture) Signed-off-by: Yohann D'ANELLO --- apps/api/serializers.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/api/serializers.py b/apps/api/serializers.py index c417ccc6..9417f25f 100644 --- a/apps/api/serializers.py +++ b/apps/api/serializers.py @@ -8,6 +8,7 @@ from django.utils import timezone from rest_framework import serializers from member.api.serializers import ProfileSerializer, MembershipSerializer +from note.api.serializers import NoteSerializer from note.models import Alias @@ -47,6 +48,8 @@ class OAuthSerializer(serializers.ModelSerializer): profile = ProfileSerializer() + note = NoteSerializer() + memberships = serializers.SerializerMethodField() def get_normalized_name(self, obj): @@ -69,5 +72,6 @@ class OAuthSerializer(serializers.ModelSerializer): 'is_active', 'is_staff', 'profile', + 'note', 'memberships', ) From c825dee95a30dfaa64066601843c77b2716adc6d Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 15:42:36 +0100 Subject: [PATCH 10/12] CAS documentation Signed-off-by: Yohann D'ANELLO --- docs/external_services/cas.rst | 80 +++++++++++++++++++++++++++++++ docs/external_services/index.rst | 28 +++++++++++ docs/external_services/oauth2.rst | 4 ++ docs/index.rst | 1 + 4 files changed, 113 insertions(+) create mode 100644 docs/external_services/cas.rst create mode 100644 docs/external_services/index.rst create mode 100644 docs/external_services/oauth2.rst diff --git a/docs/external_services/cas.rst b/docs/external_services/cas.rst new file mode 100644 index 00000000..efaf6ae8 --- /dev/null +++ b/docs/external_services/cas.rst @@ -0,0 +1,80 @@ +Service d'Authentification Centralisé (CAS) +=========================================== + +Un `CAS `_ est +déployé sur la Note Kfet. Il est accessible à l'adresse ``_. +Il a pour but uniquement d'authentifier les utilisateurs via la note et ne communique +que peu d'informations. + +Configuration +------------- + +Le serveur CAS utilisé est implémenté grâce au paquet ``django-cas-server``. Il peut être +installé soit par PIP soit sur une machine Debian via +``apt install python3-django-cas-server``. + +On ajoute ensuite ``cas_server`` aux applications Django installées. On n'oublie pas ni +d'appliquer les migrations (``./manage.py migrate``) ni de collecter les fichiers statiques +(``./manage.py collectstatic``). + +On enregistre les routes dans ``note_kfet/urls.py`` : + +.. code:: python + + urlpatterns.append( + path('cas/', include('cas_server.urls', namespace='cas_server')) + ) + +Le CAS est désormais déjà prêt à être utilisé. Toutefois, puisque l'on utilise un site +Django-admin personnalisé, on n'oublie pas d'enregistrer les pages d'administration : + +.. code:: python + + if "cas_server" in settings.INSTALLED_APPS: + from cas_server.admin import * + from cas_server.models import * + admin_site.register(ServicePattern, ServicePatternAdmin) + admin_site.register(FederatedIendityProvider, FederatedIendityProviderAdmin) + +Enfin, on souhaite pouvoir fournir au besoin le pseudo normalisé. Pour cela, on crée une +classe dans ``member.auth`` : + +.. code:: python + + class CustomAuthUser(DjangoAuthUser): + def attributs(self): + d = super().attributs() + if self.user: + d["normalized_name"] = Alias.normalize(self.user.username) + return d + + +Puis on source ce fichier dans les paramètres : + +.. code:: python + + CAS_AUTH_CLASS = 'member.auth.CustomAuthUser' + +Utilisation +----------- +Le service est accessible sur ``_. C'est ce lien qu'il faut +donner à votre application. + +L'application doit néanmoins être autorisée à accéder au CAS. Pour cela, rendez-vous +dans Django-admin (``_), dans +``Service Central d'Authentification/Motifs de services``, ajoutez une nouvelle entrée. +Choisissez votre position favorite puis le nom de l'application. + +Les champs importants sont les deux suivants : + +* **Motif :** il s'agit d'une expression régulière qui doit reconnaitre le site voulu. + Par exemple, pour autoriser Belenios (``_), on rentrera + le motif ``^https?://belenios\.crans\.org/.*$``. +* **Champ d'utilisateur :** C'est le pseudo que renverra le CAS. Par défaut, il s'agira + du nom de note principal, mais il arrive parfois que certains sites supportent mal + d'avoir des caractères UTF-8 dans le pseudo. C'est par exemple le cas de Belenios. + On rentrera alors ``normalized_name`` dans ce champ, qui correspond à la version + normalisée (sans accent ni espace ni aucun caractère non-ASCII) du pseudo, et qui + suffit à identifier une personne. + +On peut également utiliser le ``Single log out`` si besoin. diff --git a/docs/external_services/index.rst b/docs/external_services/index.rst new file mode 100644 index 00000000..ab1539aa --- /dev/null +++ b/docs/external_services/index.rst @@ -0,0 +1,28 @@ +Applications externes +===================== + +.. toctree:: + :maxdepth: 2 + :caption: Applications externes + + cas + oauth2 + +.. warning:: + L'utilisation de la note par des services externes est actuellement en beta. Il est + fort à parier que cette utilisation sera revue et améliorée à l'avenir. + +Puisque la Note Kfet recense tous les comptes des adhérents BDE, les clubs ont alors +la possibilité de développer leurs propres applications et de les interfacer avec la +note. De cette façon, chaque application peut authentifier ses utilisateurs via la note, +et récupérer leurs adhésion, leur nom de note afin d'éventuellement faire des transferts +via l'API. + +Deux protocoles d'authentification sont implémentées : + + * `CAS `_ + * `OAuth2 `_ + +À ce jour, il n'y a pas encore d'exemple d'utilisation d'application qui utilise ce +mécanisme, mais on peut imaginer par exemple que la Mediatek ou l'AMAP implémentent +ces protocoles pour récupérer leurs adhérents. diff --git a/docs/external_services/oauth2.rst b/docs/external_services/oauth2.rst new file mode 100644 index 00000000..5df4b70b --- /dev/null +++ b/docs/external_services/oauth2.rst @@ -0,0 +1,4 @@ +OAuth2 +====== + +TODO diff --git a/docs/index.rst b/docs/index.rst index 766053aa..ac17e171 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,3 +12,4 @@ Des informations complémentaires sont également disponibles sur le `Wiki Crans :caption: Développement de la NK20 apps/index + external_services/index From d8c9618772f33ecca020f76fa8d352a41dad421c Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 17:04:16 +0100 Subject: [PATCH 11/12] OAuth2 documentation Signed-off-by: Yohann D'ANELLO --- docs/external_services/cas.rst | 4 +- docs/external_services/oauth2.rst | 131 +++++++++++++++++++++++++++++- 2 files changed, 132 insertions(+), 3 deletions(-) diff --git a/docs/external_services/cas.rst b/docs/external_services/cas.rst index efaf6ae8..36dedf3e 100644 --- a/docs/external_services/cas.rst +++ b/docs/external_services/cas.rst @@ -14,8 +14,8 @@ installé soit par PIP soit sur une machine Debian via ``apt install python3-django-cas-server``. On ajoute ensuite ``cas_server`` aux applications Django installées. On n'oublie pas ni -d'appliquer les migrations (``./manage.py migrate``) ni de collecter les fichiers statiques -(``./manage.py collectstatic``). +d'appliquer les migrations (``./manage.py migrate``) ni de collecter les fichiers +statiques (``./manage.py collectstatic``). On enregistre les routes dans ``note_kfet/urls.py`` : diff --git a/docs/external_services/oauth2.rst b/docs/external_services/oauth2.rst index 5df4b70b..3f1eee2c 100644 --- a/docs/external_services/oauth2.rst +++ b/docs/external_services/oauth2.rst @@ -1,4 +1,133 @@ OAuth2 ====== -TODO +L'authentification `OAuth2 `_ est supportée par la +Note Kfet. Elle offre l'avantage non seulement d'identifier les utilisateurs, mais aussi +de transmettre des informations à un service tiers tels que des informations personnelles, +le solde de la note ou encore les adhésions de l'utilisateur, en l'avertissant sur +quelles données sont effectivement collectées. + +.. danger:: + L'implémentation actuelle ne permet pas de choisir quels droits on offre. Se connecter + par OAuth2 offre actuellement exactement les mêmes permissions que l'on n'aurait + normalement, avec le masque le plus haut, y compris en écriture. + + Faites alors très attention lorsque vous vous connectez à un service tiers via OAuth2, + et contrôlez bien exactement ce que l'application fait de vos données, à savoir si + elle ignore bien tout ce dont elle n'a pas besoin. + + À l'avenir, la fenêtre d'authentification pourra vous indiquer clairement quels + paramètres sont collectés. + +Configuration du serveur +------------------------ + +On utilise ``django-oauth-toolkit``, qui peut être installé grâce à PIP ou bien via APT, +via le paquet ``python3-django-oauth-toolkit``. + +On commence par ajouter ``oauth2_provider`` aux applications Django installées. On +n'oublie pas ni d'appliquer les migrations (``./manage.py migrate``) ni de collecter +les fichiers statiques (``./manage.py collectstatic``). + +On souhaite que l'API gérée par ``django-rest-framework`` puisse être accessible via +l'authentification OAuth2. On adapte alors la configuration pour permettre cela : + +.. code:: python + + REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework.authentication.SessionAuthentication', + 'rest_framework.authentication.TokenAuthentication', + 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', + ... + ], + ... + } + +On ajoute les routes dans ``urls.py`` : + +.. code:: python + + urlpatterns.append( + path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')) + ) + +L'OAuth2 est désormais prêt à être utilisé. + + +Configuration client +-------------------- + +Contrairement au `CAS `_, n'importe qui peut en théorie créer une application OAuth2. +En théorie, car pour l'instant les permissions ne leur permettent pas. + +Pour créer une application, il faut se rendre à la page +`/o/applications/ `_. Dans ``client type``, +rentrez ``public`` (ou ``confidential`` selon vos choix), et vous rentrerez +généralement ``authorization-code`` dans ``Authorization Grant Type``. +Le champ ``Redirect Uris`` contient une liste d'adresses URL autorisées pour des +redirections post-connexion. + +Il vous suffit de donner à votre application : + +* L'identifiant client (client-ID) +* La clé secrète +* Les scopes : sous-ensemble de ``[read, write]`` (ignoré pour l'instant, cf premier paragraphe) +* L'URL d'autorisation : ``_ +* L'URL d'obtention de jeton : ``_ +* L'URL de récupération des informations de l'utilisateur : ``_ + +N'hésitez pas à consulter la page ``_ pour s'imprégner +du format renvoyé. + +Avec Django-allauth +################### + +Si vous utilisez Django-allauth pour votre propre application, vous pouvez utiliser +le module pré-configuré disponible ici : +``_. Pour l'installer, vous +pouvez simplement faire : + +.. code:: bash + + $ pip3 install git+https://gitlab.crans.org/bde/allauth-note-kfet.git + +L'installation du module se fera automatiquement. + +Il vous suffit ensuite d'inclure l'application ``allauth_note_kfet`` à vos applications +installées (sur votre propre client), puis de bien ajouter l'application sociale : + +.. code:: python + + SOCIALACCOUNT_PROVIDERS = { + 'notekfet': { + # 'DOMAIN': 'note.crans.org', + }, + ... + } + +Le paramètre ``DOMAIN`` permet de changer d'instance de Note Kfet. Par défaut, il +se connectera à ``note.crans.org`` si vous ne renseignez rien. + +En créant l'application sur la note, vous pouvez renseigner +``https://monsite.example.com/accounts/notekfet/login/callback/`` en URL de redirection, +à adapter selon votre configuration. + +Vous devrez ensuite enregistrer l'application sociale dans la base de données. +Vous pouvez passer par Django-admin, mais cela peut nécessiter d'avoir déjà un compte, +alors autant le faire via un shell python : + +.. code:: python + + from allauth.socialaccount.models import SocialApp + SocialApp.objects.create( + name="Note Kfet", + provider="notekfet", + client_id="VOTRECLIENTID", + secret="VOTRESECRET", + key="", + ) + +Si vous avez bien configuré ``django-allauth``, vous êtes désormais prêts par à vous +connecter via la note :) Par défaut, nom, prénom, pseudo et adresse e-mail sont +récupérés. Les autres données sont stockées mais inutilisées. From b2437ef9b5cb89b46e97d3bf718038ed7fdcd17a Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Tue, 9 Mar 2021 17:18:43 +0100 Subject: [PATCH 12/12] Remove additional blank lines Signed-off-by: Yohann D'ANELLO --- apps/api/serializers.py | 1 - apps/member/auth.py | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/api/serializers.py b/apps/api/serializers.py index 9417f25f..c5e6f2b3 100644 --- a/apps/api/serializers.py +++ b/apps/api/serializers.py @@ -6,7 +6,6 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.auth.models import User from django.utils import timezone from rest_framework import serializers - from member.api.serializers import ProfileSerializer, MembershipSerializer from note.api.serializers import NoteSerializer from note.models import Alias diff --git a/apps/member/auth.py b/apps/member/auth.py index 0f9e42e8..888adea1 100644 --- a/apps/member/auth.py +++ b/apps/member/auth.py @@ -1,5 +1,7 @@ -from cas_server.auth import DjangoAuthUser # pragma: no cover +# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later +from cas_server.auth import DjangoAuthUser # pragma: no cover from note.models import Alias