• [^] # Re: Dommage cette licence non libre

    Posté par (site web personnel) . En réponse au journal Django + Jupyter Lab = ❤️. Évalué à 2.

    Tu as raison sur le fond. Voici le même code sous licence MIT.

    # Copyright 2023 Jonathan Tremesaygues
    #
    # 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.
    from importlib import import_module
    from typing import Awaitable, Optional
    from asgiref.sync import sync_to_async
    from jupyter_server.auth import IdentityProvider
    from jupyter_server.auth.identity import User as JUser
    from jupyter_server.base.handlers import JupyterHandler
    from django.conf import settings
    from django.contrib import auth
    from django.contrib.auth.models import User as DUser
    # https://jupyter-server.readthedocs.io/en/latest/operators/security.html#jupyter_server.auth.IdentityProvider
    class DjangoIdentityProvider(IdentityProvider):
     def __init__(self, **kwargs):
     super().__init__(**kwargs)
     # C'est vraiment la méthode recommandée par Django pour charqer le bon
     # moteur de session >_<
     # https://docs.djangoproject.com/en/4.2/topics/http/sessions/#using-sessions-out-of-views
     self.SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
     # https://jupyter-server.readthedocs.io/en/latest/operators/security.html#jupyter_server.auth.IdentityProvider.get_user
     async def get_user(self, handler: JupyterHandler) -> Optional[JUser] | Awaitable[Optional[JUser]]:
     # `get_user` est utilisé dans un contexte async mais Django préfère un 
     # contexte sync pour parler avec la db. Et le SessionStore par défaut 
     # utilise la db. Pis de toute façon faudra accéder à la DB pour charger
     # l'utilisateur.
     # https://docs.djangoproject.com/en/4.2/topics/async/
     return await sync_to_async(self._get_user)(handler)
     def _get_user(self, handler: JupyterHandler) -> Optional[JUser]:
     # Essaye de récupérer le session id dans les cookies
     if (cookie_entry := handler.request.cookies.get(settings.SESSION_COOKIE_NAME)) is not None:
     # Charge la session correspondante
     session = self.SessionStore(session_key=cookie_entry.value).load()
     # Essaye de récupérer l'user id correspondant
     if (user_id := session[auth.SESSION_KEY]) is not None:
     try:
     # Essaye de charger l'utilisateur correspondant 
     user = DUser.objects.get(pk=user_id)
     except DUser.DoesNotExist:
     # Utilisateur non trouvé
     pass
     else:
     # Est-ce que l'utilisateur est un admin?
     if user.is_staff:
     # L'utilisateur actuel est bien connecté et est un admin!
     # Crée un Jupyter user à partir du Django user
     return JUser(username=user.username)
     # Impossible d'authentifier l'utilisateur
     return None