From 908947395b857bb8a7b846a6784e5b61e3d154fe Mon Sep 17 00:00:00 2001 From: Tobias Frust Date: Tue, 30 Jan 2018 11:08:52 +0100 Subject: [PATCH] global: make ssh key deployment configurable --- invenio_uploadbyurl/__init__.py | 7 ++++++- invenio_uploadbyurl/config.py | 3 +++ invenio_uploadbyurl/ext.py | 17 +++++++++++++++++ invenio_uploadbyurl/proxies.py | 28 ++++++++++++++++++++++++++++ invenio_uploadbyurl/utils.py | 15 ++++++++++++++- tests/conftest.py | 8 ++++++++ 6 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 invenio_uploadbyurl/proxies.py diff --git a/invenio_uploadbyurl/__init__.py b/invenio_uploadbyurl/__init__.py index 79a5045..4cbad9d 100644 --- a/invenio_uploadbyurl/__init__.py +++ b/invenio_uploadbyurl/__init__.py @@ -21,6 +21,11 @@ """Module for invenio for server-side download from a given URL.""" from .ext import InvenioUploadByURL +from .proxies import current_uploadbyurl from .version import __version__ -__all__ = ('__version__', 'InvenioUploadByURL') +__all__ = ( + '__version__', + 'current_uploadbyurl', + 'InvenioUploadByURL', +) diff --git a/invenio_uploadbyurl/config.py b/invenio_uploadbyurl/config.py index 8b5a418..a681c0e 100644 --- a/invenio_uploadbyurl/config.py +++ b/invenio_uploadbyurl/config.py @@ -81,3 +81,6 @@ UPLOADBYURL_EMAIL_BODY_FAILED = 'Your upload failed. Please make sure ' \ 'for {filepath}. Also make sure, that the file exists. Please contact ' \ 'us, if the problem persists.' """Message body used for notification mail in case of failure.""" + +UPLOADBYURL_REMOTE_SERVERS = {} +"""Special configuration option for remote server.""" diff --git a/invenio_uploadbyurl/ext.py b/invenio_uploadbyurl/ext.py index 79d2aa0..71e4a87 100644 --- a/invenio_uploadbyurl/ext.py +++ b/invenio_uploadbyurl/ext.py @@ -23,6 +23,22 @@ from . import config from .receivers import upload_finished_receiver from .signals import upload_finished +from .utils import deploy_ssh_key, make_object + + +class _UploadByURLState(object): + """Uploady by URL state to store customized functions.""" + + def __init__(self, app): + """Initialize state.""" + self.app = app + self.deploy_handler = {} + + for remote_server, conf in app.config[ + 'UPLOADBYURL_REMOTE_SERVERS'].items(): + # add customized deploy functions + self.deploy_handler[remote_server] = make_object( + conf.get('deploy_handler', deploy_ssh_key)) class InvenioUploadByURL(object): @@ -48,6 +64,7 @@ class InvenioUploadByURL(object): else: self.redisstore = redisstore + self.state = _UploadByURLState(app) app.extensions['invenio-uploadbyurl'] = self self.register_signals(app) diff --git a/invenio_uploadbyurl/proxies.py b/invenio_uploadbyurl/proxies.py new file mode 100644 index 0000000..3908fec --- /dev/null +++ b/invenio_uploadbyurl/proxies.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# +# This file is part of RODARE. +# Copyright (C) 2017 HZDR. +# +# RODARE is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# RODARE 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with RODARE; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307, USA. + +"""Proxy to the state object.""" + +from flask import current_app +from werkzeug.local import LocalProxy + +current_uploadbyurl = LocalProxy( + lambda: current_app.extensions['invenio-uploadbyurl'].state +) diff --git a/invenio_uploadbyurl/utils.py b/invenio_uploadbyurl/utils.py index 4e86b36..8e4a948 100644 --- a/invenio_uploadbyurl/utils.py +++ b/invenio_uploadbyurl/utils.py @@ -24,13 +24,16 @@ from datetime import date from io import StringIO import paramiko +import six from flask import current_app, flash from flask_login import current_user from invenio_accounts.models import User from invenio_db import db from werkzeug.local import LocalProxy +from werkzeug.utils import import_string from .models import RemoteServer, SSHKey +from .proxies import current_uploadbyurl _redisstore = LocalProxy( lambda: current_app.extensions['invenio-uploadbyurl'].redisstore) @@ -150,7 +153,8 @@ def connect_user_and_server(remote, username, password): prv, pub = generate_rsa_key() # deploy SSH key to server try: - deploy_ssh_key(pub, remote.server_address, username, password) + current_uploadbyurl.deploy_handler.get(remote.name, deploy_ssh_key)( + pub, remote.server_address, username, password) key = SSHKey.create(private_key=prv, username=username, user=current_user, remote_server=remote, keytype='rsa') @@ -189,3 +193,12 @@ def notification_mail(user_id, failed=False, filepath=None): ) send_email.delay(msg.__dict__) + + +def make_object(value, default=None): + """Make a handler to configure specific functions.""" + if isinstance(value, six.string_types): + return import_string(value) + else: + return value + return default diff --git a/tests/conftest.py b/tests/conftest.py index 988a645..381d75c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -99,6 +99,13 @@ def base_app(instance_path): @pytest.yield_fixture() def app(base_app): """Flask application fixture.""" + base_app.config.update( + UPLOADBYURL_REMOTE_SERVERS={ + 'foo': { + 'deploy_handler': 'invenio_uploadbyurl.utils:deploy_ssh_key', + } + } + ) InvenioAccounts(base_app) InvenioAccess(base_app) InvenioAssets(base_app) @@ -106,6 +113,7 @@ def app(base_app): InvenioMail(base_app) base_app.register_blueprint(accounts_blueprint) base_app.register_blueprint(files_rest_blueprint) + InvenioUploadByURL(base_app) base_app.register_blueprint(blueprint) with base_app.app_context(): -- GitLab