From 968667d9edf77091db2809884033b2b43d701664 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Tue, 20 Aug 2019 03:32:52 +0200 Subject: [PATCH] Try to improve the semantic of where/when the auth happens... --- moulinette/actionsmap.py | 11 +++++++++++ moulinette/interfaces/api.py | 37 +++++++++++++++++++----------------- moulinette/interfaces/cli.py | 6 ++++++ 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/moulinette/actionsmap.py b/moulinette/actionsmap.py index 63483701..4e936800 100644 --- a/moulinette/actionsmap.py +++ b/moulinette/actionsmap.py @@ -473,6 +473,17 @@ class ActionsMap(object): - **kwargs -- Additional interface arguments """ + + # Perform authentication if needed + auth_required = self.parser.auth_required(args, **kwargs) + if auth_required: + auth_conf, klass = auth_required + + # TODO: Catch errors + auth = msignals.authenticate(klass(), **auth_conf) + if not auth.is_authenticated: + raise MoulinetteError('authentication_required_long') + # Parse arguments arguments = vars(self.parser.parse_args(args, **kwargs)) diff --git a/moulinette/interfaces/api.py b/moulinette/interfaces/api.py index 3828fd42..507ab861 100644 --- a/moulinette/interfaces/api.py +++ b/moulinette/interfaces/api.py @@ -623,6 +623,24 @@ class ActionsMapParser(BaseActionsMapParser): # Return the created parser return parser + def auth_required(self, args, route, **kwargs): + try: + # Retrieve the tid for the route + tid, _ = self._parsers[route] + if not self.get_conf(tid, 'authenticate'): + return False + else: + # TODO: In the future, we could make the authentication + # dependent of the route being hit ... + # e.g. in the context of friend2friend stuff that could + # auth with some custom auth system to access some + # data + # return self.get_conf(tid, 'authenticator') + return self.get_global_conf('authenticator', 'default') + except KeyError: + logger.error("no argument parser found for route '%s'", route) + raise MoulinetteError('error_see_log') + def parse_args(self, args, route, **kwargs): """Parse arguments @@ -631,28 +649,13 @@ class ActionsMapParser(BaseActionsMapParser): """ try: - # Retrieve the tid and the parser for the route - tid, parser = self._parsers[route] + # Retrieve the parser for the route + _, parser = self._parsers[route] except KeyError: logger.error("no argument parser found for route '%s'", route) raise MoulinetteError('error_see_log') ret = argparse.Namespace() - # Perform authentication if needed - if self.get_conf(tid, 'authenticate'): - # TODO: Clean this hard fix and find a way to set an authenticator - # to use for the api only - # auth_conf, klass = self.get_conf(tid, 'authenticator') - auth_conf, klass = self.get_global_conf('authenticator', 'default') - - # TODO: Catch errors - auth = msignals.authenticate(klass(), **auth_conf) - if not auth.is_authenticated: - raise MoulinetteError('authentication_required_long') - if self.get_conf(tid, 'argument_auth') and \ - self.get_conf(tid, 'authenticate') == 'all': - ret.auth = auth - # TODO: Catch errors? ret = parser.parse_args(args, ret) parser.dequeue_callbacks(ret) diff --git a/moulinette/interfaces/cli.py b/moulinette/interfaces/cli.py index 70e2833a..9a10c17b 100644 --- a/moulinette/interfaces/cli.py +++ b/moulinette/interfaces/cli.py @@ -347,6 +347,12 @@ class ActionsMapParser(BaseActionsMapParser): deprecated=deprecated, deprecated_alias=deprecated_alias) + def auth_required(self, args, **kwargs): + # No auth is required for CLI, + # e.g. in the context of Yunohost we only run as root + # but we could someday change this code to check for + return False + def add_global_arguments(self, arguments): for argument_name, argument_options in arguments.items(): # will adapt arguments name for cli or api context