Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decorators depending on request method types #169

Open
erdimeola opened this issue Apr 27, 2021 · 3 comments
Open

Decorators depending on request method types #169

erdimeola opened this issue Apr 27, 2021 · 3 comments
Labels
feature new features

Comments

@erdimeola
Copy link

Hi, hope everyone is healthy and safe.

I have multiple views which are working with multiple request methods. For some of these views, I'ld like to update/replace/exclude the csp only for the request method. For example;

@csp_exempt(methods=["POST"])
def view(request):
    if request.method == "GET":
        result = do_get_with_default_csp(request)
    elif request.method == "POST":
        result = do_post_with_csp_excluded(request)
    else:
        raise InvalidRequestException()
    return result

@csp_update(methods=["GET"], SCRIPT_SRC=["url"])
def another_view(request):
    if request.method == "GET":
        result = do_get_with_updated_csp(request)
    elif request.method == "POST":
        result = do_post_with_default_csp(request)
    else:
        raise InvalidRequestException()
    return result

I hope I'm not the only one in need of such feature.

@DylanYoung
Copy link
Contributor

I think it will be simple to add this after #36 has landed. Though I have to admit, I'm confused about the value proposition here. Can you explain a little bit about why you want to do this @erdimeola?

@some1ataplace

This comment was marked as spam.

@erdimeola
Copy link
Author

erdimeola commented Nov 7, 2023

Sorry for the late answer.

I think it will be simple to add this after #36 has landed. Though I have to admit, I'm confused about the value proposition here. Can you explain a little bit about why you want to do this @erdimeola?

Payment pages. If GET request return payment page, and POST request gets the information and redirects to 3d secure pages (as html), we need to apply some exemptions or updates to CSP for the payment to start.

@some1ataplace I just updated the decorators.py in github code to check method. This worked for me. Code is below;

example usage: @csp_exempt(methods=["POST"])

from functools import wraps

def valid_method(allowed_methods, request):
    """
        Params:
            allowed_methods:    list or string of method to make the update
            request:            the request for the csp

        Returns:
            True if the method in decorator parameter matches

        Check if any method restriction is available. If not, update is valid.
        If a list of methods is given, iterate through methods to check if request method is in
        restriction
        If only a method is given, check if the request method is the matching one
    """
    if allowed_methods is None:
        return True
    if isinstance(request, tuple):
        request = request[0]
    result = False
    if isinstance(allowed_methods, list):
        for method in allowed_methods:
            if request.method == method:
                result = True
                break
    elif isinstance(allowed_methods, str):
        if request.method == allowed_methods:
            result = True
    return result

def csp_exempt(methods=None, **kwargs):
    """
        csp_exempt
    """
    def decorator(function):
        @wraps(function)
        def _wrapped(*a, **kw):
            response = function(*a, **kw)
            if valid_method(methods, a):
                response._csp_exempt = True
            return response
        return _wrapped
    return decorator


def csp_update(methods=None, **kwargs):
    """
        csp_update
    """
    update = dict((k.lower().replace('_', '-'), v) for k, v in kwargs.items())

    def decorator(function):
        @wraps(function)
        def _wrapped(*a, **kw):
            response = function(*a, **kw)
            if valid_method(methods, a):
                response._csp_update = update
            return response
        return _wrapped
    return decorator


def csp_replace(methods=None, **kwargs):
    """
        csp_replace
    """
    replace = dict((k.lower().replace('_', '-'), v) for k, v in kwargs.items())

    def decorator(function):
        @wraps(function)
        def _wrapped(*a, **kw):
            response = function(*a, **kw)
            if valid_method(methods, a):
                response._csp_replace = replace
            return response
        return _wrapped
    return decorator


def csp(methods=None, **kwargs):
    """
        csp
    """
    config = dict(
        (k.lower().replace('_', '-'), [v] if isinstance(v, str) else v)
        for k, v
        in kwargs.items()
    )

    def decorator(function):
        @wraps(function)
        def _wrapped(*a, **kw):
            response = function(*a, **kw)
            if valid_method(methods, a):
                response._csp_config = config
            return response
        return _wrapped
    return decorator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature new features
Projects
None yet
Development

No branches or pull requests

4 participants