Yet another permissions

Inspired by

And Bridget’s awesome comment near the end of this thread:

I thought I’d make this even simpler for my needs. I created several ‘auth_’ boolean columns in my users table and those are my permissions. I went with this route after trying 2/3 table setups that were just too complicated when it came to querying based on permissions.

I modified the scripts seen in the above threads to come up with this to wrap around the anvil.server.callable, which I have stored in a helpers.py server module:

import anvil.server

from functools import wraps, partial


def permission_required(permissions):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)
        return anvil.server.callable(require_user=partial(check_user_auth, permissions=permissions))(wrapper)
    return decorator


def check_user_auth(user, permissions):
    print('Checking user auth: ', permissions)
    if user is None:
        return False
        
    if isinstance(permissions, str):
        required_permissions = set([permissions])
    else:
        required_permissions = set(permissions)

    try:
        user_permissions = set(
            [
                permission
                for permission in required_permissions
                if user[permission] == True
            ]
        )
    except Exception:
        return False
        
    if not required_permissions.issubset(user_permissions):
        return False
        
    return True

And now, I have a single decorator I can use for server callables I want to authorize:

from .helpers import permission_required

@permission_required('auth_members')
def do_something(input):
    # do something
    return None
5 Likes

Really nice. I like the ability to have a combination of permissions for a single method.

1 Like