Ensure that reconnect dialogs are shown when restoring pgAdmin sessions for the Query Tool or View/Edit Data, if the server password was not saved. #8901

pull/8978/head
Yogesh Mahajan 2025-07-21 15:11:12 +05:30 committed by GitHub
parent bec47845be
commit 56d5cab13e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 11 deletions

View File

@ -204,11 +204,24 @@ def initialize_viewdata(trans_id, cmd_type, obj_type, sgid, sid, did, obj_id):
else:
_data = request.args or request.form
filter_sql = _data['filter_sql'] if 'filter_sql' in _data else None
filter_sql = _data['sql_filter'] if 'sql_filter' in _data else None
server_cursor = _data['server_cursor'] if\
'server_cursor' in _data and (
_data['server_cursor'] == 'true' or _data['server_cursor'] is True
) else False
dbname = _data['dbname'] if 'dbname' in _data else None
kwargs = {
'user': _data['user'] if 'user' in _data else None,
'role': _data['role'] if 'role' in _data else None,
'password': _data['password'] if 'password' in _data else None
}
server = Server.query.filter_by(id=sid).first()
if kwargs.get('password', None) is None:
kwargs['encpass'] = server.password
else:
kwargs['encpass'] = None
# Create asynchronous connection using random connection id.
conn_id = str(secrets.choice(range(1, 9999999)))
@ -216,11 +229,36 @@ def initialize_viewdata(trans_id, cmd_type, obj_type, sgid, sid, did, obj_id):
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
# default_conn is same connection which is created when user connect to
# database from tree
default_conn = manager.connection(did=did)
conn = manager.connection(did=did, conn_id=conn_id,
conn = manager.connection(conn_id=conn_id,
auto_reconnect=False,
use_binary_placeholder=True,
array_to_string=True)
array_to_string=True,
**({"database": dbname} if dbname is not None
else {"did": did}
))
status, msg, is_ask_password, user, _, _ = _connect(
conn,**kwargs)
if not status:
current_app.logger.error(msg)
if is_ask_password:
return make_json_response(
success=0,
status=428,
result={
"server_label": server.name,
"username": user or server.username,
"errmsg": msg,
"prompt_password": True,
"allow_save_password": True
if ALLOW_SAVE_PASSWORD and
session.get('allow_save_password', None)
else False,
}
)
else:
return internal_server_error(
errormsg=str(msg))
default_conn = manager.connection(did=did)
except (ConnectionLost, SSHTunnelConnectionLost):
raise
except Exception as e:

View File

@ -308,7 +308,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
if (toolContent?.modifiedExternally) {
toolContent = await fmUtilsObj.warnFileReload(toolContent?.fileName, toolContent.data, '');
}
if(toolContent?.loadFile){
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.LOAD_FILE, toolContent.fileName, params?.storage);
}else{
@ -338,13 +338,15 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
});
}
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.SERVER_CURSOR, executeServerCursor);
api.post(baseUrl, qtState.params.is_query_tool ? {
let requestParams = {
user: selectedConn.user,
role: selectedConn.role,
password: password,
dbname: selectedConn.database_name
} : {sql_filter: qtState.params.sql_filter,
server_cursor: qtState.params.server_cursor})
};
api.post(baseUrl, qtState.params.is_query_tool ?
{...requestParams} :
{sql_filter: qtState.params.sql_filter, server_cursor: qtState.params.server_cursor, ...requestParams})
.then(()=>{
setQtStatePartial({
connected: true,
@ -391,7 +393,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
connected: false,
obtaining_conn: false,
});
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.HANDLE_API_ERROR, error);
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.HANDLE_API_ERROR, error, ()=>{});
}
});
};
@ -511,6 +513,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
const handleApiError = (error, handleParams)=>{
let selectedConn = _.find(qtState.connection_list, (c)=>c.is_selected);
if(error.response?.status == 503 && error.response.data?.info == 'CONNECTION_LOST') {
// We will display re-connect dialog, no need to display error message again
modal.confirm(
@ -529,7 +532,6 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
gettext('Cancel')
);
} else if(handleParams?.checkTransaction && error.response?.data.info == 'DATAGRID_TRANSACTION_REQUIRED') {
let selectedConn = _.find(qtState.connection_list, (c)=>c.is_selected);
initConnection(api, {
'gid': selectedConn.sgid,
'sid': selectedConn.sid,
@ -542,6 +544,17 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
});
} else if(error.response?.status == 403 && error.response?.data.info == 'ACCESS_DENIED') {
pgAdmin.Browser.notifier.error(error.response.data.errormsg);
}else if(error?.response?.status == 428) {
connectServerModal(modal, error.response?.data?.result, async (passwordData)=>{
await connectServer(api, modal, selectedConn.sid, selectedConn.user, passwordData, async ()=>{
initializeQueryTool();
});
}, ()=>{
/*This is intentional (SonarQube)*/
});
}else {
let msg = parseApiError(error);
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.SET_MESSAGE, msg, true);

View File

@ -190,7 +190,7 @@ function showFilterDialog(pgBrowser, item, queryToolMod, transId,
let helpUrl = url_for('help.static', {'filename': 'viewdata_filter.html'});
let okCallback = function() {
queryToolMod.launch(transId, gridUrl, false, queryToolTitle, {sql_filter: JSON.stringify(schema.sessData.filter_sql)});
queryToolMod.launch(transId, gridUrl, false, queryToolTitle, {sql_filter: schema.sessData.filter_sql});
};
pgBrowser.Events.trigger('pgadmin:utility:show', item,