From 26b85d8e523f2b6aafbe18132efcd617ae892228 Mon Sep 17 00:00:00 2001 From: Duda Dornelles Date: Tue, 27 Jan 2015 16:08:03 -0200 Subject: #237 #232 #196 syncing user data once before starting the UA. Displaying a loading screen in the meantime. The initial sync will make sure the user has a single key pair --- service/pixelated/config/__init__.py | 71 ++++++++++++++++++++++++++ service/pixelated/config/app.py | 25 +++++++++ service/pixelated/config/app_factory.py | 15 +++--- service/pixelated/config/config_ua.py | 48 +++++++++++++++++ service/pixelated/config/credentials_prompt.py | 8 --- service/pixelated/config/debug.py | 40 +++++++++++++++ service/pixelated/config/dispatcher.py | 38 ++++++++++++++ service/pixelated/config/events_server.py | 21 ++++++++ service/pixelated/config/leap_cert.py | 21 ++++++++ service/pixelated/config/loading_page.py | 54 ++++++++++++++++++++ service/pixelated/config/register.py | 25 +++++++++ service/pixelated/config/soledad.py | 27 ++++++++++ 12 files changed, 377 insertions(+), 16 deletions(-) create mode 100644 service/pixelated/config/app.py create mode 100644 service/pixelated/config/config_ua.py delete mode 100644 service/pixelated/config/credentials_prompt.py create mode 100644 service/pixelated/config/debug.py create mode 100644 service/pixelated/config/dispatcher.py create mode 100644 service/pixelated/config/events_server.py create mode 100644 service/pixelated/config/leap_cert.py create mode 100644 service/pixelated/config/loading_page.py create mode 100644 service/pixelated/config/register.py create mode 100644 service/pixelated/config/soledad.py (limited to 'service/pixelated/config') diff --git a/service/pixelated/config/__init__.py b/service/pixelated/config/__init__.py index e69de29b..ce720c80 100644 --- a/service/pixelated/config/__init__.py +++ b/service/pixelated/config/__init__.py @@ -0,0 +1,71 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +from functools import partial +import sys + +from pixelated.config.app import App +from pixelated.config import app_factory +from pixelated.config.args import parse as parse_args +from pixelated.config.config_ua import config_user_agent +from pixelated.config.dispatcher import config_dispatcher +from pixelated.config.events_server import init_events_server +from pixelated.config.loading_page import loading +from pixelated.config.register import register +from pixelated.config.debug import init_debugger +from pixelated.config.leap_cert import init_leap_cert +from pixelated.config.soledad import init_soledad_and_user_key +from twisted.internet import reactor +from twisted.internet.threads import deferToThread + + +def initialize(): + args = parse_args() + app = App() + + init_debugger(args) + init_leap_cert(args) + + if args.register: + register(*args.register[::-1]) + sys.exit(0) + + if args.dispatcher or args.dispatcher_stdin: + config_dispatcher(app, args) + else: + config_user_agent(app, args) + + init_events_server() + + def load_app(): + # welcome to deferred hell. Or maybe you'll be welcomed later, who knows. + loading_app = loading(args) + + def init_soledad(): + return init_soledad_and_user_key(app) + + def stop_loading_app(leap_session): + d = loading_app.stopListening() + d.addCallback(partial(start_user_agent_app, leap_session)) + + def start_user_agent_app(leap_session, _): + app_factory.create_app(app, args, leap_session) + + d = deferToThread(init_soledad) + d.addCallback(stop_loading_app) + + reactor.callWhenRunning(load_app) + reactor.run() diff --git a/service/pixelated/config/app.py b/service/pixelated/config/app.py new file mode 100644 index 00000000..6dea9baa --- /dev/null +++ b/service/pixelated/config/app.py @@ -0,0 +1,25 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + + +class App: + + def __getitem__(self, item): + return self.config[item] + + def __init__(self): + self.resource = None + self.config = {} diff --git a/service/pixelated/config/app_factory.py b/service/pixelated/config/app_factory.py index ebae465d..f2810e08 100644 --- a/service/pixelated/config/app_factory.py +++ b/service/pixelated/config/app_factory.py @@ -89,12 +89,14 @@ def look_for_user_key_and_create_if_cant_find(leap_session): def stop_incoming_mail_fetcher(reactor_stop_function, leap_session): def wrapper(): leap_session.stop_background_jobs() + reactor.threadpool.stop() reactor_stop_function() return wrapper -def init_app(app, leap_home): - leap_session = init_leap_session(app, leap_home) +def init_app(app, leap_home, leap_session): + leap_session.start_background_jobs() + soledad_querier = SoledadQuerier(soledad=leap_session.account._soledad) tag_service = TagService() @@ -118,18 +120,17 @@ def init_app(app, leap_home): register(signal=proto.SOLEDAD_DONE_DATA_SYNC, uid=CREATE_KEYS_IF_KEYS_DONT_EXISTS_CALLBACK, callback=look_for_user_key_and_create_if_cant_find(leap_session)) + reactor.threadpool.adjustPoolsize(20, 40) reactor.stop = stop_incoming_mail_fetcher(reactor.stop, leap_session) -def create_app(app, args): +def create_app(app, args, leap_session): app.resource = RootResource() + init_app(app, args.home, leap_session) if args.sslkey and args.sslcert: listen_with_ssl(app, args) else: listen_without_ssl(app, args) - reactor.suggestThreadPoolSize(20) - reactor.callWhenRunning(lambda: init_app(app, args.home)) - reactor.run() def listen_without_ssl(app, args): @@ -151,8 +152,6 @@ def _ssl_options(args): def listen_with_ssl(app, args): reactor.listenSSL(args.port, Site(app.resource), _ssl_options(args), interface=args.host) - return reactor - class RedirectToSSL(resource.Resource): isLeaf = True diff --git a/service/pixelated/config/config_ua.py b/service/pixelated/config/config_ua.py new file mode 100644 index 00000000..50abca1f --- /dev/null +++ b/service/pixelated/config/config_ua.py @@ -0,0 +1,48 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +import ConfigParser +import os +import getpass + + +def parse_config_from_file(config_file): + config_parser = ConfigParser.ConfigParser() + config_file_path = os.path.abspath(os.path.expanduser(config_file)) + config_parser.read(config_file_path) + provider, user, password = \ + config_parser.get('pixelated', 'leap_server_name'), \ + config_parser.get('pixelated', 'leap_username'), \ + config_parser.get('pixelated', 'leap_password') + + # TODO: add error messages in case one of the parameters are empty + return provider, user, password + + +def prompt_for_credentials(): + provider = raw_input('Which provider do you want to connect to:\n') + username = raw_input('What\'s your username registered on the provider:\n') + password = getpass.getpass('Type your password:\n') + return provider, username, password + + +def config_user_agent(app, args): + config_file = args.config + provider, user, password = parse_config_from_file(config_file) if config_file else prompt_for_credentials() + + app.config['LEAP_SERVER_NAME'] = provider + app.config['LEAP_USERNAME'] = user + app.config['LEAP_PASSWORD'] = password diff --git a/service/pixelated/config/credentials_prompt.py b/service/pixelated/config/credentials_prompt.py deleted file mode 100644 index de4095b0..00000000 --- a/service/pixelated/config/credentials_prompt.py +++ /dev/null @@ -1,8 +0,0 @@ -import getpass - - -def run(): - provider = raw_input('Which provider do you want to connect to:\n') - username = raw_input('What\'s your username registered on the provider:\n') - password = getpass.getpass('Type your password:\n') - return provider, username, password diff --git a/service/pixelated/config/debug.py b/service/pixelated/config/debug.py new file mode 100644 index 00000000..d91d3a34 --- /dev/null +++ b/service/pixelated/config/debug.py @@ -0,0 +1,40 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +import logging +import sys +import os +from twisted.python import log + + +def init_debugger(args): + debug_enabled = args.debug or os.environ.get('DEBUG', False) + log.startLogging(sys.stdout) + + if debug_enabled: + logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', + datefmt='%m-%d %H:%M', + filename='/tmp/leap.log', + filemode='w') # define a Handler which writes INFO messages or higher to the sys.stderr + + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + return debug_enabled diff --git a/service/pixelated/config/dispatcher.py b/service/pixelated/config/dispatcher.py new file mode 100644 index 00000000..0a4805dc --- /dev/null +++ b/service/pixelated/config/dispatcher.py @@ -0,0 +1,38 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +import json +import sys +import os + + +def config_dispatcher(app, args): + + def fetch_credentials_from_dispatcher(filename): + if not os.path.exists(filename): + print('The credentials pipe doesn\'t exist') + sys.exit(1) + with open(filename, 'r') as fifo: + return json.loads(fifo.read()) + + def fetch_credentials_from_dispatcher_stdin(): + return json.loads(sys.stdin.read()) + + config = fetch_credentials_from_dispatcher(args.dispatcher) if args.dispatcher else fetch_credentials_from_dispatcher_stdin() + + app.config['LEAP_SERVER_NAME'] = config['leap_provider_hostname'] + app.config['LEAP_USERNAME'] = config['user'] + app.config['LEAP_PASSWORD'] = config['password'] diff --git a/service/pixelated/config/events_server.py b/service/pixelated/config/events_server.py new file mode 100644 index 00000000..121ebcab --- /dev/null +++ b/service/pixelated/config/events_server.py @@ -0,0 +1,21 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +from leap.common.events import server as events_server + + +def init_events_server(): + events_server.ensure_server(port=8090) diff --git a/service/pixelated/config/leap_cert.py b/service/pixelated/config/leap_cert.py new file mode 100644 index 00000000..9e6dfc01 --- /dev/null +++ b/service/pixelated/config/leap_cert.py @@ -0,0 +1,21 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +import pixelated.bitmask_libraries.certs as certs + + +def init_leap_cert(args): + certs.LEAP_CERT = args.leap_cert diff --git a/service/pixelated/config/loading_page.py b/service/pixelated/config/loading_page.py new file mode 100644 index 00000000..b8a95f57 --- /dev/null +++ b/service/pixelated/config/loading_page.py @@ -0,0 +1,54 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +import os +from twisted.internet import reactor +from twisted.internet.threads import deferToThread +from twisted.web.resource import Resource +from twisted.web.server import Site, NOT_DONE_YET +from twisted.web.static import File + + +class LoadingResource(Resource): + + def __init__(self): + Resource.__init__(self) + self._path = os.path.dirname(os.path.abspath(__file__)) + self.putChild('assets', File(os.path.join(self._path, '..', 'assets'))) + + def render_GET(self, request): + + def open_html(): + return open(os.path.join(self._path, '..', 'assets', 'Interstitial.html')).read() + + def close_request(html): + request.responseHeaders.addRawHeader("Connection", "close") + request.write(html) + request.finish() + + d = deferToThread(open_html) + d.addCallback(close_request) + + return NOT_DONE_YET + + def getChild(self, path, request): + if path == '': + return self + return Resource.getChild(self, path, request) + + +def loading(args): + return reactor.listenTCP(args.port, Site(LoadingResource()), interface=args.host) diff --git a/service/pixelated/config/register.py b/service/pixelated/config/register.py new file mode 100644 index 00000000..3f93aa8d --- /dev/null +++ b/service/pixelated/config/register.py @@ -0,0 +1,25 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +from pixelated.bitmask_libraries.leap_srp import LeapAuthException +from pixelated.bitmask_libraries.register import register_new_user + + +def register(username, server_name): + try: + register_new_user(username, server_name) + except LeapAuthException: + print('User already exists') diff --git a/service/pixelated/config/soledad.py b/service/pixelated/config/soledad.py new file mode 100644 index 00000000..3a033f09 --- /dev/null +++ b/service/pixelated/config/soledad.py @@ -0,0 +1,27 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +from pixelated.bitmask_libraries.session import open as open_leap_session + + +def init_soledad_and_user_key(app): + leap_session = open_leap_session(app['LEAP_USERNAME'], + app['LEAP_PASSWORD'], + app['LEAP_SERVER_NAME']) + soledad = leap_session.soledad_session.soledad + soledad.sync(defer_decryption=False) + leap_session.nicknym.generate_openpgp_key() + return leap_session -- cgit v1.2.3