From 6a56e96fd901bf8f9f3f216b39455c2b6e6c68de Mon Sep 17 00:00:00 2001 From: Florian Streibelt Date: Sun, 9 Aug 2015 12:43:29 +0200 Subject: [PATCH 1/2] added call to callback, rewrote creds extraction, allow Custom User Model --- jsonrpc/__init__.py | 78 ++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/jsonrpc/__init__.py b/jsonrpc/__init__.py index 11d600f..813b759 100644 --- a/jsonrpc/__init__.py +++ b/jsonrpc/__init__.py @@ -188,7 +188,9 @@ def decorator(func): X['arg_names'] = authentication_arguments + X['arg_names'] X['name'] = _inject_args(X['name'], ('String', 'String')) from django.contrib.auth import authenticate as _authenticate - from django.contrib.auth.models import User + # allow replacement of User Model - is User actually used? + import django.contrib.auth + User = django.contrib.auth.get_user_model() else: authenticate = authenticated @six.wraps(func) @@ -198,32 +200,58 @@ def _func(request, *args, **kwargs): if ((user is not None and six.callable(is_authenticated) and not is_authenticated()) or user is None): - user = None - try: - creds = args[:len(authentication_arguments)] - if len(creds) == 0: - raise IndexError - # Django's authenticate() method takes arguments as dict - user = _authenticate(username=creds[0], password=creds[1], *creds[2:]) - if user is not None: - args = args[len(authentication_arguments):] - except IndexError: - auth_kwargs = {} - try: - for auth_kwarg in authentication_arguments: - auth_kwargs[auth_kwarg] = kwargs[auth_kwarg] - except KeyError: + + creds = {} + # first look for creds in kwargs + for auth_kwarg in authentication_arguments: + if auth_kwarg in kwargs: + creds[auth_kwarg] = kwargs.pop(auth_kwarg) + + if not len(creds)==len(authentication_arguments): + # not able to find (all) auth args in kwargs, trying args + creds = {} + # try to blindly use the first elements in args as kwargs... + try: + index = 0 + for auth_kwarg in authentication_arguments: + creds[auth_kwarg] = args[index] + index+=1 + args=args[index:] + except IndexError: + creds={} + + if not len(creds)==len(authentication_arguments): + # still no success with finding the credentials raise InvalidParamsError( 'Authenticated methods require at least ' - '[%s] or {%s} arguments', authentication_arguments) - - user = _authenticate(**auth_kwargs) - if user is not None: - for auth_kwarg in authentication_arguments: - kwargs.pop(auth_kwarg) - if user is None: - raise InvalidCredentialsError - request.user = user + '[%s] or {%s} arguments', + (authentication_arguments, authentication_arguments) + ) + + # if callback is provided, calling callback with creds + if callable(authenticated): + + try: + user = authenticated(**creds) + except Exception: + user = None + # callback threw exception + + if user is not None: + request.user = user + return func(request, *args, **kwargs) + else: + raise InvalidCredentialsError + + # finally trying djangos auth, e.g. callback was not provided + + # Django's authenticate() method takes arguments as dict, + # default configuration of authentication_arguments matches. + user = _authenticate(**creds) + if user is None: + raise InvalidCredentialsError + + request.user = user return func(request, *args, **kwargs) else: _func = func From 42467cb4e6989c5d73947ab7ed781424951929b5 Mon Sep 17 00:00:00 2001 From: Florian Streibelt Date: Sun, 9 Aug 2015 12:56:06 +0200 Subject: [PATCH 2/2] commenting out User model as this breaks 1.4 compatibilty and is not used anyway --- jsonrpc/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jsonrpc/__init__.py b/jsonrpc/__init__.py index 813b759..127406c 100644 --- a/jsonrpc/__init__.py +++ b/jsonrpc/__init__.py @@ -189,8 +189,10 @@ def decorator(func): X['name'] = _inject_args(X['name'], ('String', 'String')) from django.contrib.auth import authenticate as _authenticate # allow replacement of User Model - is User actually used? - import django.contrib.auth - User = django.contrib.auth.get_user_model() + # this breaks Django 1.4 compatibilty, so commenting out as + # it seems the model is not used anywhere directly anyway + # import django.contrib.auth + # User = django.contrib.auth.get_user_model() else: authenticate = authenticated @six.wraps(func)