feat: init

This commit is contained in:
Maurice Debray 2025-12-18 15:48:17 +01:00
commit a6e0b0a803
No known key found for this signature in database
29 changed files with 911 additions and 0 deletions

8
.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
.direnv
.pre-commit-config.yaml
db.sqlite3
__pycache__/
.static/*
!.static/.gitkeep

0
.static/.gitkeep Normal file
View file

99
LICENSE Normal file
View file

@ -0,0 +1,99 @@
LICENCE PUBLIQUE DE L'UNION EUROPÉENNE v. 1.2
EUPL © Union européenne 2007, 2016
La présente licence publique de l'Union européenne («EUPL») s'applique à toute œuvre (telle que définie ci-dessous) fournie aux conditions prévues par la présente licence.
Toute utilisation de l'œuvre autre que ce qu'autorise la présente licence est interdite (dans la mesure où pareille utilisation est couverte par un droit du titulaire des droits d'auteur sur l'œuvre).
L'œuvre est fournie aux conditions prévues par la présente licence quand le donneur de licence (tel que défini ci-dessous) a placé la mention suivante immédiatement après la déclaration relative au droit d'auteur sur l'œuvre:
Sous licence EUPL
ou a exprimé de toute autre manière sa volonté de fournir l'œuvre sous licence EUPL.
1.Définitions
Dans la présente licence, on entend par:
— «licence», la présente licence,
— «œuvre originale», l'œuvre ou le logiciel distribué ou communiqué par le donneur de licence en vertu de la présente licence, sous forme de code source ou de code objet, selon le cas,
— «œuvres dérivées», les œuvres ou logiciels qui pourraient être créés par le licencié sur la base de l'œuvre originale ou des modifications qui y auraient été appliquées. La présente licence ne définit pas le degré de modification ou de dépendance requis par rapport à l'œuvre originale pour qu'une œuvre soit qualifiée d'œuvre dérivée; cette question est réglée par la loi applicable en matière de droit d'auteur dans le pays visé à l'article 15,
— «œuvre», l'œuvre originale ou ses œuvres dérivées,
— «code source», la forme de l'œuvre, lisible par l'homme, la plus appropriée pour que des personnes puissent l'examiner et la modifier,
— «code objet», l'œuvre codée, généralement après compilation, destinée à être exécutée en tant que programme par un ordinateur, — «donneur de licence», la personne physique ou morale qui distribue ou communique l'œuvre sous licence,
— «contributeur», toute personne physique ou morale qui modifie l'œuvre sous licence, ou contribue de toute autre manière à en faire une œuvre dérivée,
— «licencié» ou «vous», toute personne physique ou morale qui utilise l'œuvre conformément à la licence,
— «distribution» ou «communication», tout acte de vente, don, prêt, location, distribution, communication, transmission ou mise à disposition, en ligne ou hors ligne, de copies de l'œuvre, et tout acte donnant accès à ses fonctions essentielles à toute autre personne physique ou morale.
2.Portée des droits accordés par la licence
Par la présente, le donneur de licence vous concède, pour la durée de la protection de son droit d'auteur sur l'œuvre originale, une licence mondiale, libre de redevances, non exclusive et pouvant faire l'objet de sous-licences, en vertu de laquelle vous pouvez:
— utiliser l'œuvre en toute circonstance et pour tout usage,
— reproduire l'œuvre,
— modifier l'œuvre et créer des œuvres dérivées sur la base de l'œuvre,
— communiquer l'œuvre au public, ce qui inclut le droit de mettre à disposition du public ou de lui présenter l'œuvre ou des copies de l'œuvre et d'en effectuer des représentations publiques, le cas échéant,
— distribuer l'œuvre ou des copies de celle-ci,
— prêter et louer l'œuvre ou des copies de celles-ci,
— accorder en sous-licence des droits sur l'œuvre ou sur des copies de celle-ci.
Ces droits peuvent être exercés sur tout support et format, connu ou encore à inventer, dans la mesure où le droit applicable le permet. Dans les pays où des droits moraux s'appliquent, le donneur de licence renonce à son droit d'exercer son droit moral dans la mesure permise par la loi afin que la licence sur les droits patrimoniaux susmentionnés produise ses effets. Le donneur de licence vous concède un droit d'usage libre de redevances et non exclusif sur tout brevet qu'il détient, dans la mesure nécessaire à l'exercice des droits qui vous sont concédés sur l'œuvre sous licence.
3.Communication du code source
Le donneur de licence fournit l'œuvre sous forme de code source ou de code objet. Si l'œuvre est fournie sous forme de code objet, le donneur de licence accompagne chacune des copies de l'œuvre qu'il distribue d'une copie lisible par machine du code source de l'œuvre ou indique, dans un avis qui suit la déclaration relative au droit d'auteur jointe à l'œuvre, l'endroit où le code source est aisément et gratuitement accessible aussi longtemps que le donneur de licence continue à distribuer ou communiquer l'œuvre.
4.Limitations du droit d'auteur
Rien dans la présente licence n'a pour but de priver le licencié des avantages résultant de toute exception ou limitation aux droits exclusifs des titulaires de droits sur l'œuvre, de l'épuisement de ces droits ou de toute autre limitation qui s'y applique.
5.Obligations du licencié
La concession des droits susmentionnés est soumise à des restrictions et à des obligations pour le licencié. Ces obligations sont les suivantes:
Droit d'attribution: le licencié laisse intactes toutes les déclarations concernant le droit d'auteur, le brevet ou les marques et toutes les déclarations concernant la licence et l'exclusion de garantie. Le licencié assortit chaque copie de l'œuvre qu'il distribue ou communique d'une copie de ces déclarations et d'une copie de la licence. Le licencié veille à ce que toute œuvre dérivée soit assortie d'un avis bien visible indiquant que l'œuvre a été modifiée et mentionnant la date de la modification.
Clause copyleft: si le licencié distribue ou communique des copies d'œuvres originales ou d'œuvres dérivées, cette distribution ou cette communication est effectuée dans les conditions prévues par la présente licence ou une version ultérieure de cette licence, sauf si l'œuvre originale est expressément distribuée en vertu de la présente version de la licence uniquement, par exemple au moyen de la mention «EUPL v. 1.2 seulement». Le licencié (qui devient donneur de licence) ne peut pas, en ce qui concerne l'œuvre ou les œuvres dérivées, offrir ou imposer des conditions supplémentaires qui restreignent ou modifient les conditions de la licence.
Clause de compatibilité: si le licencié distribue ou communique des œuvres dérivées ou des copies de telles œuvres basées à la fois sur l'œuvre et sur une autre œuvre concédée sous une licence compatible, la distribution ou la communication peut être faite aux conditions de cette licence compatible. Aux fins de la présente clause, une «licence compatible» est l'une des licences énumérées dans l'appendice de la présente licence. Dans le cas où les obligations du licencié au titre de la licence compatible entrent en conflit avec les obligations du licencié au titre de la présente licence, les premières prévalent.
Fourniture du code source: lorsqu'il distribue ou communique des copies de l'œuvre, le licencié fournit une copie lisible par machine du code source ou indique l'endroit où ce code source restera aisément et gratuitement accessible aussi longtemps que le donneur de licence continuera à distribuer ou communiquer l'œuvre.
Protection des droits: la présente licence ne donne pas le droit d'utiliser les noms commerciaux, les marques commerciales, les marques de service ou les noms du donneur de licence, sauf dans la mesure nécessaire, conformément à une utilisation raisonnable et aux pratiques habituelles, pour décrire l'origine de l'œuvre et reproduire la déclaration concernant le droit d'auteur.
6.Chaîne d'auteurs
Le donneur de licence initial garantit que les droits d'auteur sur l'œuvre originale concédés par la présente licence lui appartiennent ou lui ont été donnés sous licence, et qu'il a le pouvoir et la capacité de concéder la licence. Tout contributeur garantit que les droits d'auteur sur les modifications qu'il apporte à l'œuvre lui appartiennent ou lui ont été donnés sous licence, et qu'il a le pouvoir et la capacité de concéder la licence. Chaque fois que vous acceptez la licence, le donneur de licence initial et les contributeurs successifs vous concèdent une licence sur leurs contributions à l'œuvre selon les conditions de la présente licence.
7.Exclusion de garantie
L'œuvre est un travail en cours, amélioré de manière continue par de nombreux contributeurs. Elle constitue un travail inachevé et peut dès lors contenir des défauts ou bogues inhérents à ce type de développement. Pour cette raison, l'œuvre est fournie sous licence telle quelle, sans aucune garantie d'aucune sorte la concernant, y compris, sans que cette liste soit exhaustive, eu égard à sa qualité marchande, son aptitude à un usage particulier, l'absence de défauts ou d'erreurs, l'exactitude ou la non-violation de droits de propriété intellectuelle autres que le droit d'auteur comme prévu à l'article 6 de la présente licence. Cette exclusion de garantie est une partie essentielle de la licence et une condition de la concession de droits sur l'œuvre.
8.Exclusion de responsabilité
Sauf dans les cas de faute intentionnelle ou de dommages directement causés à des personnes physiques, le donneur de licence n'est en aucun cas responsable des dommages, quelle qu'en soit la nature, directs ou indirects, matériels ou moraux, résultant de la licence ou de l'utilisation de l'œuvre, y compris, sans que cette liste soit exhaustive, des dommages causés par les atteintes à la réputation, les interruptions de travail, les défaillances ou le mauvais fonctionnement de matériel informatique, les pertes de données ou tout autre dommage économique, même si le donneur de licence a été informé de la possibilité de tels dommages. Cependant, le donneur de licence est responsable en vertu des dispositions législatives et réglementaires relatives à la responsabilité du fait des produits, dans la mesure où celles-ci sont applicables à l'œuvre.
9.Accords additionnels
Lorsque vous distribuez l'œuvre, vous pouvez choisir de conclure un accord additionnel définissant des obligations ou des services compatibles avec la présente licence. Cependant, si vous acceptez des obligations, vous ne pouvez agir qu'en votre nom et sous votre seule responsabilité, et non au nom du donneur de licence initial ou de tout autre contributeur, et seulement si vous acceptez d'indemniser, de défendre et de mettre hors de cause tous les contributeurs s'ils encourent une responsabilité quelconque ou si des réclamations sont formulées à leur encontre du fait que vous avez accepté des garanties ou des responsabilités additionnelles.
10.Acceptation de la licence
Vous pouvez exprimer votre accord sur le contenu de la présente licence en cliquant sur l'icône «J'accepte» placée au bas d'une fenêtre faisant apparaître le texte de la présente licence, ou par toute autre manifestation de consentement similaire, conformément à la loi applicable. Le fait de cliquer sur cette icône indique votre acceptation claire et irrévocable de la présente licence et de toutes ses conditions. De même, vous acceptez irrévocablement la présente licence et toutes ses conditions dès lors que vous exercez un des droits qui vous sont concédés par l'article 2 de la présente licence, tels que l'utilisation de l'œuvre, la création d'une œuvre dérivée ou la distribution ou la communication de l'œuvre ou de copies de l'œuvre.
11.Information du public
En cas de distribution ou de communication électronique de l'œuvre (par exemple en permettant son téléchargement à distance), le canal de distribution ou le support (par exemple un site web) doit au minimum fournir au public les informations requises par le droit applicable en ce qui concerne le donneur de licence et la licence ainsi que la manière dont le licencié peut accéder à celle-ci, la conclure, la stocker et la reproduire.
12.Fin de la licence
La licence et les droits qu'elle concède prennent automatiquement fin dès que le licencié viole l'une de ses conditions. Un tel événement ne met pas fin aux licences des personnes ayant reçu l'œuvre sous licence de la part du licencié, pour autant que ces personnes respectent pleinement la licence.
13.Divers
Sous réserve de l'article 9, la licence représente l'entièreté de l'accord entre les parties quant à l'œuvre. Le fait qu'une clause quelconque de la licence soit invalide ou inapplicable en vertu du droit applicable n'affecte pas la validité ou l'applicabilité de la licence dans son ensemble. Une telle clause sera interprétée ou modifiée dans la mesure nécessaire pour la rendre valide ou applicable. La Commission européenne peut publier d'autres versions linguistiques ou de nouvelles versions de la présente licence ou des versions actualisées de son appendice, dans la mesure de ce qui est nécessaire et raisonnable, sans réduire la portée des droits accordés par la licence. Les nouvelles versions de la licence seront publiées avec un numéro de version unique. Toutes les versions linguistiques de la présente licence, approuvées par la Commission européenne, ont la même valeur. Les parties peuvent se prévaloir de la version linguistique de leur choix.
14.Juridiction compétente
Sans préjudice d'accords spécifiques entre les parties,
— tout litige résultant de l'interprétation de la présente licence survenant entre des institutions, organes, bureaux ou agences de l'Union européenne en tant que donneurs de licence et un licencié relève de la juridiction de la Cour de justice de l'Union européenne, conformément à l'article 272 du traité sur le fonctionnement de l'Union européenne,
— tout litige survenant entre d'autres parties et résultant de l'interprétation de la présente licence relève de la compétence exclusive de la juridiction compétente du lieu où le donneur de licence réside ou exerce son activité principale.
15.Droit applicable
Sans préjudice d'accords spécifiques entre les parties,
— la présente licence est régie par le droit de l'État membre de l'Union européenne où le donneur de licence réside ou a son siège social ou statutaire,
— la présente licence est régie par le droit belge si le donneur de licence ne réside pas et n'a pas son siège social ou statutaire dans un État membre de l'Union européenne.
Appendice
Aux fins de l'article 5 de l'EUPL, les licences compatibles sont les suivantes:
— GNU General Public License (GPL) v. 2, v. 3
— GNU Affero General Public License (AGPL) v. 3
— Open Software License (OSL) v. 2.1, v. 3.0
— Eclipse Public License (EPL) v. 1.0
— CeCILL v. 2.0, v. 2.1
— Mozilla Public licence (MPL) v. 2
— GNU Lesser General Public licence (LGPL) v. 2.1, v. 3
— Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) pour les œuvres autres que logicielles
— Licence publique de l'Union européenne (EUPL) v. 1.1, v. 1.2
— Licence libre du Québec — Réciprocité (LiLiQ-R) ou Réciprocité forte (LiLiQ-R+)
La Commission européenne pourra actualiser le présent appendice afin d'y inclure des versions ultérieures des licences ci-dessus sans produire de nouvelle version de l'EUPL, dès lors que ces versions prévoient la concession des droits visés à l'article 2 de la présente licence et empêchent l'appropriation exclusive du code source couvert.
Tout autre changement ou ajout au présent appendice requiert la production d'une nouvelle version de l'EUPL.

0
app/__init__.py Normal file
View file

16
app/asgi.py Normal file
View file

@ -0,0 +1,16 @@
"""
ASGI config for casexporter project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
application = get_asgi_application()

175
app/settings.py Normal file
View file

@ -0,0 +1,175 @@
"""
Django settings for cas-exporter project.
Generated by 'django-admin startproject' using Django 4.2.12.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
import os
from pathlib import Path
from django.contrib import messages
from django.urls import reverse_lazy
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv("SECRET_KEY", "insecure")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ALLOWED_HOSTS = ["100.64.0.1", "localhost", "127.0.0.1"] + (
[s] if (s := os.getenv("ALLOWED_HOST")) else []
)
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"casexporter",
"allauth",
"allauth.account",
"allauth.socialaccount",
"allauth_cas",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"allauth.account.middleware.AccountMiddleware",
]
if DEBUG:
INSTALLED_APPS += [
"django_browser_reload",
]
MIDDLEWARE += [
"django_browser_reload.middleware.BrowserReloadMiddleware",
]
ROOT_URLCONF = "app.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "app.wsgi.application"
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = []
# Authentication backends
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
]
LOGIN_URL = reverse_lazy("account_login")
SOCIALACCOUNT_PROVIDERS = {
"ens_cas": {
"APP": {
"provider_id": "ens_cas",
"name": "CAS CRI",
}
}
}
LOGIN_REDIRECT_URL = reverse_lazy("home")
LOGOUT_REDIRECT_URL = reverse_lazy("home")
# AUTHENS_USE_OLDCAS = True
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = "fr-fr"
TIME_ZONE = "Europe/Paris"
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / ".static"
STATICFILES_DIRS = []
STATICFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
]
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# Messages tags
MESSAGE_TAGS = {
messages.DEBUG: "is-warning",
messages.INFO: "is-info",
messages.SUCCESS: "is-success",
messages.WARNING: "is-warning",
messages.ERROR: "is-danger",
}
# Email
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"

33
app/urls.py Normal file
View file

@ -0,0 +1,33 @@
"""
URL configuration for casexporter project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from debug_toolbar.toolbar import debug_toolbar_urls
from django.conf import settings
from django.contrib import admin
from django.urls import include, path
from casexporter.views import HomeView
urlpatterns = [
path("admin/", admin.site.urls),
path("accounts/", include("allauth.urls")),
path("", HomeView.as_view(), name="home"),
]
if settings.DEBUG:
urlpatterns += [
path("__reload__/", include("django_browser_reload.urls")),
] + debug_toolbar_urls()

16
app/wsgi.py Normal file
View file

@ -0,0 +1,16 @@
"""
WSGI config for casexporter project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
application = get_wsgi_application()

0
casexporter/__init__.py Normal file
View file

1
casexporter/admin.py Normal file
View file

@ -0,0 +1 @@
# Register your models here.

6
casexporter/apps.py Normal file
View file

@ -0,0 +1,6 @@
from django.apps import AppConfig
class CasexporterConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "casexporter"

View file

1
casexporter/models.py Normal file
View file

@ -0,0 +1 @@
# Create your models here.

11
casexporter/provider.py Normal file
View file

@ -0,0 +1,11 @@
from allauth.socialaccount.providers.base import ProviderAccount
from allauth_cas.providers import CASProvider
class ENSCASProvider(CASProvider):
id = "ens_cas" # Choose an identifier for your provider
name = "CAS CRI" # Verbose name of your provider
account_class = ProviderAccount
provider_classes = [ENSCASProvider]

View file

@ -0,0 +1,19 @@
{% extends "allauth/layouts/base.html" %}
{% load i18n %}
{% load static %}
{% load allauth %}
{% load socialaccount %}
{% get_providers as socialaccount_providers %}
{% block content %}
<h1 class="has-text-centered">Export cas ens</h1>
{% for data in extra_data %}
<h2>{{ data.0 }}</h2>
<pre>
{{ data.1 }}
</pre>
{% empty %}
<p>Veuillez vous connecter</p>
{% endfor %}
{% endblock content %}

1
casexporter/tests.py Normal file
View file

@ -0,0 +1 @@
# Create your tests here.

5
casexporter/urls.py Normal file
View file

@ -0,0 +1,5 @@
from allauth_cas.urls import default_urlpatterns
from .provider import ENSCASProvider
urlpatterns = default_urlpatterns(ENSCASProvider)

35
casexporter/views.py Normal file
View file

@ -0,0 +1,35 @@
from allauth.socialaccount.models import SocialAccount
from allauth_cas.views import CASAdapter, CASCallbackView, CASLoginView
from django.views.generic import TemplateView
from .provider import ENSCASProvider
class ENSCASAdapter(CASAdapter):
provider_id = ENSCASProvider.id
url = "https://sso.ens.psl.eu/cas/"
version = 3
class HomeView(TemplateView):
template_name = "home.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
social_accounts = (
SocialAccount.objects.filter(user=self.request.user)
if self.request.user.is_authenticated
else []
)
context["extra_data"] = [
(social_account.provider, social_account.extra_data)
for social_account in social_accounts
]
return context
login = CASLoginView.adapter_view(ENSCASAdapter)
callback = CASCallbackView.adapter_view(ENSCASAdapter)

22
manage.py Executable file
View file

@ -0,0 +1,22 @@
#!/nix/store/6b1fqdwb3g56j5pazv8zkx9qd0mv3wiz-python3-3.11.9/bin/python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == "__main__":
main()

144
npins/default.nix Normal file
View file

@ -0,0 +1,144 @@
/*
This file is provided under the MIT licence:
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
# Generated by npins. Do not modify; will be overwritten regularly
let
data = builtins.fromJSON (builtins.readFile ./sources.json);
inherit (data) version;
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
range =
first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1);
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
concatStrings = builtins.concatStringsSep "";
# If the environment variable NPINS_OVERRIDE_${name} is set, then use
# the path directly as opposed to the fetched source.
# (Taken from Niv for compatibility)
mayOverride =
name: path:
let
envVarName = "NPINS_OVERRIDE_${saneName}";
saneName = stringAsChars (c: if (builtins.match "[a-zA-Z0-9]" c) == null then "_" else c) name;
ersatz = builtins.getEnv envVarName;
in
if ersatz == "" then
path
else
# this turns the string into an actual Nix path (for both absolute and
# relative paths)
builtins.trace "Overriding path of \"${name}\" with \"${ersatz}\" due to set \"${envVarName}\"" (
if builtins.substring 0 1 ersatz == "/" then
/. + ersatz
else
/. + builtins.getEnv "PWD" + "/${ersatz}"
);
mkSource =
name: spec:
assert spec ? type;
let
path =
if spec.type == "Git" then
mkGitSource spec
else if spec.type == "GitRelease" then
mkGitSource spec
else if spec.type == "PyPi" then
mkPyPiSource spec
else if spec.type == "Channel" then
mkChannelSource spec
else if spec.type == "Tarball" then
mkTarballSource spec
else
builtins.throw "Unknown source type ${spec.type}";
in
spec // { outPath = mayOverride name path; };
mkGitSource =
{
repository,
revision,
url ? null,
submodules,
hash,
...
}:
assert repository ? type;
# At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository
# In the latter case, there we will always be an url to the tarball
if url != null && !submodules then
builtins.fetchTarball {
inherit url;
sha256 = hash; # FIXME: check nix version & use SRI hashes
}
else
let
url =
if repository.type == "Git" then
repository.url
else if repository.type == "GitHub" then
"https://github.com/${repository.owner}/${repository.repo}.git"
else if repository.type == "GitLab" then
"${repository.server}/${repository.repo_path}.git"
else
throw "Unrecognized repository type ${repository.type}";
urlToName =
url: rev:
let
matched = builtins.match "^.*/([^/]*)(\\.git)?$" url;
short = builtins.substring 0 7 rev;
appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else "";
in
"${if matched == null then "source" else builtins.head matched}${appendShort}";
name = urlToName url revision;
in
builtins.fetchGit {
rev = revision;
inherit name;
# hash = hash;
inherit url submodules;
};
mkPyPiSource =
{ url, hash, ... }:
builtins.fetchurl {
inherit url;
sha256 = hash;
};
mkChannelSource =
{ url, hash, ... }:
builtins.fetchTarball {
inherit url;
sha256 = hash;
};
mkTarballSource =
{
url,
locked_url ? url,
hash,
...
}:
builtins.fetchTarball {
url = locked_url;
sha256 = hash;
};
in
if version == 5 then
builtins.mapAttrs mkSource data.pins
else
throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`"

24
npins/sources.json Normal file
View file

@ -0,0 +1,24 @@
{
"pins": {
"git-hooks": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "cachix",
"repo": "git-hooks.nix"
},
"branch": "master",
"submodules": false,
"revision": "b68b780b69702a090c8bb1b973bab13756cc7a27",
"url": "https://github.com/cachix/git-hooks.nix/archive/b68b780b69702a090c8bb1b973bab13756cc7a27.tar.gz",
"hash": "1k99smax7zpa5cdw9afa4v4y4155amy21a8z5z8x3cikdz3gyx5p"
},
"nixpkgs": {
"type": "Channel",
"name": "nixpkgs-unstable",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-26.05pre913028.af84f9d270d4/nixexprs.tar.xz",
"hash": "0y61ia5r3b07r9m79zajyfll3fcsbg5a24lj8daajwbwhvpyd2q4"
}
},
"version": 5
}

View file

@ -0,0 +1,12 @@
diff --git a/setup.py b/setup.py
index fb06ec0..506677f 100644
--- a/setup.py
+++ b/setup.py
@@ -52,7 +52,6 @@ setup(
install_requires=[
"django-allauth",
"python-cas",
- "six",
],
extras_require={
"docs": ["sphinx"],

View file

@ -0,0 +1,39 @@
diff --git a/allauth_cas/signals.py b/allauth_cas/signals.py
index 36c9b24..530c26e 100644
--- a/allauth_cas/signals.py
+++ b/allauth_cas/signals.py
@@ -1,4 +1,4 @@
-from allauth.account.adapter import get_adapter
+from allauth.socialaccount.adapter import get_adapter
from allauth.account.utils import get_next_redirect_url
from allauth.socialaccount import providers
from django.contrib.auth.signals import user_logged_out
@@ -14,7 +14,7 @@ def cas_account_logout(sender, request, **kwargs):
if not provider_id:
return
- provider = providers.registry.by_id(provider_id, request)
+ provider = get_adapter(request).get_provider(request, provider_id)
if not provider.message_suggest_caslogout_on_logout(request):
return
diff --git a/allauth_cas/views.py b/allauth_cas/views.py
index d08e354..9e81e53 100644
--- a/allauth_cas/views.py
+++ b/allauth_cas/views.py
@@ -1,5 +1,5 @@
import cas
-from allauth.account.adapter import get_adapter
+from allauth.socialaccount.adapter import get_adapter
from allauth.account.utils import get_next_redirect_url
from allauth.socialaccount import providers
from allauth.socialaccount.helpers import (
@@ -56,7 +56,7 @@ class CASAdapter:
"""
Returns a provider instance for the current request.
"""
- return providers.registry.by_id(self.provider_id, self.request)
+ return get_adapter(self.request).get_provider(self.request, self.provider_id)
def complete_login(self, request, response):
"""

View file

@ -0,0 +1,51 @@
# SPDX-FileCopyrightText: 2025 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
wheel,
django-allauth,
python-cas,
}:
buildPythonPackage rec {
pname = "django-allauth-cas";
version = "unstable-2024-01-25";
pyproject = true;
src = fetchFromGitHub {
owner = "jlucasp25";
repo = "django-allauth-cas";
rev = "77e02f3796cd564a9a0c48b5b568b14d4d4c5687";
hash = "sha256-y/IquXl/4+9MJmsgbWtPun3tBbRJ4kJFzWo5c+5WeHk=";
};
patches = [
./01-setup.patch
./02-registry.patch
];
build-system = [
setuptools
wheel
];
dependencies = [
django-allauth
python-cas
];
pythonImportsCheck = [ "allauth_cas" ];
meta = {
description = "CAS support for django-allauth";
homepage = "https://github.com/jlucasp25/django-allauth-cas";
changelog = "https://github.com/jlucasp25/django-allauth-cas/blob/${src.rev}/CHANGELOG.rst";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ ];
};
}

View file

@ -0,0 +1,42 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
wheel,
asgiref,
django,
}:
buildPythonPackage rec {
pname = "django-browser-reload";
version = "1.18.0";
pyproject = true;
src = fetchFromGitHub {
owner = "adamchainz";
repo = "django-browser-reload";
rev = version;
hash = "sha256-iLu9+E3Ejp/Dhv4I7RuL/F1WNiFRKytNvNDDhrh0Hhs=";
};
nativeBuildInputs = [
setuptools
wheel
];
propagatedBuildInputs = [
asgiref
django
];
pythonImportsCheck = [ "django_browser_reload" ];
meta = with lib; {
description = "Automatically reload your browser in development";
homepage = "https://github.com/adamchainz/django-browser-reload";
changelog = "https://github.com/adamchainz/django-browser-reload/blob/${src.rev}/CHANGELOG.rst";
license = licenses.mit;
maintainers = with maintainers; [ thubrecht ];
};
}

View file

@ -0,0 +1,49 @@
# SPDX-FileCopyrightText: 2025 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
wheel,
lxml,
requests,
six,
}:
buildPythonPackage rec {
pname = "python-cas";
version = "1.6.0";
pyproject = true;
src = fetchFromGitHub {
owner = "python-cas";
repo = "python-cas";
rev = "v${version}";
hash = "sha256-0lpjG/Sma0tJGtahiFE1CjvTyswrBUp+F6f1S65b+lk=";
};
nativeBuildInputs = [
setuptools
wheel
];
propagatedBuildInputs = [
lxml
requests
six
];
pythonImportsCheck = [ "cas" ];
meta = with lib; {
description = "Python CAS (Central Authentication Service) client library support CAS 1.0/2.0/3.0";
homepage = "https://github.com/python-cas/python-cas";
license = licenses.mit;
maintainers = with maintainers; [
# thubrecht
];
};
}

71
provisioning/shell.nix Normal file
View file

@ -0,0 +1,71 @@
{
sources ? import ../npins,
pkgs ? import sources.nixpkgs { },
}:
let
check = (import sources.git-hooks).run {
src = ./.;
hooks = {
# JS hooks
# eslint.enable = true;
# Python hooks
ruff.enable = true;
black.enable = true;
isort.enable = true;
# Nix Hooks
statix.enable = true;
deadnix.enable = true;
rfc101 = {
enable = true;
name = "RFC-101 formatting";
entry = "${pkgs.lib.getExe pkgs.nixfmt-rfc-style}";
files = "\\.nix$";
};
# Misc Hooks
commitizen.enable = true;
};
};
python = pkgs.python3.override {
packageOverrides = self: _: {
python-cas = self.callPackage ./python-cas { };
django-allauth-cas = self.callPackage ./django-allauth-cas { };
django-browser-reload = self.callPackage ./django-browser-reload { };
};
};
in
pkgs.mkShell {
buildInputs = [
pkgs.jq
pkgs.dart-sass
(python.withPackages (
ps:
[
ps.django
ps.gunicorn
ps.django-browser-reload
ps.django-types
ps.django-allauth-cas
ps.django-allauth
#Debug
ps.black
ps.isort
]
++ ps.django-allauth.optional-dependencies.socialaccount
))
pkgs.djlint
]
++ check.enabledPackages;
shellHook = ''
${check.shellHook}
'';
}

30
pyproject.toml Normal file
View file

@ -0,0 +1,30 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "casexporter"
version = "1.0.0"
authors = [{name = "Maurice Debray", email = "sinavir@sinavir.fr"}]
description = ""
license = {file = "LICENSE"}
readme = "README.md"
classifiers = [
"Development Status :: 4 - Beta",
"License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)",
"Programming Language :: Python :: 3",
]
[tool.djlint]
blank_line_after_tag = "load,extends"
format_js = true
indent = 2
max_blank_lines = 1
profile = "django"
[tool.djlint.js]
indent_size = 4
[tool.isort]
profile = "black"

1
shell.nix Symbolic link
View file

@ -0,0 +1 @@
./provisioning/shell.nix