Skip to content

Commit c443529

Browse files
Fix the review comments.
1 parent e5a56fc commit c443529

33 files changed

+352
-378
lines changed

web/migrations/versions/4aa49c5d8eb1_.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1-
2-
"""empty message
1+
##########################################################################
2+
#
3+
# pgAdmin 4 - PostgreSQL Tools
4+
#
5+
# Copyright (C) 2013 - 2025, The pgAdmin Development Team
6+
# This software is released under the PostgreSQL Licence
7+
#
8+
##########################################################################
9+
"""Add ability to save the workspace/tools data to
10+
restore on abrupt restart/refresh of application #3319
311
412
Revision ID: 4aa49c5d8eb1
513
Revises: 1f0eddc8fc79
@@ -18,7 +26,7 @@
1826

1927
def upgrade():
2028
op.create_table(
21-
'pgadmin_state_data',
29+
'application_state',
2230
sa.Column('uid', sa.Integer(), nullable=False),
2331
sa.Column('id', sa.Integer()),
2432
sa.Column('connection_info', sa.JSON()),

web/pgadmin/authenticate/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ def authenticate(self):
274274
"""Authenticate through all the sources."""
275275
status = False
276276
msg = None
277+
username = self.form.data['email']
278+
users = User.query.filter_by(username=username).all()
279+
277280
for src in self.auth_sources:
278281
source = get_auth_sources(src)
279282
self.set_source(source)
@@ -282,6 +285,8 @@ def authenticate(self):
282285
source.get_source_name())
283286

284287
status, msg = source.authenticate(self.form)
288+
print(status)
289+
print(msg)
285290

286291
if status:
287292
self.set_current_source(source.get_source_name())
@@ -292,6 +297,16 @@ def authenticate(self):
292297
current_app.logger.debug(
293298
"Authentication initiated via source: %s is failed." %
294299
source.get_source_name())
300+
current_user = User.query.filter_by(username=username,
301+
auth_source=src).first()
302+
# get list with auth source src
303+
# iterate over it and find if user present with that
304+
if len(users) > 0 and current_user:
305+
print('User may be coming first time so continue with all possible')
306+
break
307+
elif len(users) > 0:
308+
print('User already present with other aut source break it')
309+
break
295310

296311
return status, msg
297312

web/pgadmin/browser/static/js/browser.js

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ import getApiInstance, {parseApiError} from '../../../static/js/api_instance';
1616
import usePreferences, { setupPreferenceBroadcast } from '../../../preferences/static/js/store';
1717
import checkNodeVisibility from '../../../static/js/check_node_visibility';
1818
import * as showQueryTool from '../../../tools/sqleditor/static/js/show_query_tool';
19-
import {relaunchPsqlTool} from '../../../tools/psql/static/js/show_psql_tool';
20-
import {relaunchErdTool} from '../../../tools/erd/static/js/show_erd_tool';
21-
import { relaunchSchemaDiff } from '../../../tools/schema_diff/static/js/showSchemaDiffTool';
19+
import {getRandomInt} from 'sources/utils';
2220

2321
define('pgadmin.browser', [
2422
'sources/gettext', 'sources/url_for', 'sources/pgadmin',
@@ -211,7 +209,7 @@ define('pgadmin.browser', [
211209
this.set_master_password('');
212210
this.check_version_update();
213211
const prefStore = usePreferences.getState();
214-
let save_the_workspace = prefStore.getPreferencesForModule('misc').save_the_workspace;
212+
let save_the_workspace = prefStore.getPreferencesForModule('misc').save_app_state;
215213
if(save_the_workspace){
216214
this.restore_pgadmin_state();
217215
}
@@ -300,41 +298,44 @@ define('pgadmin.browser', [
300298
});
301299
},
302300

303-
restore_pgadmin_state: async function () {
301+
restore_pgadmin_state: function () {
304302
getApiInstance().get(
305-
url_for('settings.get_pgadmin_state')
303+
url_for('settings.get_application_state')
306304
).then((res)=> {
307305
if(res.data.success && res.data.data.result.length > 0){
308-
//let oldIds = []
309-
_.each(res.data.data.result, function(tool_data){
310-
if (tool_data.tool_name == 'sqleditor'){
311-
showQueryTool.relaunchSqlTool(tool_data);
312-
}else if(tool_data.tool_name == 'psql'){
313-
relaunchPsqlTool(tool_data);
314-
}else if(tool_data.tool_name == 'ERD'){
315-
relaunchErdTool(tool_data);
316-
}else if(tool_data.tool_name == 'schema_diff'){
317-
relaunchSchemaDiff(tool_data);
306+
_.each(res.data.data.result, function(tool_state){
307+
let tool_name = tool_state.tool_name;
308+
let tool_data = tool_state.tool_data;
309+
let sql_id = `${tool_name}-${getRandomInt(1, 9999999)}`;
310+
311+
if (tool_name == 'sqleditor'){
312+
localStorage.setItem(sql_id, tool_data);
313+
showQueryTool.relaunchSqlTool(tool_state, sql_id);
314+
}else if(tool_name == 'psql'){
315+
pgAdmin.Tools.Psql.openPsqlTool(null, null, tool_state);
316+
}else if(tool_name == 'ERD'){
317+
localStorage.setItem(sql_id, tool_data);
318+
pgAdmin.Tools.ERD.showErdTool(null, null, false, sql_id, tool_state);
319+
}else if(tool_name == 'schema_diff'){
320+
localStorage.setItem(sql_id, tool_data);
321+
pgAdmin.Tools.SchemaDiff.launchSchemaDiff(sql_id);
318322
}
319323
});
320324

321-
// call clear query data for which query tool has been launched.
325+
// call clear application state data.
322326
try {
323-
getApiInstance().delete(url_for('settings.delete_pgadmin_state'), {
327+
getApiInstance().delete(url_for('settings.delete_application_state'), {
324328
});
325329
} catch (error) {
326330
console.error(error);
327331
pgAdmin.Browser.notifier.error(gettext('Failed to remove query data.') + parseApiError(error));
328332
}
329-
330333
}
331334
}).catch(function(error) {
332335
pgAdmin.Browser.notifier.pgRespErrorNotify(error);
333336
});
334-
335337
},
336338

337-
338339
bind_beforeunload: function() {
339340
window.addEventListener('beforeunload', function(e) {
340341
/* Can open you in new tab */

web/pgadmin/misc/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,15 @@ def register_preferences(self):
125125
)
126126

127127
self.preference.register(
128-
'user_interface', 'save_the_workspace',
129-
gettext("Save the workspaces and data?"),
128+
'user_interface', 'save_app_state',
129+
gettext("Save the application state?"),
130130
'boolean', True,
131131
category_label=PREF_LABEL_USER_INTERFACE,
132132
help_str=gettext(
133-
'Turning on this setting will save the information about the'
134-
' tools that are opened and data within it. Data will be '
135-
'restored in case of abrupt shutdown/refresh of the '
136-
'application'
133+
'If set to True, pgAdmin will save the state of opened tools'
134+
' (such as Query Tool, PSQL, Schema Diff, and ERD), including'
135+
' any unsaved data. This data will be automatically restored'
136+
' in the event of an unexpected shutdown or browser refresh.'
137137
)
138138
)
139139

web/pgadmin/model/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,9 @@ class QueryHistoryModel(db.Model):
392392
last_updated_flag = db.Column(db.String(), nullable=False)
393393

394394

395-
class PgadminStateData(db.Model):
396-
"""Define the history SQL table."""
397-
__tablename__ = 'pgadmin_state_data'
395+
class ApplicationState(db.Model):
396+
"""Define the application state SQL table."""
397+
__tablename__ = 'application_state'
398398
uid = db.Column(db.Integer(), db.ForeignKey(USER_ID), nullable=False,
399399
primary_key=True)
400400
id = db.Column(db.Integer(),nullable=False,primary_key=True)

web/pgadmin/settings/__init__.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
success_return, internal_server_error
2222
from pgadmin.utils.menu import MenuItem
2323

24-
from pgadmin.model import db, Setting, PgadminStateData
24+
from pgadmin.model import db, Setting, ApplicationState
2525
from pgadmin.utils.constants import MIMETYPE_APP_JS
2626
from .utils import get_dialog_type, get_file_type_setting
2727
from cryptography.fernet import Fernet
@@ -54,8 +54,9 @@ def get_exposed_url_endpoints(self):
5454
'settings.reset_tree_state',
5555
'settings.save_file_format_setting',
5656
'settings.get_file_format_setting',
57-
'settings.save_pgadmin_state',
58-
'settings.delete_pgadmin_state'
57+
'settings.save_application_state',
58+
'settings.get_application_state',
59+
'settings.delete_application_state'
5960
]
6061

6162

@@ -262,11 +263,11 @@ def get_file_format_setting():
262263

263264

264265
@blueprint.route(
265-
'/save_pgadmin_state',
266-
methods=["POST"], endpoint='save_pgadmin_state'
266+
'/save_application_state',
267+
methods=["POST"], endpoint='save_application_state'
267268
)
268269
@pga_login_required
269-
def save_pgadmin_state_data():
270+
def save_application_state():
270271
"""
271272
Args:
272273
sid: server id
@@ -279,7 +280,7 @@ def save_pgadmin_state_data():
279280
connection_info = data['connection_info'] \
280281
if 'connection_info' in data else None
281282
try:
282-
data_entry = PgadminStateData(
283+
data_entry = ApplicationState(
283284
uid=current_user.id, id=id,connection_info=connection_info,
284285
tool_name=data['tool_name'], tool_data=tool_data)
285286

@@ -298,15 +299,15 @@ def save_pgadmin_state_data():
298299

299300

300301
@blueprint.route(
301-
'/get_pgadmin_state',
302-
methods=["GET"], endpoint='get_pgadmin_state'
302+
'/get_application_state',
303+
methods=["GET"], endpoint='get_application_state'
303304
)
304305
@pga_login_required
305-
def get_pgadmin_state():
306+
def get_application_state():
306307
fernet = Fernet(current_app.config['SECRET_KEY'].encode())
307308
result = db.session \
308-
.query(PgadminStateData) \
309-
.filter(PgadminStateData.uid == current_user.id) \
309+
.query(ApplicationState) \
310+
.filter(ApplicationState.uid == current_user.id) \
310311
.all()
311312

312313
res = []
@@ -326,10 +327,10 @@ def get_pgadmin_state():
326327

327328

328329
@blueprint.route(
329-
'/delete_pgadmin_state/',
330-
methods=["DELETE"], endpoint='delete_pgadmin_state')
330+
'/delete_application_state/',
331+
methods=["DELETE"], endpoint='delete_application_state')
331332
@pga_login_required
332-
def delete_pgadmin_state_data():
333+
def delete_application_state():
333334
trans_id = None
334335
if request.data:
335336
data = json.loads(request.data)
@@ -341,14 +342,14 @@ def delete_tool_data(trans_id):
341342
try:
342343
if trans_id:
343344
results = db.session \
344-
.query(PgadminStateData) \
345-
.filter(PgadminStateData.uid == current_user.id,
346-
PgadminStateData.id == trans_id) \
345+
.query(ApplicationState) \
346+
.filter(ApplicationState.uid == current_user.id,
347+
ApplicationState.id == trans_id) \
347348
.all()
348349
else:
349350
results = db.session \
350-
.query(PgadminStateData) \
351-
.filter(PgadminStateData.uid == current_user.id) \
351+
.query(ApplicationState) \
352+
.filter(ApplicationState.uid == current_user.id) \
352353
.all()
353354
for result in results:
354355
db.session.delete(result)
@@ -364,6 +365,6 @@ def delete_tool_data(trans_id):
364365
return make_json_response(
365366
data={
366367
'status': False,
367-
'msg': 'str(e)',
368+
'msg': str(e),
368369
}
369370
)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/////////////////////////////////////////////////////////////
2+
//
3+
// pgAdmin 4 - PostgreSQL Tools
4+
//
5+
// Copyright (C) 2013 - 2025, The pgAdmin Development Team
6+
// This software is released under the PostgreSQL Licence
7+
//
8+
//////////////////////////////////////////////////////////////
9+
import React, { useContext, useMemo } from 'react';
10+
import PropTypes from 'prop-types';
11+
import getApiInstance from '../../static/js/api_instance';
12+
import url_for from 'sources/url_for';
13+
14+
const ApplicationStateContext = React.createContext();
15+
16+
export const useApplicationState = ()=>useContext(ApplicationStateContext);
17+
18+
export function retrieveDataFromLocalStorgae(sqlId){
19+
let sqlValue = JSON.parse(localStorage.getItem(sqlId));
20+
localStorage.removeItem(sqlId);
21+
return sqlValue;
22+
}
23+
24+
export function ApplicationStateProvider({children}){
25+
const saveToolData = (data) =>{
26+
getApiInstance().post(
27+
url_for('settings.save_application_state'),
28+
JSON.stringify(data),
29+
).catch((error)=>{console.error(error);});
30+
};
31+
32+
const value = useMemo(()=>({
33+
saveToolData,
34+
}), []);
35+
36+
return <ApplicationStateContext.Provider value={value}>
37+
{children}
38+
</ApplicationStateContext.Provider>;
39+
40+
}
41+
42+
ApplicationStateProvider.propTypes = {
43+
children: PropTypes.object
44+
};

web/pgadmin/static/js/PgAdminProvider.jsx

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99

1010
import React from 'react';
1111
import PropTypes from 'prop-types';
12-
import EventBus from './helpers/EventBus';
13-
import getApiInstance from './api_instance';
14-
import url_for from 'sources/url_for';
1512

1613
const PgAdminContext = React.createContext();
1714

@@ -21,19 +18,7 @@ export function usePgAdmin() {
2118
}
2219

2320
export function PgAdminProvider({children, value}) {
24-
25-
const eventBus = React.useRef(new EventBus());
26-
27-
React.useEffect(()=>{
28-
eventBus.current.registerListener('SAVE_TOOL_DATA', (data) => {
29-
getApiInstance().post(
30-
url_for('settings.save_pgadmin_state'),
31-
JSON.stringify(data),
32-
).catch((error)=>{console.error(error);});
33-
});
34-
}, []);
35-
36-
return <PgAdminContext.Provider value={{pgAdminProviderEventBus: eventBus.current, ...value}}>
21+
return <PgAdminContext.Provider value={value}>
3722
{children}
3823
</PgAdminContext.Provider>;
3924
}

web/pgadmin/static/js/ToolView.jsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,18 @@ export default function ToolView({dockerObj}) {
5959
// Handler here will return which layout instance the tool should go in
6060
// case of workspace layout.
6161
let handler = pgAdmin.Browser.getDockerHandler?.(panelId, dockerObj);
62-
const dergisterRemove = handler.docker.eventBus.registerListener(LAYOUT_EVENTS.REMOVE, (closePanelId)=>{
62+
const deregisterRemove = handler.docker.eventBus.registerListener(LAYOUT_EVENTS.REMOVE, (closePanelId)=>{
6363
if(panelId == closePanelId){
6464
let api = getApiInstance();
6565
api.delete(
66-
url_for('settings.delete_pgadmin_state'), {data:{'panelId': panelId}}
67-
).then(()=> { /* Sona qube */}).catch(function(error) {
66+
url_for('settings.delete_application_state'), {data:{'panelId': panelId}}
67+
).then(()=> { /* Sonar Qube */}).catch(function(error) {
6868
pgAdmin.Browser.notifier.pgRespErrorNotify(error);
6969
});
70-
dergisterRemove();
70+
deregisterRemove();
7171
}
7272
});
7373

74-
7574
handler.focus();
7675
handler.docker.openTab({
7776
id: panelId,

0 commit comments

Comments
 (0)