From 9fe4ea478d22d7dfb2638eee8a8b2246f90af002 Mon Sep 17 00:00:00 2001 From: "Kali Kaneko (leap communications)" Date: Mon, 12 Dec 2016 01:43:51 +0100 Subject: [refactor] reorganize API so that whitelisting doesn't have to peek into the data. added more documentation and some tests stubs too. --- src/leap/bitmask/__init__.py | 6 ++-- src/leap/bitmask/cli/bitmask_cli.py | 16 +++++++--- src/leap/bitmask/core/dispatcher.py | 57 ++++++++++++++++++++---------------- src/leap/bitmask/core/dummy.py | 56 +++++++++++++++++++++++++---------- src/leap/bitmask/core/launcher.py | 1 + src/leap/bitmask/core/service.py | 1 + src/leap/bitmask/core/web/_auth.py | 3 -- src/leap/bitmask/core/web/service.py | 8 ++++- 8 files changed, 97 insertions(+), 51 deletions(-) (limited to 'src/leap') diff --git a/src/leap/bitmask/__init__.py b/src/leap/bitmask/__init__.py index 20719d47..6fd6174d 100644 --- a/src/leap/bitmask/__init__.py +++ b/src/leap/bitmask/__init__.py @@ -2,9 +2,6 @@ import sys import pkg_resources from ._version import get_versions -__version__ = get_versions()['version'] -del get_versions - if not getattr(sys, 'frozen', False): # FIXME: HACK for https://github.com/pypa/pip/issues/3 # Without this 'fix', there are resolution conflicts when pip installs at @@ -12,3 +9,6 @@ if not getattr(sys, 'frozen', False): # namespace from pypi. For instance: # 'pip install -e .' and 'pip install leap.common' pkg_resources.get_distribution('leap.bitmask') + +__version__ = get_versions()['version'] +del get_versions diff --git a/src/leap/bitmask/cli/bitmask_cli.py b/src/leap/bitmask/cli/bitmask_cli.py index 893b7d11..dfd1fbcd 100755 --- a/src/leap/bitmask/cli/bitmask_cli.py +++ b/src/leap/bitmask/cli/bitmask_cli.py @@ -60,7 +60,6 @@ GENERAL COMMANDS: ''' epilog = ("Use 'bitmaskctl help' to learn more " "about each command.") - commands = ['stop', 'stats'] def user(self, raw_args): user = User() @@ -99,7 +98,7 @@ GENERAL COMMANDS: return defer.succeed(None) def version(self, raw_args): - self.data = ['version'] + self.data = ['core', 'version'] return self._send(printer=self._print_version) def _print_version(self, version): @@ -107,7 +106,7 @@ GENERAL COMMANDS: print(Fore.GREEN + 'bitmask_core: ' + Fore.RESET + corever) def status(self, raw_args): - self.data = ['status'] + self.data = ['core', 'status'] return self._send(printer=self._print_status) def _print_status(self, status): @@ -119,11 +118,19 @@ GENERAL COMMANDS: print(key.ljust(10) + ': ' + color + value + Fore.RESET) + def stop(self, raw_args): + self.data = ['core', 'stop'] + return self._send(printer=command.default_dict_printer) + + def stats(self, raw_args): + self.data = ['core', 'stats'] + return self._send(printer=command.default_dict_printer) + @defer.inlineCallbacks def execute(): cli = BitmaskCLI() - cli.data = ['version'] + cli.data = ['core', 'version'] args = ['--verbose'] if '--verbose' in sys.argv else None yield cli._send( timeout=0.1, printer=_null_printer, @@ -152,5 +159,6 @@ def main(): signal.signal(signal.SIGINT, signal_handler) reactor.run() + if __name__ == "__main__": main() diff --git a/src/leap/bitmask/core/dispatcher.py b/src/leap/bitmask/core/dispatcher.py index 59003906..b068683d 100644 --- a/src/leap/bitmask/core/dispatcher.py +++ b/src/leap/bitmask/core/dispatcher.py @@ -38,6 +38,10 @@ from .api import APICommand, register_method logger = Logger() +class DispatchError(Exception): + pass + + class SubCommand(object): __metaclass__ = APICommand @@ -112,6 +116,8 @@ class UserCmd(SubCommand): @register_method("{'signup': 'ok', 'user': str}") def do_CREATE(self, bonafide, *parts): + if len(parts) < 5: + raise DispatchError('Not enough parameters passed') # params are: [user, create, full_id, password, invite, autoconf] user, password, invite = parts[2], parts[3], parts[4] @@ -219,7 +225,6 @@ class WebUICmd(SubCommand): @register_method('dict') def do_STATUS(self, webui, *parts, **kw): - print 'webui', webui d = webui.do_status() return d @@ -310,7 +315,6 @@ class EventsCmd(SubCommand): self.waiting.append(d) return d - @register_method("") def _callback(self, event, *content): payload = (str(event), content) if not self.waiting: @@ -322,15 +326,35 @@ class EventsCmd(SubCommand): d.callback(payload) +class CoreCmd(SubCommand): + + label = 'core' + + @register_method("{'mem_usage': str}") + def do_STATS(self, core, *parts): + return core.do_stats() + + @register_method("{version_core': '0.0.0'}") + def do_VERSION(self, core, *parts): + return core.do_version() + + @register_method("{'mail': 'running'}") + def do_STATUS(self, core, *parts): + return core.do_status() + + @register_method("{'stop': 'ok'}") + def do_STOP(self, core, *parts): + return core.do_stop() + + class CommandDispatcher(object): __metaclass__ = APICommand - label = 'core' - def __init__(self, core): self.core = core + self.subcommand_core = CoreCmd() self.subcommand_bonafide = BonafideCmd() self.subcommand_eip = EIPCmd() self.subcommand_mail = MailCmd() @@ -338,26 +362,10 @@ class CommandDispatcher(object): self.subcommand_events = EventsCmd() self.subcommand_webui = WebUICmd() - # XXX -------------------------------------------- - # TODO move general services to another subclass - - @register_method("{'mem_usage': str}") - def do_STATS(self, *parts): - return _format_result(self.core.do_stats()) - - @register_method("{version_core': '0.0.0'}") - def do_VERSION(self, *parts): - return _format_result(self.core.do_version()) - - @register_method("{'mail': 'running'}") - def do_STATUS(self, *parts): - return _format_result(self.core.do_status()) - - @register_method("{'stop': 'ok'}") - def do_STOP(self, *parts): - return _format_result(self.core.do_stop()) - - # ----------------------------------------------- + def do_CORE(self, *parts): + d = self.subcommand_core.dispatch(self.core, *parts) + d.addCallbacks(_format_result, _format_error) + return d def do_BONAFIDE(self, *parts): bonafide = self._get_service('bonafide') @@ -446,7 +454,6 @@ class CommandDispatcher(object): def dispatch(self, msg): cmd = msg[0] - _method = getattr(self, 'do_' + cmd.upper(), None) if not _method: diff --git a/src/leap/bitmask/core/dummy.py b/src/leap/bitmask/core/dummy.py index 455756c4..2037b81f 100644 --- a/src/leap/bitmask/core/dummy.py +++ b/src/leap/bitmask/core/dummy.py @@ -22,6 +22,34 @@ import json from leap.bitmask.hooks import HookableService +class CannedData: + + class backend: + status = { + 'soledad': 'running', + 'keymanager': 'running', + 'mail': 'running', + 'eip': 'stopped', + 'backend': 'dummy'} + version = {'version_core': '0.0.1'} + stop = {'stop': 'ok'} + stats = {'mem_usage': '01 KB'} + + class bonafide: + auth = { + u'srp_token': u'deadbeef123456789012345678901234567890123', + u'uuid': u'01234567890abcde01234567890abcde'} + signup = { + 'signup': 'ok', + 'user': 'dummyuser@provider.example.org'} + list_users = { + 'userid': 'testuser', + 'authenticated': False} + logout = { + 'logout': 'ok'} + get_active_user = 'dummyuser@provider.example.org' + + class BackendCommands(object): """ @@ -30,23 +58,19 @@ class BackendCommands(object): def __init__(self, core): self.core = core + self.canned = CannedData def do_status(self): - return json.dumps( - {'soledad': 'running', - 'keymanager': 'running', - 'mail': 'running', - 'eip': 'stopped', - 'backend': 'dummy'}) + return json.dumps(self.canned.backend.stats) def do_version(self): - return {'version_core': '0.0.1'} + return self.canned.backend.version def do_stats(self): - return {'mem_usage': '01 KB'} + return self.canned.backend.stats def do_stop(self): - return {'stop': 'ok'} + return self.canned.backend.stop class mail_services(object): @@ -64,17 +88,19 @@ class mail_services(object): class BonafideService(HookableService): def __init__(self, basedir): - pass + self.canned = CannedData def do_authenticate(self, user, password): - return {u'srp_token': u'deadbeef123456789012345678901234567890123', - u'uuid': u'01234567890abcde01234567890abcde'} + return self.canned.bonafide.auth def do_signup(self, user, password): - return {'signup': 'ok', 'user': 'dummyuser@provider.example.org'} + return self.canned.bonafide.signup + + def do_list_users(self): + return self.canned.bonafide.list_users def do_logout(self, user): - return {'logout': 'ok'} + return self.canned.bonafide.logout def do_get_active_user(self): - return 'dummyuser@provider.example.org' + return self.canned.bonafide.get_active_user diff --git a/src/leap/bitmask/core/launcher.py b/src/leap/bitmask/core/launcher.py index a1c8690f..14d8e607 100644 --- a/src/leap/bitmask/core/launcher.py +++ b/src/leap/bitmask/core/launcher.py @@ -45,6 +45,7 @@ def here(module=None): def run_bitmaskd(): + # TODO --- configure where to put the logs... (get --logfile, --logdir # from bitmaskctl for (index, arg) in enumerate(sys.argv): diff --git a/src/leap/bitmask/core/service.py b/src/leap/bitmask/core/service.py index 9682c18c..c3e97f72 100644 --- a/src/leap/bitmask/core/service.py +++ b/src/leap/bitmask/core/service.py @@ -266,6 +266,7 @@ class BackendCommands(object): return {'version_core': __version__} def do_stats(self): + print "DO STATS" logger.debug('BitmaskCore Service STATS') mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss return {'mem_usage': '%s MB' % (mem / 1024)} diff --git a/src/leap/bitmask/core/web/_auth.py b/src/leap/bitmask/core/web/_auth.py index 6a5e3621..3eb4fa13 100644 --- a/src/leap/bitmask/core/web/_auth.py +++ b/src/leap/bitmask/core/web/_auth.py @@ -18,9 +18,6 @@ class WhitelistHTTPAuthSessionWrapper(HTTPAuthSessionWrapper): It doesn't apply the enforcement to routes included in a whitelist. """ - # TODO extend this to inspect the data -- so that we pass a tuple - # with the action - whitelist = (None,) def __init__(self, *args, **kw): diff --git a/src/leap/bitmask/core/web/service.py b/src/leap/bitmask/core/web/service.py index 2437d2d6..77e1c729 100644 --- a/src/leap/bitmask/core/web/service.py +++ b/src/leap/bitmask/core/web/service.py @@ -59,7 +59,13 @@ class HTTPDispatcherService(service.Service): """ API_WHITELIST = ( - '/API/bonafide/user', + '/API/core/version', + '/API/core/stats', + '/API/bonafide/user/create', + '/API/bonafide/user/authenticate', + '/API/bonafide/provider/list', + '/API/bonafide/provider/create', + '/API/bonafide/provider/read', ) def __init__(self, core, port=7070, debug=False, onion=False): -- cgit v1.2.3