Source code for esi.decorators

import logging
from functools import wraps

from .models import Token, CallbackRedirect


logger = logging.getLogger(__name__)


def _check_callback(request):
    # ensure session installed in database
    if not request.session.exists(request.session.session_key):
        logger.debug("Creating new session for %s", request.user)
        request.session.create()

    # clean up callback redirect, pass token if new requested
    try:
        model = CallbackRedirect.objects.get(session_key=request.session.session_key)
        token = Token.objects.get(pk=model.token.pk)
        model.delete()
        logger.debug(
            "Retrieved new token from callback for %s session %s",
            request.user,
            request.session.session_key[:5])
        return token

    except (CallbackRedirect.DoesNotExist, Token.DoesNotExist, AttributeError):
        logger.debug(
            "No callback for %s session %s",
            request.user,
            request.session.session_key[:5],
            exc_info=True
        )
        return None


[docs] def tokens_required(scopes='', new=False): """ Decorator for views to request an ESI Token. Accepts required scopes as a space-delimited string or list of strings of scope names. Can require a new token to be retrieved by SSO. Returns a QueryDict of Tokens. """ def decorator(view_func): @wraps(view_func) def _wrapped_view(request, *args, **kwargs): # if we're coming back from SSO with a new token, return it token = _check_callback(request) if token: tokens = Token.objects.filter(pk=token.pk) logger.debug("Returning new token.") return view_func(request, tokens, *args, **kwargs) if not new: # ensure user logged in to check existing tokens if not request.user.is_authenticated: logger.debug( "Session %s is not logged in. Redirecting to login.", request.session.session_key[:5] ) from django.contrib.auth.views import redirect_to_login return redirect_to_login(request.get_full_path()) # collect tokens in db, check if still valid, return if any tokens = ( Token.objects .filter(user__pk=request.user.pk) .require_scopes(scopes) .require_valid() ) if tokens.exists(): logger.debug( "Retrieved %s tokens for %s session %s", tokens.count(), request.user, request.session.session_key[:5] ) return view_func(request, tokens, *args, **kwargs) # trigger creation of new token via sso logger.debug( "No tokens identified for %s session %s. Redirecting to SSO.", request.user, request.session.session_key[:5] ) from esi.views import sso_redirect return sso_redirect(request, scopes=scopes) return _wrapped_view return decorator
[docs] def token_required(scopes='', new=False): """ Decorator for views which supplies a single, user-selected token for the view to process. Same parameters as tokens_required. """ def decorator(view_func): @wraps(view_func) def _wrapped_view(request, *args, **kwargs): # if we're coming back from SSO with a new token, return it token = _check_callback(request) if token: logger.debug( "Got new token from %s session %s. Returning to view.", request.user, request.session.session_key[:5] ) return view_func(request, token, *args, **kwargs) # if we're selecting a token, return it if request.method == 'POST': if request.POST.get("_add", False): logger.debug( "%s has selected to add new token. Redirecting to SSO.", request.user ) # user has selected to add a new token from esi.views import sso_redirect return sso_redirect(request, scopes=scopes) token_pk = request.POST.get('_token', None) if token_pk: logger.debug( "%s has selected token %s", request.user, token_pk ) try: token = Token.objects.get(pk=token_pk) # ensure token belongs to this user and has required scopes if ( ( (token.user and token.user == request.user) or not token.user ) and Token.objects .filter(pk=token_pk) .require_scopes(scopes) .require_valid() .exists() ): logger.debug( "Selected token fulfills requirements of view. " "Returning." ) return view_func(request, token, *args, **kwargs) except Token.DoesNotExist: logger.debug("Token %s not found.", token_pk) if not new: # present the user with token choices tokens = ( Token.objects .filter(user__pk=request.user.pk) .require_scopes(scopes) .require_valid() ) if tokens.exists(): logger.debug( "Returning list of available tokens for %s.", request.user ) from esi.views import select_token return select_token(request, scopes=scopes, new=new) else: logger.debug( "No tokens found for %s session %s with scopes %s", request.user, request.session.session_key[:5], scopes ) # prompt the user to add a new token logger.debug( "Redirecting %s session %s to SSO.", request.user, request.session.session_key[:5] ) from esi.views import sso_redirect return sso_redirect(request, scopes=scopes) return _wrapped_view return decorator
[docs] def single_use_token(scopes='', new=False): """ Decorator for views which supplies a single use token granted via sso login regardless of login state. Same parameters as tokens_required. """ def decorator(view_func): @wraps(view_func) def _wrapped_view(request, *args, **kwargs): # if we're coming back from SSO for a new token, return it token = _check_callback(request) if token: logger.debug( "Got new token from session %s. Returning to view.", request.session.session_key[:5] ) return view_func(request, token, *args, **kwargs) # prompt the user to login for a new token logger.debug( "Redirecting session %s to SSO.", request.session.session_key[:5] ) from esi.views import sso_redirect return sso_redirect(request, scopes=scopes) return _wrapped_view return decorator