Disable the PSQL tool for Windows, the 'fcntl' module is not working on Windows.

This commit is contained in:
Nikhil Mohite
2021-06-01 20:04:43 +05:30
committed by Akshay Joshi
parent 9ac08c263b
commit e0eac875b6
18 changed files with 175 additions and 101 deletions

View File

@@ -1,35 +1,35 @@
#!/usr/bin/env python3
import fcntl
import os
import pty
import re
import select
import struct
import termios
import config
from sys import platform as _platform
import eventlet.green.subprocess as subprocess
from config import PG_DEFAULT_DRIVER
from flask import Response, url_for, request
from flask import render_template, copy_current_request_context, \
current_app as app
from flask_babelex import gettext
from flask_security import login_required, current_user
from pgadmin.browser.utils import underscore_unescape
from pgadmin.browser.utils import underscore_unescape, underscore_escape
from pgadmin.utils import PgAdminModule
from pgadmin.utils.constants import MIMETYPE_APP_JS
from pgadmin.utils.driver import get_driver
from ... import socketio as sio
from pgadmin.utils import get_complete_file_path
from pgadmin.utils.ajax import internal_server_error
if _platform != 'win32':
import fcntl
import termios
import pty
session_input = dict()
session_input_cursor = dict()
session_last_cmd = dict()
pdata = dict()
cdata = dict()
_NODES_SQL = 'nodes.sql'
class PSQLModule(PgAdminModule):
@@ -225,27 +225,35 @@ def start_process(data):
"""
@copy_current_request_context
def read_and_forward_pty_output(sid, data):
max_read_bytes = 1024 * 20
p, parent, fd = create_pty_terminal(connection_data)
if _platform != 'win32':
p, parent, fd = create_pty_terminal(connection_data)
while p and p.poll() is None:
if request.sid in app.config['sessions']:
# This code is added to make this unit testable.
if "is_test" not in data:
sio.sleep(0.01)
else:
data['count'] += 1
if data['count'] == 5:
break
while p and p.poll() is None:
if request.sid in app.config['sessions']:
# This code is added to make this unit testable.
if "is_test" not in data:
sio.sleep(0.01)
else:
data['count'] += 1
if data['count'] == 5:
break
timeout = 0
# module provides access to platform-specific I/O
# monitoring functions
(data_ready, _, _) = select.select([parent, fd], [], [],
timeout)
timeout = 0
# module provides access to platform-specific I/O
# monitoring functions
(data_ready, _, _) = select.select([parent, fd], [], [],
timeout)
read_terminal_data(parent, data_ready, max_read_bytes, sid)
read_terminal_data(parent, data_ready, max_read_bytes, sid)
else:
sio.emit(
'conn_error',
{
'error': 'PSQL tool not supported.',
}, namespace='/pty', room=request.sid)
# Check user is authenticated and PSQL is enabled in config.
if current_user.is_authenticated and config.ENABLE_PSQL:
@@ -255,6 +263,8 @@ def start_process(data):
if data['db']:
db = underscore_unescape(data['db']).replace('\\', "\\\\")
data['db'] = db
conn, manager = _get_connection(int(data['sid']), data)
psql_utility = manager.utility('sql')
connection_data = get_connection_str(psql_utility, db,
@@ -348,15 +358,15 @@ def get_conn_str(manager, db):
"""
manager.export_password_env('PGPASSWORD')
conn_attr =\
"host={0} port={1} dbname={2} user={3} sslmode={4} " \
"sslcompression={5} " \
"".format(
'host={0} port={1} dbname={2} user={3} sslmode={4} ' \
'sslcompression={5} ' \
''.format(
manager.local_bind_host if manager.use_ssh_tunnel else
manager.host,
manager.local_bind_port if manager.use_ssh_tunnel else
manager.port,
db if db != '' else 'postgres',
manager.user if manager.user else 'postgres',
underscore_unescape(db) if db != '' else 'postgres',
underscore_unescape(manager.user) if manager.user else 'postgres',
manager.ssl_mode,
True if manager.sslcompression else False,
)
@@ -423,7 +433,6 @@ def invalid_cmd():
:rtype:
"""
session_last_cmd[request.sid]['invalid_cmd'] = True
for i in range(len(session_input[request.sid])):
os.write(app.config['sessions'][request.sid],
'\b \b'.encode())
@@ -455,6 +464,7 @@ def check_valid_cmd(user_input):
if stop_execution:
session_last_cmd[request.sid]['invalid_cmd'] = True
# Remove already added command from terminal.
for i in range(len(user_input)):
os.write(app.config['sessions'][request.sid],
@@ -482,6 +492,7 @@ def enter_key_press(data):
# contains \! in input.
is_new_connection = session_last_cmd[request.sid][
'is_new_connection']
if user_input.startswith('\\!') and re.match("^\\\!$", user_input) and len(
user_input) == 2 and not config.ALLOW_PSQL_SHELL_COMMANDS \
and not is_new_connection:
@@ -490,7 +501,8 @@ def enter_key_press(data):
not config.ALLOW_PSQL_SHELL_COMMANDS and\
not session_last_cmd[request.sid]['is_new_connection']:
check_valid_cmd(user_input)
elif user_input == '\q' or user_input == 'q\\q':
elif user_input == '\q' or user_input == 'q\\q' or \
user_input in ['exit', 'exit;']:
# If user enter \q to terminate the PSQL, emit the msg to
# notify user connection is terminated.
sio.emit('pty-output',
@@ -501,6 +513,7 @@ def enter_key_press(data):
' tool.'),
'error': True},
namespace='/pty', room=request.sid)
os.write(app.config['sessions'][request.sid],
'\n'.encode())

View File

@@ -54,7 +54,7 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
}];
this.enable_psql_tool = pgAdmin['enable_psql'];
if(pgAdmin['enable_psql']) {
if(pgAdmin['enable_psql'] && pgAdmin['platform'] != 'win32') {
pgBrowser.add_menus(menus);
}

View File

@@ -23,36 +23,40 @@
require(
['sources/generated/psql_tool'],
function(pgBrowser) {
const term = self.pgAdmin.Browser.psql.psql_terminal();
<!--Addon for fitAddon, webLinkAddon, SearchAddon -->
const fitAddon = self.pgAdmin.Browser.psql.psql_Addon(term);
<!-- Update the theme for terminal as per pgAdmin 4 theme.-->
self.pgAdmin.Browser.psql.set_theme(term);
<!-- Open the terminal -->
term.open(document.getElementById('psql-terminal'));
<!-- Socket-->
const socket = self.pgAdmin.Browser.psql.psql_socket();
self.pgAdmin.Browser.psql.psql_socket_io(socket, '{{is_enable}}', '{{sid}}', '{{db}}', '{{server_type}}', fitAddon, term);
self.pgAdmin.Browser.psql.psql_terminal_io(term, socket);
self.pgAdmin.Browser.psql.check_db_name_change('{{db}}', '{{o_db_name}}');
if (self.pgAdmin['platform'] != 'win32') {
const term = self.pgAdmin.Browser.psql.psql_terminal();
<!--Addon for fitAddon, webLinkAddon, SearchAddon -->
const fitAddon = self.pgAdmin.Browser.psql.psql_Addon(term);
<!-- Update the theme for terminal as per pgAdmin 4 theme.-->
self.pgAdmin.Browser.psql.set_theme(term);
<!-- Open the terminal -->
term.open(document.getElementById('psql-terminal'));
<!-- Socket-->
const socket = self.pgAdmin.Browser.psql.psql_socket();
self.pgAdmin.Browser.psql.psql_socket_io(socket, '{{is_enable}}', '{{sid}}', '{{db}}', '{{server_type}}', fitAddon, term);
self.pgAdmin.Browser.psql.psql_terminal_io(term, socket);
self.pgAdmin.Browser.psql.check_db_name_change('{{db}}', '{{o_db_name}}');
<!-- Resize the terminal -->
function fitToscreen(){
fitAddon.fit()
socket.emit("resize", {"cols": term.cols, "rows": term.rows})
}
function debounce(func, wait_ms) {
let timeout
return function(...args) {
const context = this
clearTimeout(timeout)
timeout = setTimeout(() => func.apply(context, args), wait_ms)
<!-- Resize the terminal -->
function fitToscreen(){
fitAddon.fit()
socket.emit("resize", {"cols": term.cols, "rows": term.rows})
}
}
const wait_ms = 50;;
window.onresize = debounce(fitToscreen, wait_ms)
function debounce(func, wait_ms) {
let timeout
return function(...args) {
const context = this
clearTimeout(timeout)
timeout = setTimeout(() => func.apply(context, args), wait_ms)
}
}
const wait_ms = 50;;
window.onresize = debounce(fitToscreen, wait_ms)
} else {
document.getElementById('psql-terminal').innterHTML = 'PSQL not supported'
}
});
{% endblock %}

View File

@@ -1,5 +1,6 @@
import uuid
import config
import sys
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from regression import parent_node_dict
@@ -24,6 +25,8 @@ class PSQLBackend(BaseTestGenerator):
self.server_con = server_utils.connect_server(self, self.sid)
def runTest(self):
if sys.platform == 'win32':
self.skipTest('PSQL disabled for windows')
# Fetch flask client to access current user and other cookies.
flask_client = app.test_client()
flask_client.get('/')

View File

@@ -1,5 +1,6 @@
import uuid
import random
import sys
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from regression import parent_node_dict
@@ -16,6 +17,8 @@ class PSQLPanel(BaseTestGenerator):
self.theme = 'standard'
def runTest(self):
if sys.platform == 'win32':
self.skipTest('PSQL disabled for windows')
trans_id = random.randint(1, 9999999)
url = '/psql/panel/{trans_id}?sgid={sgid}&sid={sid}&did={did}' \
'&server_type=pg&db={db_name}&theme={theme}'.\

View File

@@ -1,5 +1,6 @@
import uuid
import config
import sys
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from regression import parent_node_dict
@@ -17,6 +18,8 @@ class PSQLSocketDisabled(BaseTestGenerator):
config.ENABLE_PSQL = False
def runTest(self):
if sys.platform == 'win32':
self.skipTest('PSQL disabled for windows')
self.test_client = socketio.test_client(app, namespace='/pty')
self.assertTrue(self.test_client.is_connected('/pty'))
received = self.test_client.get_received('/pty')

View File

@@ -1,5 +1,6 @@
import uuid
import config
import sys
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from regression import parent_node_dict
@@ -24,6 +25,8 @@ class PSQLInput(BaseTestGenerator):
self.server_con = server_utils.connect_server(self, self.sid)
def runTest(self):
if sys.platform == 'win32':
self.skipTest('PSQL disabled for windows')
# Fetch flask client to access current user and other cookies.
flask_client = app.test_client()
flask_client.get('/')

View File

@@ -1,5 +1,6 @@
import uuid
import config
import sys
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from regression import parent_node_dict
@@ -24,6 +25,8 @@ class PSQLResizeTerminal(BaseTestGenerator):
self.server_con = server_utils.connect_server(self, self.sid)
def runTest(self):
if sys.platform == 'win32':
self.skipTest('PSQL disabled for windows')
# Fetch flask client to access current user and other cookies.
flask_client = app.test_client()
flask_client.get('/')

View File

@@ -1,5 +1,6 @@
import uuid
import config
import sys
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from regression import parent_node_dict
@@ -17,6 +18,8 @@ class PSQLSocketConnect(BaseTestGenerator):
config.ENABLE_PSQL = True
def runTest(self):
if sys.platform == 'win32':
self.skipTest('PSQL disabled for windows')
self.test_client = socketio.test_client(app, namespace='/pty')
self.assertTrue(self.test_client.is_connected('/pty'))
received = self.test_client.get_received('/pty')

View File

@@ -1,5 +1,6 @@
import uuid
import config
import sys
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from regression import parent_node_dict
@@ -17,6 +18,8 @@ class PSQLSocketDisconnect(BaseTestGenerator):
config.ENABLE_PSQL = True
def runTest(self):
if sys.platform == 'win32':
self.skipTest('PSQL disabled for windows')
# Fetch flask client to access current user and other cookies.
flask_test_client = app.test_client()
flask_test_client.get('/')

View File

@@ -1,5 +1,6 @@
import uuid
import config
import sys
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from regression import parent_node_dict
@@ -21,6 +22,8 @@ class PSQLStartProcess(BaseTestGenerator):
self.server_con = server_utils.connect_server(self, self.sid)
def runTest(self):
if sys.platform == 'win32':
self.skipTest('PSQL disabled for windows')
# Fetch flask client to access current user and other cookies.
flask_client = app.test_client()
flask_client.get('/')

View File

@@ -1,5 +1,6 @@
import uuid
import config
import sys
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from regression import parent_node_dict
@@ -17,6 +18,8 @@ class PSQLStartProcessFail(BaseTestGenerator):
config.ENABLE_PSQL = True
def runTest(self):
if sys.platform == 'win32':
self.skipTest('PSQL disabled for windows')
self.test_client = socketio.test_client(app, namespace='/pty')
self.assertTrue(self.test_client.is_connected('/pty'))
received = self.test_client.get_received('/pty')