From 2042e91699b4bc9d9e7171e36dba6f7f6ef0f781 Mon Sep 17 00:00:00 2001 From: Michele-Alberti <62114934+Michele-Alberti@users.noreply.github.com> Date: Sat, 4 Jan 2025 01:55:09 +0100 Subject: [PATCH] feat(AuthCallback): add AuthCallback class and convert authorize function to a method now the authorization callback is a method of an object instantiated by hydra, selected from auth/default.yaml config file change auth/default.yaml config file to instantiate an object instead of a function --- dlunch/__main__.py | 6 +-- dlunch/auth.py | 94 +++++++++++++++++++---------------- dlunch/conf/auth/default.yaml | 3 +- 3 files changed, 55 insertions(+), 48 deletions(-) diff --git a/dlunch/__main__.py b/dlunch/__main__.py index 850c9b3..5b491a2 100755 --- a/dlunch/__main__.py +++ b/dlunch/__main__.py @@ -56,12 +56,10 @@ def run_app(config: DictConfig) -> None: # Configurations pn.config.nthreads = config.panel.nthreads pn.config.notifications = True - authorize_callback_factory = hydra.utils.call( + authorize_callback_object: auth.AuthCallback = hydra.utils.instantiate( config.auth.authorization_callback, config ) - pn.config.authorize_callback = lambda ui, tp: authorize_callback_factory( - user_info=ui, target_path=tp - ) + pn.config.authorize_callback = authorize_callback_object.authorize pn.config.auth_template = config.auth.auth_error_template # If basic auth is used the database and users credentials shall be created here diff --git a/dlunch/auth.py b/dlunch/auth.py index d96cd1b..b21bef9 100644 --- a/dlunch/auth.py +++ b/dlunch/auth.py @@ -589,7 +589,7 @@ def set_guest_user_password(self) -> str: if self.is_basic_auth_active(): # If active basic_auth.guest_user is true if guest user is active is_guest_user_active = self.config.basic_auth.guest_user - log.debug("guest user flag is {is_guest_user_active}") + log.debug(f"guest user flag is {is_guest_user_active}") else: # Otherwise the guest user feature is not applicable is_guest_user_active = False @@ -970,51 +970,61 @@ def remove_user(self) -> dict: } -# FUNCTIONS ------------------------------------------------------------------- - - -def authorize( - config: DictConfig, - user_info: dict, - target_path: str, - authorize_guest_users=False, -) -> bool: - """Authorization callback: read config, user info and the target path of the - requested resource. - - Return `True` (authorized) or `False` (not authorized) by checking current user - and target path. +class AuthCallback: + """Class to handle authorization callback. Args: config (DictConfig): Hydra configuration dictionary. - user_info (dict): dictionary with user info passed by Panel to the authorization handle. - target_path (str): path of the requested resource. authorize_guest_users (bool, optional): Set to `True` to enable the main page to guest users. Defaults to `False`. - - Returns: - bool: authorization flag. `True` if authorized. """ - # Set authenticated user from panel state (authentication context is - # instantiated automatically) - auth_user = AuthUser(config=config) - # If authorization is not active authorize every user - if not auth_user.auth_context.is_auth_active(): - return True - # Get privileged users - privileged_users = auth_user.auth_context.list_privileged_users() - log.debug(f"target path: {target_path}") - # If user is not authenticated block it - if not auth_user.name: + + def __init__( + self, config: DictConfig, authorize_guest_users: bool = False + ) -> None: + self.config = config + self.authorize_guest_users = authorize_guest_users + + def authorize(self, user_info: dict, target_path: str) -> bool: + """Authorization callback: read config, user info and the target path of the + requested resource. + + Return `True` (authorized) or `False` (not authorized) by checking current user + and target path. + + Args: + user_info (dict): dictionary with user info passed by Panel to the authorization handle. + target_path (str): path of the requested resource. + + Returns: + bool: authorization flag. `True` if authorized. + """ + # Set authenticated user from panel state (authentication context is + # instantiated automatically) + auth_user = AuthUser(config=self.config) + # If authorization is not active authorize every user + if not auth_user.auth_context.is_auth_active(): + return True + # Get privileged users + privileged_users = auth_user.auth_context.list_privileged_users() + log.debug(f"target path: {target_path}") + # If user is not authenticated block it + if not auth_user.name: + log.debug("user not authenticated") + return False + # All privileged users can reach backend (but the backend will have + # controls only for admins) + if auth_user.name in privileged_users: + return True + # If the target is the mainpage always authorized (if authenticated) + if self.authorize_guest_users and (target_path == "/"): + return True + + # In all other cases, don't authorize and logout + log.debug("not authorized") + pn.state.location.pathname.split("/")[0] + "/logout" return False - # All privileged users can reach backend (but the backend will have - # controls only for admins) - if auth_user.name in privileged_users: - return True - # If the target is the mainpage always authorized (if authenticated) - if authorize_guest_users and (target_path == "/"): - return True - - # In all other cases, don't authorize and logout - pn.state.location.pathname.split("/")[0] + "/logout" - return False + + +# FUNCTIONS ------------------------------------------------------------------- +# Intentionally left void diff --git a/dlunch/conf/auth/default.yaml b/dlunch/conf/auth/default.yaml index 37023e7..55b7120 100644 --- a/dlunch/conf/auth/default.yaml +++ b/dlunch/conf/auth/default.yaml @@ -7,8 +7,7 @@ oauth_expiry: 15 auth_error_template: ${package_path}/templates/error.html # Autorization callback (_partial_ is required for usage with lambda functions) authorization_callback: - _target_: dlunch.auth.authorize - _partial_: true + _target_: dlunch.auth.AuthCallback # Flag to authorize access of guest users to the home page # They can only place orders for guests authorize_guest_users: true