Metadata-Version: 2.1
Name: authens
Version: 0.1b6
Summary: CAS Authentication Client at the ENS.
Author-email: Klub Dev ENS <klub-dev@ens.fr>, Tom Hubrecht <pypi@mail.hubrecht.ovh>
License: The MIT License (MIT)
        
        Copyright 2020 Klub Dev ENS
        
        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.
        
Project-URL: Homepage, https://git.dgnum.eu/DGNum/authens
Project-URL: Repository, https://git.dgnum.eu/DGNum/authens
Project-URL: Issues, https://git.dgnum.eu/DGNum/authens/issues
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 2.2
Classifier: Framework :: Django :: 3.1
Classifier: Framework :: Django :: 3.2
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: django>=2.2
Requires-Dist: python-ldap<4,>=3
Requires-Dist: python-cas<2,>=1.5

# AuthENS

Librairie Django pour l'authentification via le CAS élèves à l'ENS.

AuthENS fournit une page de connexion qui laisse le choix entre "Connexion par
CAS" et "Connexion par mot de passe".
De plus, elle gère de façon transparente les potentiels "conflits" de `username`
liés aux comptes Django standards non-CAS (1) et aux vieux comptes clippers (2).
Plus précisément :

1. Si un compte clipper `dupond` est créé alors qu'un compte Django standard
   avec le `username` `dupond` existait déjà, le compte nouvellement créé
   obtient un `username` différent (typiquement `dupond2`).
   La personne détentrice du compte continue de se connecter en tant que
   `dupond` sur le CAS élèves mais devra utiliser le nom `dupond2` lorsqu'elle
   choisira d'utiliser la connexion par mot de passe sur le site, typiquement
   après la fin de la scolarité lorsque le compte clipper est supprimé.

2. Si, quelques années plus tard, après que `dupond` a terminé sa scolarité, le
   SPI donne le login `dupond` à une nouvelle personne, AuthENS détecte que le
   nouveau compte `dupond` n'est pas le même que l'ancien et crée un nouveau
   compte (par exemple `dupond3`).
   Le compte `dupond3` peut se connecter par CAS en tant que `dupond` et le
   compte `dupond2` ne peut plus se connecter que par mot de passe.


## Configuration

### Urls

Vous devez rendre les pages de connexion de AuthENS accessibles, par exemple en
ajoutant dans votre fichier d'urls :

```python
urlpatterns = [
  ...
  path("authens/", include("authens.urls")),
  ...
]
```

La page de connexion principale de AuthENS est ensuite accessible via l'url
nommée `authens:login`.
La page de déconnexion est `authens:logout`, il est important d'utiliser cette
vue est non la vue de déconnexion par défaut de Django pour déconnecter du CAS
en plus du site.

### Dans le fichier `settings.py`

- Ajouter `"authens"` dans les [`INSTALLED_APPS`](https://docs.djangoproject.com/en/3.0/ref/settings/#installed-apps).
- Ajouter `"authens.backends.ENSCASBackend"` dans les
  [`AUTHENTICATION_BACKENDS`](https://docs.djangoproject.com/en/3.0/ref/settings/#authentication-backends).
  Si `AUTHENTICATION_BACKENDS` n'apparaît pas dans vos settings, utiliser :

```python
AUTHENTICATION_BACKENDS = [
    "django.contrib.auth.backends.ModelBackend",
    "authens.backends.ENSCASBackend",
]
```

- Préciser l'url de connexion:

```python
LOGIN_URL = reverse_lazy("authens:login")
```

- (Optionnel) Par défaut AuthENS propose les 3 modes de connexion (CAS / Vieux
  compte CAS / mot de passe). Les modes de connexion "Vieux compte CAS" et
  "mot de passe" peuvent être désactivés en ajoutant :

```python
AUTHENS_USE_OLDCAS = False
AUTHENS_USE_PASSWORD = False
```

- (Optionnel) Il est possible d'autoriser la connexion via CAS pour les membres
  de `staffs`, lorsque cette option est activée, leur promotion est fixée à 0,
  lorsque l'option est désactivée, une tentative de connexion renvoie une erreur
  car le format de `$HOME` n'est pas valide.

```python
AUTHENS_ALLOW_STAFF = True
```


- (Optionnel) AuthENS utilise le paramètre Django standard
  [`LOGIN_REDIRECT_URL`](https://docs.djangoproject.com/en/3.0/ref/settings/#login-redirect-url)
  par défaut pour rediriger l'utilisateurice en cas de connexion réussie.
  Il peut être utile de définir ce paramètre.


## Utilisation

À lire

### Création d'utilisateurices

AuthENS maintient une table des comptes clipper connus.
Cette table est automatiquement mise à jour lors qu'une personne se connecte via
le CAS pour la première fois.
En revanche lorsqu'un nouveau compte est créé manuellement et que ce compte
correspond à un compte clipper, il faut enregistrer ce compte auprès d'AuthENS,
autrement le compte Django et le compte clipper seront considérés comme deux
comptes différents.
Authens fournit une fonction `register_cas_account` pour cela.

Exemple:

```python
from authens.shortcuts import register_cas_account
from django.http import HttpResponseRedirect
from yourapp.forms import UserCreationForm

def create_user_view(requests, cas_login: str):
    if request.method == "POST":
        form = UserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            register_cas_account(user, cas_login)
            return HttpResponseRedirect("success.html")
    else:
        form = UserCreationForm()

    return render(request, "create_user.html", {"form": form}
```


## Utilisation avancée

### Modification des templates

Il est possible de supplanter les templates d'authens en activant un répertoire
de templates dans les settings Django, puis de créer un dossier `authens` dans
celui-ci. Les templates à substituer sont :

- `authens/login_switch.html` pour la sélection de la méthode de connexion
- `authens/pwd_login.html` pour le formulaire de connexion par mot de passe
- `authens/pwd_reset.html` pour le formulaire de demande de réinitialisation de
  mot de passe
- `authens/pwd_reset_confirm.html` pour le formulaire de réinitialisation de mot
  de passe

### Migration depuis `django_cas_ng`

Pour migrer depuis `django_cas_ng`, il est recommandé de faire une
[data migration](https://docs.djangoproject.com/en/3.1/howto/writing-migrations/#migrating-data-between-third-party-apps)
et d'appliquer la fonction `register_cas_account` sur tou⋅tes les
utilisateurices.

Dans le cas où certain⋅es utilisateurices n'ont pas de clipper, on peut d'abord
tester leur existence dans le LDAP du SPI de la façon suivante:

```python
from authens.models impomrt CASAccount
from authens.shortcuts import fetch_cas_account

def migrate_user(user: User):
    # On regarde si `user` existe dans le LDAP du SPI
    ldap_info = fetch_cas_account(user.username)
    if ldap_info:
        # Si oui, on enregiste `user` en tant que compte CAS.
        # Les deux lignes suivantes sont équivalentes à appeler
        # `register_cas_account(user, user.username)` mais nous économisent une
        # requête au LDAP.
        entrance_year = ldap_info["entrance_year"]
        CASAccount.objects.create(
            user=user, cas_login=user.username, entrance_year=entrance_year
        )
```

### Utilisation des signaux

Authens émet le signal `authens.signals.post_cas_connect` à chaque fois qu'un
compte CAS se connecte. Le signal est envoyé avec les arguments suivants :

- `sender` : la classe Django utilisée pour stocker l'utilisateurice
  (vraisemblablement la class `User` par défaut);

- `instance` : l'utilisateurice concerné⋅e;

- `created` : un booléen valant `True` si l'utilisateurice vient d'être créé⋅e
  (première connexion);

- `cas_login` : le login CAS de la personne;

- `attributes` : un dictionnaire contenant des informations supplémentaires sur
  le compte, fournies par le CAS.
