From 8ae8fea6d2c4198af96e7bf380c2f5c108a32ed9 Mon Sep 17 00:00:00 2001 From: Pradip Parkale Date: Thu, 22 Apr 2021 17:29:04 +0530 Subject: [PATCH] Ensure that Backup and Restore should work on shared servers as some cases were failing due to initial changes. Fixes #6385 --- docs/en_US/release_notes.rst | 1 + docs/en_US/release_notes_5_2.rst | 3 +- docs/en_US/release_notes_5_3.rst | 20 +++++++++++ web/migrations/versions/c6974f64df08_.py | 28 +++++++++++++++ .../browser/server_groups/servers/__init__.py | 5 +-- web/pgadmin/model/__init__.py | 7 +++- web/pgadmin/tools/backup/__init__.py | 34 ++++--------------- web/pgadmin/tools/maintenance/__init__.py | 26 +++----------- web/pgadmin/tools/restore/__init__.py | 33 ++++-------------- web/pgadmin/utils/__init__.py | 11 ++++++ 10 files changed, 87 insertions(+), 81 deletions(-) create mode 100644 docs/en_US/release_notes_5_3.rst create mode 100644 web/migrations/versions/c6974f64df08_.py diff --git a/docs/en_US/release_notes.rst b/docs/en_US/release_notes.rst index 25570b536..174b377b9 100644 --- a/docs/en_US/release_notes.rst +++ b/docs/en_US/release_notes.rst @@ -11,6 +11,7 @@ notes for it. .. toctree:: :maxdepth: 1 + release_notes_5_3 release_notes_5_2 release_notes_5_1 release_notes_5_0 diff --git a/docs/en_US/release_notes_5_2.rst b/docs/en_US/release_notes_5_2.rst index 4afdbd395..3da7d9b8a 100644 --- a/docs/en_US/release_notes_5_2.rst +++ b/docs/en_US/release_notes_5_2.rst @@ -23,7 +23,7 @@ Bug fixes | `Issue #5908 `_ - Fixed an issue where shortcut keys are not working with manage macro. | `Issue #6076 `_ - Fixed an issue where correct error not thrown while importing servers and JSON file has incorrect/insufficient keys. | `Issue #6082 `_ - Ensure that the user should not be to change the connection when a long query is running. -| `Issue #6106 `_ - Fixed flickering issue of the input box on check constraints. +| `Issue #6107 `_ - Fixed flickering issue of the input box on check constraints. | `Issue #6161 `_ - Fixed an issue where the cursor shifts its focus to the wrong window for all the query tool related model dialogs. | `Issue #6220 `_ - Corrected the syntax for 'CREATE TRIGGER', use 'EXECUTE FUNCTION' instead of 'EXECUTE PROCEDURE' from v11 onwards. | `Issue #6274 `_ - Ensure that the strings in the LDAP auth module are translatable. @@ -40,4 +40,3 @@ Bug fixes | `Issue #6375 `_ - Fixed an issue where users are unable to see data of the partitions using the View/Edit data option. | `Issue #6376 `_ - Fixed an issue where a connection warning should be displayed on the user clicks on explain or explain analyze and the database server is disconnected from the browser tree. | `Issue #6379 `_ - Fixed an issue where foreign data wrapper properties are not visible if the host option contains two host addresses. -| `Issue #6385 `_ - Ensure that Backup and Restore should work on shared servers. diff --git a/docs/en_US/release_notes_5_3.rst b/docs/en_US/release_notes_5_3.rst new file mode 100644 index 000000000..570f01348 --- /dev/null +++ b/docs/en_US/release_notes_5_3.rst @@ -0,0 +1,20 @@ +************ +Version 5.3 +************ + +Release date: 2021-05-20 + +This release contains a number of bug fixes and new features since the release of pgAdmin4 5.2. + +New features +************ + + +Housekeeping +************ + + +Bug fixes +********* + +| `Issue #6385 `_ - Ensure that Backup and Restore should work on shared servers. diff --git a/web/migrations/versions/c6974f64df08_.py b/web/migrations/versions/c6974f64df08_.py new file mode 100644 index 000000000..277853631 --- /dev/null +++ b/web/migrations/versions/c6974f64df08_.py @@ -0,0 +1,28 @@ + +"""empty message + +Revision ID: c6974f64df08 +Revises: a39bd015b644 +Create Date: 2021-04-22 10:06:21.282770 + +""" +from pgadmin.model import db + + + +# revision identifiers, used by Alembic. +revision = 'c6974f64df08' +down_revision = 'a39bd015b644' +branch_labels = None +depends_on = None + + +def upgrade(): + db.engine.execute( + 'ALTER TABLE sharedserver ADD COLUMN osid INTEGER' + ) + + +def downgrade(): + # pgAdmin only upgrades, downgrade not implemented. + pass diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py index 00025196b..233ea07f8 100644 --- a/web/pgadmin/browser/server_groups/servers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/__init__.py @@ -339,6 +339,7 @@ class ServerModule(sg.ServerGroupPluginModule): db.session.rollback() user = User.query.filter_by(id=data.user_id).first() shared_server = SharedServer( + osid=data.id, user_id=current_user.id, server_owner=user.username, servergroup_id=gid, @@ -388,14 +389,14 @@ class ServerModule(sg.ServerGroupPluginModule): """ shared_server = SharedServer.query.filter_by( name=server.name, user_id=current_user.id, - servergroup_id=gid).first() + servergroup_id=gid, osid=server.id).first() if shared_server is None: ServerModule.create_shared_server(server, gid) shared_server = SharedServer.query.filter_by( name=server.name, user_id=current_user.id, - servergroup_id=gid).first() + servergroup_id=gid, osid=server.id).first() return shared_server diff --git a/web/pgadmin/model/__init__.py b/web/pgadmin/model/__init__.py index d1f498181..d849b8c26 100644 --- a/web/pgadmin/model/__init__.py +++ b/web/pgadmin/model/__init__.py @@ -29,7 +29,7 @@ from flask_sqlalchemy import SQLAlchemy # ########################################################################## -SCHEMA_VERSION = 27 +SCHEMA_VERSION = 28 ########################################################################## # @@ -361,6 +361,11 @@ class SharedServer(db.Model): __tablename__ = 'sharedserver' id = db.Column(db.Integer, primary_key=True) + osid = db.Column( + db.Integer, + db.ForeignKey('server.id'), + nullable=False + ) user_id = db.Column( db.Integer, db.ForeignKey(USER_ID) diff --git a/web/pgadmin/tools/backup/__init__.py b/web/pgadmin/tools/backup/__init__.py index aacb2e5d4..2e166b5b4 100644 --- a/web/pgadmin/tools/backup/__init__.py +++ b/web/pgadmin/tools/backup/__init__.py @@ -20,7 +20,7 @@ from flask_babelex import gettext as _ from flask_security import login_required, current_user from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc from pgadmin.utils import PgAdminModule, get_storage_directory, html, \ - fs_short_path, document_dir, does_utility_exist + fs_short_path, document_dir, does_utility_exist, get_server from pgadmin.utils.ajax import make_json_response, bad_request from config import PG_DEFAULT_DRIVER @@ -115,15 +115,7 @@ class BackupMessage(IProcessDesc): self.cmd += cmd_arg(arg) def get_server_details(self): - if Server.query.filter_by(id=self.sid, - user_id=current_user.id).first(): - s = Server.query.filter_by( - id=self.sid, user_id=current_user.id - ).first() - else: - s = SharedServer.query.filter_by( - id=self.sid, user_id=current_user.id - ).first() + s = get_server(self.sid) from pgadmin.utils.driver import get_driver driver = get_driver(PG_DEFAULT_DRIVER) @@ -422,14 +414,7 @@ def create_backup_objects_job(sid): return bad_request(errormsg=str(e)) # Fetch the server details like hostname, port, roles etc - if Server.query.filter_by(id=sid, user_id=current_user.id).first(): - server = Server.query.filter_by( - id=sid, user_id=current_user.id - ).first() - else: - server = SharedServer.query.filter_by( - id=sid, user_id=current_user.id - ).first() + server = get_server(sid) if server is None: return make_json_response( @@ -474,7 +459,7 @@ def create_backup_objects_job(sid): escaped_args.append(data['database']) p = BatchProcess( desc=BackupMessage( - BACKUP.OBJECT, sid, bfile, + BACKUP.OBJECT, server.id, bfile, *args, database=data['database'] ), @@ -485,7 +470,7 @@ def create_backup_objects_job(sid): desc=BackupMessage( BACKUP.SERVER if backup_obj_type != 'globals' else BACKUP.GLOBALS, - sid, bfile, + server.id, bfile, *args ), cmd=utility, args=escaped_args @@ -531,14 +516,7 @@ def check_utility_exists(sid, backup_obj_type): Returns: None """ - if Server.query.filter_by(id=sid, user_id=current_user.id).first(): - server = Server.query.filter_by( - id=sid, user_id=current_user.id - ).first() - else: - server = SharedServer.query.filter_by( - id=sid, user_id=current_user.id - ).first() + server = get_server(sid) if server is None: return make_json_response( diff --git a/web/pgadmin/tools/maintenance/__init__.py b/web/pgadmin/tools/maintenance/__init__.py index 160573a1c..378b00020 100644 --- a/web/pgadmin/tools/maintenance/__init__.py +++ b/web/pgadmin/tools/maintenance/__init__.py @@ -15,7 +15,7 @@ from flask import url_for, Response, render_template, request, current_app from flask_babelex import gettext as _ from flask_security import login_required, current_user from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc -from pgadmin.utils import PgAdminModule, html, does_utility_exist +from pgadmin.utils import PgAdminModule, html, does_utility_exist, get_server from pgadmin.utils.ajax import bad_request, make_json_response from pgadmin.utils.driver import get_driver @@ -209,14 +209,8 @@ def create_maintenance_job(sid, did): index_name = get_index_name(data) # Fetch the server details like hostname, port, roles etc - if Server.query.filter_by(id=sid, user_id=current_user.id).first(): - server = Server.query.filter_by( - id=sid, user_id=current_user.id - ).first() - else: - server = SharedServer.query.filter_by( - id=sid, user_id=current_user.id - ).first() + + server = get_server(sid) if server is None: return make_json_response( @@ -263,7 +257,7 @@ def create_maintenance_job(sid, did): try: p = BatchProcess( - desc=Message(sid, data, query), + desc=Message(server.id, data, query), cmd=utility, args=args ) manager.export_password_env(p.id) @@ -306,18 +300,8 @@ def check_utility_exists(sid): Returns: None """ - # server = Server.query.filter_by( - # id=sid, user_id=current_user.id - # ).first() - if Server.query.filter_by(id=sid, user_id=current_user.id).first(): - server = Server.query.filter_by( - id=sid, user_id=current_user.id - ).first() - else: - server = SharedServer.query.filter_by( - id=sid, user_id=current_user.id - ).first() + server = get_server(sid) if server is None: return make_json_response( diff --git a/web/pgadmin/tools/restore/__init__.py b/web/pgadmin/tools/restore/__init__.py index 3bb9a9c5d..94fac8046 100644 --- a/web/pgadmin/tools/restore/__init__.py +++ b/web/pgadmin/tools/restore/__init__.py @@ -18,7 +18,7 @@ from flask_babelex import gettext as _ from flask_security import login_required, current_user from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc from pgadmin.utils import PgAdminModule, get_storage_directory, html, \ - fs_short_path, document_dir, does_utility_exist + fs_short_path, document_dir, does_utility_exist, get_server from pgadmin.utils.ajax import make_json_response, bad_request from config import PG_DEFAULT_DRIVER @@ -87,16 +87,9 @@ class RestoreMessage(IProcessDesc): self.cmd += cmd_arg(arg) def get_server_details(self): + # Fetch the server details like hostname, port, roles etc - if Server.query.filter_by(id=self.sid, - user_id=current_user.id).first(): - s = Server.query.filter_by( - id=self.sid, user_id=current_user.id - ).first() - else: - s = SharedServer.query.filter_by( - id=self.sid, user_id=current_user.id - ).first() + s = get_server(self.sid) from pgadmin.utils.driver import get_driver driver = get_driver(PG_DEFAULT_DRIVER) @@ -215,14 +208,7 @@ def _connect_server(sid): :param sid: Server ID. :return: if not error occurred then return connection data. """ - if Server.query.filter_by(id=sid, user_id=current_user.id).first(): - server = Server.query.filter_by( - id=sid, user_id=current_user.id - ).first() - else: - server = SharedServer.query.filter_by( - id=sid, user_id=current_user.id - ).first() + server = get_server(sid) if server is None: return make_json_response( @@ -430,7 +416,7 @@ def create_restore_job(sid): try: p = BatchProcess( desc=RestoreMessage( - sid, + server.id, data['file'].encode('utf-8') if hasattr( data['file'], 'encode' ) else data['file'], @@ -477,14 +463,7 @@ def check_utility_exists(sid): None """ # Fetch the server details like hostname, port, roles etc - if Server.query.filter_by(id=sid, user_id=current_user.id).first(): - server = Server.query.filter_by( - id=sid, user_id=current_user.id - ).first() - else: - server = SharedServer.query.filter_by( - id=sid, user_id=current_user.id - ).first() + server = get_server(sid) if server is None: return make_json_response( diff --git a/web/pgadmin/utils/__init__.py b/web/pgadmin/utils/__init__.py index 83659a653..705e7d991 100644 --- a/web/pgadmin/utils/__init__.py +++ b/web/pgadmin/utils/__init__.py @@ -19,6 +19,7 @@ from threading import Lock from .paths import get_storage_directory from .preferences import Preferences +from pgadmin.model import Server, SharedServer class PgAdminModule(Blueprint): @@ -278,6 +279,16 @@ def does_utility_exist(file): return error_msg +def get_server(sid): + """ + # Fetch the server etc + :param sid: + :return: server + """ + server = Server.query.filter_by(id=sid).first() + return server + + # Shortcut configuration for Accesskey ACCESSKEY_FIELDS = [ {