From 1050c9857ae02ed26c2ec84f133e3d40721f44cc Mon Sep 17 00:00:00 2001 From: Aditya Toshniwal Date: Mon, 1 Jun 2020 11:22:38 +0530 Subject: [PATCH] Fixed an issue when dumping servers from a desktop pgAdmin app by providing an option '--sqlite-path'. Fixes #5521 --- docs/en_US/import_export_servers.rst | 19 ++++++- docs/en_US/release_notes_4_23.rst | 1 + web/pgadmin/__init__.py | 49 +++++++++++----- web/setup.py | 85 +++++++++++++++++++--------- 4 files changed, 110 insertions(+), 44 deletions(-) diff --git a/docs/en_US/import_export_servers.rst b/docs/en_US/import_export_servers.rst index 010281b2e..3d8e04ff5 100644 --- a/docs/en_US/import_export_servers.rst +++ b/docs/en_US/import_export_servers.rst @@ -23,7 +23,11 @@ the ``--dump-servers`` command line option, followed by the name (and if require path) to the desired output file. By default, servers owned by the desktop mode user will be dumped (pgadmin4@pgadmin.org by default - see the DESKTOP_USER setting in ``config.py``). This can be overridden with the ``--user`` command -line option. For example: +line option. There can be multiple configuations of pgAdmin on the same system. +To dump the servers from specific pgAdmin config DB file, ``--sqlite-path`` option +can be used. It is also recommended to use this option when running pgAdmin in +desktop mode. By default SQLITE_PATH setting in ``config.py`` is taken. +For example: .. code-block:: bash @@ -33,6 +37,10 @@ line option. For example: /path/to/python /path/to/setup.py --dump-servers output_file.json --user user@example.com + # to specify a pgAdmin config DB file: + + /path/to/python /path/to/setup.py --dump-servers output_file.json --sqlite-path /path/to/pgadmin4.db + To export only certain servers, use the ``--servers`` option and list one or more server IDs. For example: @@ -48,7 +56,10 @@ the ``--load-servers`` command line option, followed by the name (and if require path) of the JSON file containing the server definitions. Servers will be owned by the desktop mode user (pgadmin4@pgadmin.org by default - see the DESKTOP_USER setting in ``config.py``). This can be overridden with the ``--user`` command -line option. For example: +line option. There can be multiple configuations of pgAdmin on the same system. +To load the servers into a specific pgAdmin config DB file, ``--sqlite-path`` option +can be used. It is also recommended to use this option when running pgAdmin in +desktop mode. By default SQLITE_PATH setting in ``config.py`` is taken. For example: .. code-block:: bash @@ -58,6 +69,10 @@ line option. For example: /path/to/python /path/to/setup.py --load-servers input_file.json --user user@example.com + # to specify a pgAdmin config DB file: + + /path/to/python /path/to/setup.py --load-servers input_file.json --sqlite-path /path/to/pgadmin4.db + If any Servers are defined with a Server Group that is not already present in the configuration database, the required Group will be created. diff --git a/docs/en_US/release_notes_4_23.rst b/docs/en_US/release_notes_4_23.rst index 5635675f7..157ffc1cf 100644 --- a/docs/en_US/release_notes_4_23.rst +++ b/docs/en_US/release_notes_4_23.rst @@ -19,4 +19,5 @@ Bug fixes | `Issue #5416 `_ - Ensure that the query tool panel gets closed when clicking on the 'Don't Save' button. | `Issue #5465 `_ - Fixed an issue where the Edge browser version is showing wrong and warning message gets displayed. +| `Issue #5521 `_ - Fixed an issue when dumping servers from a desktop pgAdmin app by providing an option '--sqlite-path'. | `Issue #5539 `_ - Fixed typo in exception keyword. \ No newline at end of file diff --git a/web/pgadmin/__init__.py b/web/pgadmin/__init__.py index 08e21801e..477312c97 100644 --- a/web/pgadmin/__init__.py +++ b/web/pgadmin/__init__.py @@ -182,6 +182,11 @@ def create_app(app_name=None): if not app_name: app_name = config.APP_NAME + # Check if app is created for CLI operations or Web + cli_mode = False + if app_name.endswith('-cli'): + cli_mode = True + # Only enable password related functionality in server mode. if config.SERVER_MODE is True: # Some times we need to access these config params where application @@ -236,16 +241,17 @@ def create_app(app_name=None): config.MASTER_PASSWORD_REQUIRED = False config.UPGRADE_CHECK_ENABLED = False - # Ensure the various working directories exist - from pgadmin.setup import create_app_data_directory, db_upgrade - create_app_data_directory(config) + if not cli_mode: + # Ensure the various working directories exist + from pgadmin.setup import create_app_data_directory + create_app_data_directory(config) - # File logging - fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8') - fh.setLevel(config.FILE_LOG_LEVEL) - fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT)) - app.logger.addHandler(fh) - logger.addHandler(fh) + # File logging + fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8') + fh.setLevel(config.FILE_LOG_LEVEL) + fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT)) + app.logger.addHandler(fh) + logger.addHandler(fh) # Console logging ch = logging.StreamHandler() @@ -320,11 +326,21 @@ def create_app(app_name=None): with app.app_context(): # Run migration for the first time i.e. create database from config import SQLITE_PATH + from pgadmin.setup import db_upgrade # If version not available, user must have aborted. Tables are not # created and so its an empty db if not os.path.exists(SQLITE_PATH) or get_version() == -1: - db_upgrade(app) + # If running in cli mode then don't try to upgrade, just raise + # the exception + if not cli_mode: + db_upgrade(app) + else: + if not os.path.exists(SQLITE_PATH): + raise FileNotFoundError( + 'SQLite database file "' + SQLITE_PATH + + '" does not exists.') + raise Exception('Specified SQLite database file is not valid.') else: schema_version = get_version() @@ -343,8 +359,10 @@ def create_app(app_name=None): Mail(app) - import pgadmin.utils.paths as paths - paths.init_app(app) + # Don't bother paths when running in cli mode + if not cli_mode: + import pgadmin.utils.paths as paths + paths.init_app(app) # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role) @@ -382,9 +400,10 @@ def create_app(app_name=None): app.permanent_session_lifetime = timedelta( days=config.SESSION_EXPIRATION_TIME) - app.session_interface = create_session_interface( - app, config.SESSION_SKIP_PATHS - ) + if not cli_mode: + app.session_interface = create_session_interface( + app, config.SESSION_SKIP_PATHS + ) # Make the Session more secure against XSS & CSRF when running in web mode if config.SERVER_MODE and config.ENHANCED_COOKIE_PROTECTION: diff --git a/web/setup.py b/web/setup.py index 6bb8527a6..14bd5f9cc 100644 --- a/web/setup.py +++ b/web/setup.py @@ -56,15 +56,25 @@ def dump_servers(args): Args: args (ArgParser): The parsed command line options """ - app = create_app() + + # What user? + if args.user is not None: + dump_user = args.user + else: + dump_user = config.DESKTOP_USER + + # And the sqlite path + if args.sqlite_path is not None: + config.SQLITE_PATH = args.sqlite_path + + print('----------') + print('Dumping servers with:') + print('User:', dump_user) + print('SQLite pgAdmin config:', config.SQLITE_PATH) + print('----------') + + app = create_app(config.APP_NAME + '-cli') with app.app_context(): - - # What user? - if args.user is not None: - dump_user = args.user - else: - dump_user = config.DESKTOP_USER - user = User.query.filter_by(email=dump_user).first() if user is None: @@ -150,6 +160,23 @@ def load_servers(args): Args: args (ArgParser): The parsed command line options """ + + # What user? + if args.user is not None: + load_user = args.user + else: + load_user = config.DESKTOP_USER + + # And the sqlite path + if args.sqlite_path is not None: + config.SQLITE_PATH = args.sqlite_path + + print('----------') + print('Loading servers with:') + print('User:', load_user) + print('SQLite pgAdmin config:', config.SQLITE_PATH) + print('----------') + try: with open(args.load_servers) as f: data = json.load(f) @@ -164,20 +191,13 @@ def load_servers(args): f.close() - app = create_app() + app = create_app(config.APP_NAME + '-cli') with app.app_context(): - - # What user? - if args.user is not None: - dump_user = args.user - else: - dump_user = config.DESKTOP_USER - - user = User.query.filter_by(email=dump_user).first() + user = User.query.filter_by(email=load_user).first() if user is None: print("The specified user ID (%s) could not be found." % - dump_user) + load_user) sys.exit(1) user_id = user.id @@ -377,21 +397,26 @@ if __name__ == '__main__': parser = argparse.ArgumentParser(description='Setup the pgAdmin config DB') - imp_exp_group = parser.add_mutually_exclusive_group(required=False) - - exp_group = imp_exp_group.add_argument_group('Dump server config') + exp_group = parser.add_argument_group('Dump server config') exp_group.add_argument('--dump-servers', metavar="OUTPUT_FILE", help='Dump the servers in the DB', required=False) exp_group.add_argument('--servers', metavar="SERVERS", nargs='*', help='One or more servers to dump', required=False) - imp_group = imp_exp_group.add_argument_group('Load server config') + imp_group = parser.add_argument_group('Load server config') imp_group.add_argument('--load-servers', metavar="INPUT_FILE", help='Load servers into the DB', required=False) - imp_exp_group.add_argument('--user', metavar="USER_NAME", - help='Dump/load servers for the specified ' - 'username', required=False) + # Common args + parser.add_argument('--sqlite-path', metavar="PATH", + help='Dump/load with the specified pgAdmin config DB' + ' file. This is particularly helpful when there' + ' are multiple pgAdmin configurations. It is also' + ' recommended to use this option when running' + ' pgAdmin in desktop mode.', required=False) + parser.add_argument('--user', metavar="USER_NAME", + help='Dump/load servers for the specified username', + required=False) args, extra = parser.parse_known_args() @@ -402,8 +427,14 @@ if __name__ == '__main__': # What to do? if args.dump_servers is not None: - dump_servers(args) + try: + dump_servers(args) + except Exception as e: + print(str(e)) elif args.load_servers is not None: - load_servers(args) + try: + load_servers(args) + except Exception as e: + print(str(e)) else: setup_db()