Opened 2 years ago

Last modified 2 years ago

#26480 new New feature

Allow sensitive_variables() to preserve the signature of its decorated function

Reported by: tpazderka Owned by: nobody
Component: Error reporting Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When the method authenticate of a custom AuthenticationBackend is decorated with sensitive_variables, inspect.getcallargs will always match.

Calling the authenticate function will attempt to call this backend with any set of credentials and will raise an uncaught TypeError for an unmatching backend.

Authentication with such decorated backends used to work in version 1.6.

Change History (6)

comment:1 Changed 2 years ago by Tim Graham

Could you please try bisecting to find the commit where the behavior changed?

comment:2 Changed 2 years ago by tpazderka

Last edited 2 years ago by Tim Graham (previous) (diff)

comment:3 Changed 2 years ago by Tim Graham

Thanks! I'm not sure what can be done to fix this. Any ideas?

comment:4 Changed 2 years ago by tpazderka

Nothing apart from going back to the previous masking of TypeError... I think that these two behaviours go against each other...

comment:5 Changed 2 years ago by Tim Graham

Component: contrib.authError reporting
Summary: TypeError in authenticate decorated by sensitive_variablesAllow sensitive_variables() to preserve the signature of its decorated function
Triage Stage: UnreviewedAccepted
Type: BugNew feature

It might be possible to allow sensitive_variables to preserve the signature of whatever it decorates. Here's code that works until @sensitive_variables is added:

import inspect
from django.views.decorators.debug import sensitive_variables

class Backend(object):
    @sensitive_variables
    def authenticate(self, username=None, password=None):
        print(username)

inspect.getcallargs(Backend().authenticate, username='foo', password='bar')

comment:6 Changed 2 years ago by Vlastimil Zíma

What about something like this:

def sensitive_variables(*variables):
    def decorator(func):
        @functools.wraps(func)
        def sensitive_variables_wrapper(*func_args, **func_kwargs):
            ...
        # Keep the original function for inspection in `authenticate`
        sensitive_variables_wrapper.sensitive_variables_func = func
        return sensitive_variables_wrapper
    return decorator

Function authenticate would then check the sensitive_variables_func first.

Note: See TracTickets for help on using tickets.
Back to Top