def index(sid=None, did=None): """ Renders the welcome, server or database dashboard Args: sid: Server ID did: Database ID Returns: Welcome/Server/database dashboard """ rates = {} prefs = Preferences.module('dashboards') session_stats_refresh_pref = prefs.preference('session_stats_refresh') rates['session_stats_refresh'] = session_stats_refresh_pref.get() tps_stats_refresh_pref = prefs.preference('tps_stats_refresh') rates['tps_stats_refresh'] = tps_stats_refresh_pref.get() ti_stats_refresh_pref = prefs.preference('ti_stats_refresh') rates['ti_stats_refresh'] = ti_stats_refresh_pref.get() to_stats_refresh_pref = prefs.preference('to_stats_refresh') rates['to_stats_refresh'] = to_stats_refresh_pref.get() bio_stats_refresh_pref = prefs.preference('bio_stats_refresh') rates['bio_stats_refresh'] = bio_stats_refresh_pref.get() # Show the appropriate dashboard based on the identifiers passed to us if sid is None and did is None: return render_template('/dashboard/welcome_dashboard.html') if did is None: return render_template('/dashboard/server_dashboard.html', sid=sid, rates=rates) else: return render_template('/dashboard/database_dashboard.html', sid=sid, did=did, rates=rates)
def statistics(self, gid, sid, jid): """ statistics Returns the statistics for a particular database if jid is specified, otherwise it will return statistics for all the databases in that server. """ pref = Preferences.module('browser') rows_threshold = pref.preference( 'pgagent_row_threshold' ) status, res = self.conn.execute_dict( render_template( "/".join([self.template_path, 'stats.sql']), jid=jid, conn=self.conn, rows_threshold=rows_threshold.get() ) ) if not status: return internal_server_error(errormsg=res) return make_json_response( data=res, status=200 )
def set_preference(default_binary_path): conn = sqlite3.connect(config.TEST_SQLITE_PATH) cur = conn.cursor() perf = Preferences.module('paths') server_types = default_binary_path.keys() for server in server_types: path_pref = perf.preference('{0}_bin_dir'.format(server)) user_pref = cur.execute( 'SELECT pid, uid FROM user_preferences ' 'where pid=%s' % path_pref.pid ) user_pref_data = user_pref.fetchone() if user_pref_data: cur.execute( 'UPDATE user_preferences SET value = ? WHERE pid = ?', (default_binary_path[server], path_pref.pid) ) else: params = (path_pref.pid, 1, default_binary_path[server]) cur.execute( 'INSERT INTO user_preferences(pid, uid, value)' ' VALUES (?,?,?)', params ) conn.commit()
def register_preferences(self): """ Get show_system_objects preference """ self.browser_preference = Preferences.module('browser') self.pref_show_system_objects = self.browser_preference.preference( 'show_system_objects' )
def register_preferences(self): """ Register preferences for this module. """ # Add the node informaton for browser, not in respective # node preferences self.browser_preference = Preferences.module('browser') self.pref_show_system_objects = self.browser_preference.preference( 'show_system_objects' )
def register_language(sender, user): # After logged in, set the language in the preferences if we get from # the login page data = request.form if 'language' in data: language = data['language'] # Set the user language preference misc_preference = Preferences.module('miscellaneous') user_languages = misc_preference.preference( 'user_language' ) if user_languages and language: language = user_languages.set(language)
def register_preferences(self): """ Register preferences for this module. """ # Add the node informaton for browser, not in respective # node preferences self.browser_preference = Preferences.module('browser') self.pref_show_system_objects = self.browser_preference.preference( 'show_system_objects' ) self.pref_show_node = self.browser_preference.register( 'node', 'show_node_' + self.node_type, gettext('Package {0}').format(self.label), 'node', self.SHOW_ON_BROWSER, category_label=gettext('Nodes') )
def node_js(): prefs = Preferences.module('paths') pg_help_path_pref = prefs.preference('pg_help_path') pg_help_path = pg_help_path_pref.get() edbas_help_path_pref = prefs.preference('edbas_help_path') edbas_help_path = edbas_help_path_pref.get() return make_response( render_template('browser/js/node.js', pg_help_path=pg_help_path, edbas_help_path=edbas_help_path, _=gettext ), 200, {'Content-Type': 'application/x-javascript'})
def file_manager_config(trans_id): """render the required json""" # trans_id = Filemanager.create_new_transaction() data = Filemanager.get_trasaction_selection(trans_id) pref = Preferences.module('file_manager') file_dialog_view = pref.preference('file_dialog_view').get() show_hidden_files = pref.preference('show_hidden_files').get() return Response(response=render_template( "file_manager/js/file_manager_config.json", _=gettext, data=data, file_dialog_view=file_dialog_view, show_hidden_files=show_hidden_files ), status=200, mimetype="application/json" )
def register_preferences(self): """ register_preferences Register preferences for this module. Keep the browser preference object to be used by overriden submodule, along with that get two browser level preferences show_system_objects, and show_node will be registered to used by the submodules. """ # Add the node informaton for browser, not in respective node preferences self.browser_preference = Preferences.module('browser') self.pref_show_system_objects = self.browser_preference.preference( 'show_system_objects' ) self.pref_show_node = self.browser_preference.register( 'node', 'show_node_' + self.node_type, self.collection_label, 'node', self.SHOW_ON_BROWSER, category_label=gettext('Nodes') )
def browser_css(): """Render and return CSS snippets from the nodes and modules.""" snippets = [] # Get configurable options prefs = Preferences.module('sqleditor') sql_font_size_pref = prefs.preference('sql_font_size') sql_font_size = round(float(sql_font_size_pref.get()), 2) if sql_font_size != 0: snippets.append( '.CodeMirror { font-size: %sem; }' % str(sql_font_size) ) for submodule in blueprint.submodules: snippets.extend(submodule.csssnippets) return make_response( render_template( 'browser/css/browser.css', snippets=snippets, _=gettext ), 200, {'Content-Type': 'text/css'})
def save(pid): """ Save a specific preference. """ data = request.form if request.form else json.loads(request.data.decode()) res, msg = Preferences.save( data['mid'], data['category_id'], data['id'], data['value']) if not res: return internal_server_error(errormsg=msg) response = success_return() # Set cookie & session for language settings. # This will execute every time as could not find the better way to know # that which preference is getting updated. misc_preference = Preferences.module('miscellaneous') user_languages = misc_preference.preference( 'user_language' ) language = 'en' if user_languages: language = user_languages.get() or language domain = dict() if config.COOKIE_DEFAULT_DOMAIN and\ config.COOKIE_DEFAULT_DOMAIN != 'localhost': domain['domain'] = config.COOKIE_DEFAULT_DOMAIN setattr(session, 'PGADMIN_LANGUAGE', language) response.set_cookie("PGADMIN_LANGUAGE", value=language, path=config.COOKIE_DEFAULT_PATH, **domain) return response
def save(pid): """ Save a specific preference. """ data = request.form if request.form else json.loads(request.data.decode()) res, msg = Preferences.save(data['mid'], data['category_id'], data['id'], data['value']) if not res: return internal_server_error(errormsg=msg) response = success_return() # Set cookie & session for language settings. # This will execute every time as could not find the better way to know # that which preference is getting updated. misc_preference = Preferences.module('miscellaneous') user_languages = misc_preference.preference('user_language') language = 'en' if user_languages: language = user_languages.get() or language domain = dict() if config.COOKIE_DEFAULT_DOMAIN and\ config.COOKIE_DEFAULT_DOMAIN != 'localhost': domain['domain'] = config.COOKIE_DEFAULT_DOMAIN setattr(session, 'PGADMIN_LANGUAGE', language) response.set_cookie("PGADMIN_LANGUAGE", value=language, path=config.COOKIE_DEFAULT_PATH, **domain) return response
def browser_js(): layout = get_setting('Browser/Layout', default='') snippets = [] prefs = Preferences.module('paths') pg_help_path_pref = prefs.preference('pg_help_path') pg_help_path = pg_help_path_pref.get() edbas_help_path_pref = prefs.preference('edbas_help_path') edbas_help_path = edbas_help_path_pref.get() for submodule in current_blueprint.submodules: snippets.extend(submodule.jssnippets) return make_response( render_template( 'browser/js/browser.js', layout=layout, jssnippets=snippets, pg_help_path=pg_help_path, edbas_help_path=edbas_help_path, _=gettext ), 200, {'Content-Type': 'application/x-javascript'})
def disable_tree_state_save(): conn = sqlite3.connect(config.TEST_SQLITE_PATH) cur = conn.cursor() pref = Preferences.module('browser')\ .preference('browser_tree_state_save_interval') user_pref = cur.execute( 'SELECT pid, uid FROM user_preferences ' 'where pid=?', (pref.pid,) ) if len(user_pref.fetchall()) == 0: cur.execute( 'INSERT INTO user_preferences(pid, uid, value)' ' VALUES (?,?,?)', (pref.pid, 1, -1) ) else: cur.execute( 'UPDATE user_preferences' ' SET VALUE = ?' ' WHERE PID = ?', (-1, pref.pid) ) conn.commit() conn.close()
def get_locale(): """Get the language for the user.""" language = 'en' if config.SERVER_MODE is False: # Get the user language preference from the miscellaneous module misc_preference = Preferences.module('miscellaneous', False) if misc_preference: user_languages = misc_preference.preference('user_language') if user_languages: language = user_languages.get() or language else: # If language is available in get request then return the same # otherwise check the session or cookie data = request.form if 'language' in data: language = data['language'] or language setattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(session, 'PGADMIN_LANGUAGE'): language = getattr(session, 'PGADMIN_LANGUAGE', language) elif hasattr(request.cookies, 'PGADMIN_LANGUAGE'): language = getattr(request.cookies, 'PGADMIN_LANGUAGE', language) return language
def __init__(self, **kwargs): """ This method is used to initialize the class. Args: **kwargs : N number of parameters """ self.sid = kwargs['sid'] if 'sid' in kwargs else None self.conn = kwargs['conn'] if 'conn' in kwargs else None self.keywords = [] self.databases = [] self.functions = [] self.datatypes = [] self.dbmetadata = {'tables': {}, 'views': {}, 'functions': {}, 'datatypes': {}} self.text_before_cursor = None self.name_pattern = re.compile("^[_a-z][_a-z0-9\$]*$") manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(self.sid) # we will set template path for sql scripts self.sql_path = 'sqlautocomplete/sql/#{0}#'.format(manager.version) self.search_path = [] schema_names = [] if self.conn.connected(): # Fetch the search path query = render_template( "/".join([self.sql_path, 'schema.sql']), search_path=True) status, res = self.conn.execute_dict(query) if status: for record in res['rows']: self.search_path.append(record['schema']) # Fetch the schema names query = render_template("/".join([self.sql_path, 'schema.sql'])) status, res = self.conn.execute_dict(query) if status: for record in res['rows']: schema_names.append(record['schema']) pref = Preferences.module('sqleditor') keywords_in_uppercase = \ pref.preference('keywords_in_uppercase').get() # Fetch the keywords query = render_template("/".join([self.sql_path, 'keywords.sql'])) # If setting 'Keywords in uppercase' is set to True in # Preferences then fetch the keywords in upper case. if keywords_in_uppercase: query = render_template( "/".join([self.sql_path, 'keywords.sql']), upper_case=True) status, res = self.conn.execute_dict(query) if status: for record in res['rows']: # 'public' is a keyword in EPAS database server. Don't add # this into the list of keywords. # This is a hack to fix the issue in autocomplete. if record['word'].lower() == 'public': continue self.keywords.append(record['word']) self.prioritizer = PrevalenceCounter(self.keywords) self.reserved_words = set() for x in self.keywords: self.reserved_words.update(x.split()) self.all_completions = set(self.keywords) self.extend_schemata(schema_names) # Below are the configurable options in pgcli which we don't have # in pgAdmin4 at the moment. Setting the default value from the pgcli's # config file. self.signature_arg_style = '{arg_name} {arg_type}' self.call_arg_style = '{arg_name: <{max_arg_len}} := {arg_default}' self.call_arg_display_style = '{arg_name}' self.call_arg_oneliner_max = 2 self.search_path_filter = True self.generate_aliases = False self.insert_col_skip_patterns = [ re.compile(r'^now\(\)$'), re.compile(r'^nextval\(')] self.qualify_columns = 'if_more_than_one_table' self.asterisk_column_order = 'table_order'
def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id): """ This method is responsible for creating an asynchronous connection. After creating the connection it will instantiate and initialize the object as per the object type. It will also create a unique transaction id and store the information into session variable. Args: cmd_type: Contains value for which menu item is clicked. obj_type: Contains type of selected object for which data grid to be render sid: Server Id did: Database Id obj_id: Id of currently selected object """ if request.data: filter_sql = json.loads(request.data, encoding='utf-8') else: filter_sql = request.args or request.form # Create asynchronous connection using random connection id. conn_id = str(random.randint(1, 9999999)) try: manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid) conn = manager.connection(did=did, conn_id=conn_id, use_binary_placeholder=True) except Exception as e: return internal_server_error(errormsg=str(e)) # Connect the Server status, msg = conn.connect() if not status: return internal_server_error(errormsg=str(msg)) try: # if object type is partition then it is nothing but a table. if obj_type == 'partition': obj_type = 'table' # Get the object as per the object type command_obj = ObjectRegistry.get_object(obj_type, conn_id=conn_id, sid=sid, did=did, obj_id=obj_id, cmd_type=cmd_type, sql_filter=filter_sql) except Exception as e: return internal_server_error(errormsg=str(e)) # Create a unique id for the transaction trans_id = str(random.randint(1, 9999999)) if 'gridData' not in session: sql_grid_data = dict() else: sql_grid_data = session['gridData'] # Use pickle to store the command object which will be used # later by the sql grid module. sql_grid_data[trans_id] = { 'command_obj': pickle.dumps(command_obj, -1) # -1 specify the highest protocol version available } # Store the grid dictionary into the session variable session['gridData'] = sql_grid_data pref = Preferences.module('sqleditor') new_browser_tab = pref.preference('new_browser_tab').get() return make_json_response(data={ 'gridTransId': trans_id, 'newBrowserTab': new_browser_tab })
def properties(self, gid, sid, did, scid, tid): """ This function will show the properties of the selected table node. Args: gid: Server Group ID sid: Server ID did: Database ID scid: Schema ID scid: Schema ID tid: Table ID Returns: JSON of selected table node """ SQL = render_template("/".join( [self.table_template_path, 'properties.sql']), did=did, scid=scid, tid=tid, datlastsysoid=self.datlastsysoid) status, res = self.conn.execute_dict(SQL) if not status: return internal_server_error(errormsg=res) if len(res['rows']) == 0: return gone(gettext("The specified table could not be found.")) # We will check the threshold set by user before executing # the query because that can cause performance issues # with large result set pref = Preferences.module('browser') table_row_count_pref = pref.preference('table_row_count_threshold') table_row_count_threshold = table_row_count_pref.get() estimated_row_count = int(res['rows'][0].get('reltuples', 0)) # If estimated rows are greater than threshold then if estimated_row_count and \ estimated_row_count > table_row_count_threshold: res['rows'][0]['rows_cnt'] = str(table_row_count_threshold) + '+' # If estimated rows is lower than threshold then calculate the count elif estimated_row_count and \ table_row_count_threshold >= estimated_row_count: SQL = render_template("/".join( [self.table_template_path, 'get_table_row_count.sql']), data=res['rows'][0]) status, count = self.conn.execute_scalar(SQL) if not status: return internal_server_error(errormsg=count) res['rows'][0]['rows_cnt'] = count # If estimated_row_count is zero then set the row count with same elif not estimated_row_count: res['rows'][0]['rows_cnt'] = estimated_row_count return super(TableView, self).properties(gid, sid, did, scid, tid, res)
def index(): """Render and process the main browser window.""" # Register Gravatar module with the app only if required if config.SHOW_GRAVATAR_IMAGE: Gravatar( current_app, size=100, rating='g', default='retro', force_default=False, use_ssl=True, base_url=None ) # Get the current version info from the website, and flash a message if # the user is out of date, and the check is enabled. if config.UPGRADE_CHECK_ENABLED: data = None url = '%s?version=%s' % (config.UPGRADE_CHECK_URL, config.APP_VERSION) current_app.logger.debug('Checking version data at: %s' % url) try: # Do not wait for more than 5 seconds. # It stuck on rendering the browser.html, while working in the # broken network. if os.path.exists(config.CA_FILE): response = urlreq.urlopen(url, data, 5, cafile=config.CA_FILE) else: response = urlreq.urlopen(url, data, 5) current_app.logger.debug( 'Version check HTTP response code: %d' % response.getcode() ) if response.getcode() == 200: data = json.loads(response.read().decode('utf-8')) current_app.logger.debug('Response data: %s' % data) except Exception: current_app.logger.exception('Exception when checking for update') if data is not None: if data['pgadmin4']['version_int'] > config.APP_VERSION_INT: msg = render_template( MODULE_NAME + "/upgrade.html", current_version=config.APP_VERSION, upgrade_version=data['pgadmin4']['version'], product_name=config.APP_NAME, download_url=data['pgadmin4']['download_url'] ) flash(msg, 'warning') response = Response(render_template( MODULE_NAME + "/index.html", username=current_user.email, is_admin=current_user.has_role("Administrator"), _=gettext )) # Set the language cookie after login, so next time the user will have that # same option at the login time. misc_preference = Preferences.module('miscellaneous') user_languages = misc_preference.preference( 'user_language' ) language = 'en' if user_languages: language = user_languages.get() or 'en' domain = dict() if config.COOKIE_DEFAULT_DOMAIN and\ config.COOKIE_DEFAULT_DOMAIN != 'localhost': domain['domain'] = config.COOKIE_DEFAULT_DOMAIN response.set_cookie("PGADMIN_LANGUAGE", value=language, path=config.COOKIE_DEFAULT_PATH, **domain) return response
def initialize_query_tool(trans_id, sgid, sid, did=None): """ This method is responsible for instantiating and initializing the query tool object. It will also create a unique transaction id and store the information into session variable. Args: sgid: Server group Id sid: Server Id did: Database Id """ connect = True # Read the data if present. Skipping read may cause connection # reset error if data is sent from the client if request.data: _ = request.data req_args = request.args if ('recreate' in req_args and req_args['recreate'] == '1'): connect = False # Create asynchronous connection using random connection id. conn_id = str(random.randint(1, 9999999)) # Use Maintenance database OID manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid) if did is None: did = manager.did try: command_obj = ObjectRegistry.get_object('query_tool', conn_id=conn_id, sgid=sgid, sid=sid, did=did) except Exception as e: app.logger.error(e) return internal_server_error(errormsg=str(e)) try: conn = manager.connection(did=did, conn_id=conn_id, auto_reconnect=False, use_binary_placeholder=True, array_to_string=True) if connect: status, msg = conn.connect() if not status: app.logger.error(msg) return internal_server_error(errormsg=str(msg)) except (ConnectionLost, SSHTunnelConnectionLost) as e: app.logger.error(e) raise except Exception as e: app.logger.error(e) return internal_server_error(errormsg=str(e)) if 'gridData' not in session: sql_grid_data = dict() else: sql_grid_data = session['gridData'] # Set the value of auto commit and auto rollback specified in Preferences pref = Preferences.module('sqleditor') command_obj.set_auto_commit(pref.preference('auto_commit').get()) command_obj.set_auto_rollback(pref.preference('auto_rollback').get()) # Use pickle to store the command object which will be used # later by the sql grid module. sql_grid_data[str(trans_id)] = { # -1 specify the highest protocol version available 'command_obj': pickle.dumps(command_obj, -1) } # Store the grid dictionary into the session variable session['gridData'] = sql_grid_data return make_json_response(data={ 'connId': str(conn_id), 'serverVersion': manager.version, })
def index(): """Render and process the main browser window.""" # Register Gravatar module with the app only if required if config.SHOW_GRAVATAR_IMAGE: Gravatar(current_app, size=100, rating='g', default='retro', force_default=False, use_ssl=True, base_url=None) # Check the browser is a supported version # NOTE: If the checks here are updated, make sure the supported versions # at https://www.pgadmin.org/faq/#11 are updated to match! if config.CHECK_SUPPORTED_BROWSER: browser_name, browser_known, version = _get_supported_browser() if browser_name is not None: msg = render_template(MODULE_NAME + "/browser.html", version=version, browser=browser_name, known=browser_known) flash(msg, 'warning') # Get the current version info from the website, and flash a message if # the user is out of date, and the check is enabled. if config.UPGRADE_CHECK_ENABLED: last_check = get_setting('LastUpdateCheck', default='0') today = time.strftime('%Y%m%d') if int(last_check) < int(today): check_browser_upgrade() store_setting('LastUpdateCheck', today) auth_only_internal = False auth_source = [] session['allow_save_password'] = True if config.SERVER_MODE: if len(config.AUTHENTICATION_SOURCES) == 1\ and INTERNAL in config.AUTHENTICATION_SOURCES: auth_only_internal = True auth_source = session['_auth_source_manager_obj'][ 'source_friendly_name'] if session['_auth_source_manager_obj']['current_source'] == KERBEROS: session['allow_save_password'] = False response = Response( render_template(MODULE_NAME + "/index.html", username=current_user.username, auth_source=auth_source, is_admin=current_user.has_role("Administrator"), logout_url=_get_logout_url(), _=gettext, auth_only_internal=auth_only_internal)) # Set the language cookie after login, so next time the user will have that # same option at the login time. misc_preference = Preferences.module('misc') user_languages = misc_preference.preference('user_language') language = 'en' if user_languages: language = user_languages.get() or 'en' domain = dict() if config.COOKIE_DEFAULT_DOMAIN and\ config.COOKIE_DEFAULT_DOMAIN != 'localhost': domain['domain'] = config.COOKIE_DEFAULT_DOMAIN response.set_cookie("PGADMIN_LANGUAGE", value=language, path=config.COOKIE_DEFAULT_PATH, secure=config.SESSION_COOKIE_SECURE, httponly=config.SESSION_COOKIE_HTTPONLY, samesite=config.SESSION_COOKIE_SAMESITE, **domain) return response
def configure_preferences(default_binary_path=None): conn = sqlite3.connect(config.TEST_SQLITE_PATH) cur = conn.cursor() if default_binary_path is not None: paths_pref = Preferences.module('paths') server_types = default_binary_path.keys() for server in server_types: pref_bin_path = paths_pref.preference('{0}_bin_dir'.format(server)) user_pref = cur.execute('SELECT pid, uid FROM user_preferences ' 'where pid=%s' % pref_bin_path.pid) user_pref_data = user_pref.fetchone() if user_pref_data: cur.execute( 'UPDATE user_preferences SET value = ? WHERE pid = ?', (default_binary_path[server], pref_bin_path.pid)) else: params = (pref_bin_path.pid, 1, default_binary_path[server]) cur.execute( 'INSERT INTO user_preferences(pid, uid, value)' ' VALUES (?,?,?)', params) browser_pref = Preferences.module('browser') # Disable tree state save for tests pref_tree_state_save_interval = \ browser_pref.preference('browser_tree_state_save_interval') user_pref = cur.execute( 'SELECT pid, uid FROM user_preferences ' 'where pid=?', (pref_tree_state_save_interval.pid, )) if len(user_pref.fetchall()) == 0: cur.execute( 'INSERT INTO user_preferences(pid, uid, value)' ' VALUES (?,?,?)', (pref_tree_state_save_interval.pid, 1, -1)) else: cur.execute( 'UPDATE user_preferences' ' SET VALUE = ?' ' WHERE PID = ?', (-1, pref_tree_state_save_interval.pid)) # Disable reload warning on browser pref_confirm_on_refresh_close = \ browser_pref.preference('confirm_on_refresh_close') user_pref = cur.execute( 'SELECT pid, uid FROM user_preferences ' 'where pid=?', (pref_confirm_on_refresh_close.pid, )) if len(user_pref.fetchall()) == 0: cur.execute( 'INSERT INTO user_preferences(pid, uid, value)' ' VALUES (?,?,?)', (pref_confirm_on_refresh_close.pid, 1, 'False')) else: cur.execute( 'UPDATE user_preferences' ' SET VALUE = ?' ' WHERE PID = ?', ('False', pref_confirm_on_refresh_close.pid)) conn.commit() conn.close()
def compare(trans_id, source_sid, source_did, target_sid, target_did): """ This function will compare the two schemas. """ # Check the transaction and connection status status, error_msg, diff_model_obj, session_obj = \ check_transaction_status(trans_id) if error_msg == gettext('Transaction ID not found in the session.'): return make_json_response(success=0, errormsg=error_msg, status=404) # Server version compatibility check status, msg = check_version_compatibility(source_sid, target_sid) if not status: return make_json_response(success=0, errormsg=msg, status=428) comparison_result = [] diff_model_obj.set_comparison_info(gettext("Comparing objects..."), 0) update_session_diff_transaction(trans_id, session_obj, diff_model_obj) try: pref = Preferences.module('schema_diff') ignore_whitespaces = pref.preference('ignore_whitespaces').get() # Fetch all the schemas of source and target database # Compare them and get the status. schema_result = fetch_compare_schemas(source_sid, source_did, target_sid, target_did) total_schema = len(schema_result['source_only']) + len( schema_result['target_only']) + len( schema_result['in_both_database']) node_percent = round( 100 / (total_schema * len(SchemaDiffRegistry.get_registered_nodes()))) total_percent = 0 # Compare Database objects comparison_schema_result, total_percent = \ compare_database_objects( trans_id=trans_id, session_obj=session_obj, source_sid=source_sid, source_did=source_did, target_sid=target_sid, target_did=target_did, diff_model_obj=diff_model_obj, total_percent=total_percent, node_percent=node_percent, ignore_whitespaces=ignore_whitespaces) comparison_result = \ comparison_result + comparison_schema_result # Compare Schema objects if 'source_only' in schema_result and \ len(schema_result['source_only']) > 0: for item in schema_result['source_only']: comparison_schema_result, total_percent = \ compare_schema_objects( trans_id=trans_id, session_obj=session_obj, source_sid=source_sid, source_did=source_did, source_scid=item['scid'], target_sid=target_sid, target_did=target_did, target_scid=None, schema_name=item['schema_name'], diff_model_obj=diff_model_obj, total_percent=total_percent, node_percent=node_percent, ignore_whitespaces=ignore_whitespaces) comparison_result = \ comparison_result + comparison_schema_result if 'target_only' in schema_result and \ len(schema_result['target_only']) > 0: for item in schema_result['target_only']: comparison_schema_result, total_percent = \ compare_schema_objects( trans_id=trans_id, session_obj=session_obj, source_sid=source_sid, source_did=source_did, source_scid=None, target_sid=target_sid, target_did=target_did, target_scid=item['scid'], schema_name=item['schema_name'], diff_model_obj=diff_model_obj, total_percent=total_percent, node_percent=node_percent, ignore_whitespaces=ignore_whitespaces) comparison_result = \ comparison_result + comparison_schema_result # Compare the two schema present in both the databases if 'in_both_database' in schema_result and \ len(schema_result['in_both_database']) > 0: for item in schema_result['in_both_database']: comparison_schema_result, total_percent = \ compare_schema_objects( trans_id=trans_id, session_obj=session_obj, source_sid=source_sid, source_did=source_did, source_scid=item['src_scid'], target_sid=target_sid, target_did=target_did, target_scid=item['tar_scid'], schema_name=item['schema_name'], diff_model_obj=diff_model_obj, total_percent=total_percent, node_percent=node_percent, ignore_whitespaces=ignore_whitespaces) comparison_result = \ comparison_result + comparison_schema_result msg = gettext("Successfully compare the specified databases.") total_percent = 100 diff_model_obj.set_comparison_info(msg, total_percent) # Update the message and total percentage done in session object update_session_diff_transaction(trans_id, session_obj, diff_model_obj) except Exception as e: app.logger.exception(e) return make_json_response(data=comparison_result)
def initialize_query_tool(sgid, sid, did=None): """ This method is responsible for instantiating and initializing the query tool object. It will also create a unique transaction id and store the information into session variable. Args: sgid: Server group Id sid: Server Id did: Database Id """ connect = True if ('recreate' in request.args and request.args['recreate'] == '1'): connect = False # Create asynchronous connection using random connection id. conn_id = str(random.randint(1, 9999999)) # Use Maintenance database OID manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid) if did is None: did = manager.did try: command_obj = ObjectRegistry.get_object('query_tool', conn_id=conn_id, sgid=sgid, sid=sid, did=did) except Exception as e: app.logger.error(e) return internal_server_error(errormsg=str(e)) try: conn = manager.connection(did=did, conn_id=conn_id, auto_reconnect=False, use_binary_placeholder=True, array_to_string=True) if connect: conn.connect() except (ConnectionLost, SSHTunnelConnectionLost) as e: raise except Exception as e: app.logger.error(e) return internal_server_error(errormsg=str(e)) # Create a unique id for the transaction trans_id = str(random.randint(1, 9999999)) if 'gridData' not in session: sql_grid_data = dict() else: sql_grid_data = session['gridData'] # Use pickle to store the command object which will be used # later by the sql grid module. sql_grid_data[trans_id] = { # -1 specify the highest protocol version available 'command_obj': pickle.dumps(command_obj, -1) } # Store the grid dictionary into the session variable session['gridData'] = sql_grid_data pref = Preferences.module('sqleditor') new_browser_tab = pref.preference('new_browser_tab').get() return make_json_response(data={ 'gridTransId': trans_id, 'newBrowserTab': new_browser_tab })
def get_query_tool_keyboard_shortcuts(): """ Fetch all the query tool shortcut preferences Returns: List of query tool shortcut preferences """ qt_perf = Preferences.module('sqleditor') conn_status = qt_perf.preference('btn_conn_status').get() clear_options = qt_perf.preference('btn_clear_options').get() cancel_query = qt_perf.preference('btn_cancel_query').get() execute_options = qt_perf.preference('btn_execute_options').get() filter_options = qt_perf.preference('btn_filter_options').get() rows_limit = qt_perf.preference('btn_rows_limit').get() filter_dialog = qt_perf.preference('btn_filter_dialog').get() delete_row = qt_perf.preference('btn_delete_row').get() paste_row = qt_perf.preference('btn_paste_row').get() copy_row = qt_perf.preference('btn_copy_row').get() save_file = qt_perf.preference('btn_save_file').get() open_file = qt_perf.preference('btn_open_file').get() move_next = qt_perf.preference('move_next').get() move_previous = qt_perf.preference('move_previous').get() download_csv = qt_perf.preference('download_csv').get() execute_query = qt_perf.preference('execute_query').get() explain_query = qt_perf.preference('explain_query').get() explain_analyze_query = qt_perf.preference('explain_analyze_query').get() find_options = qt_perf.preference('btn_find_options').get() return { 'keys': { 'conn_status': conn_status.get('key').get('char'), 'clear_options': clear_options.get('key').get('char'), 'cancel_query': cancel_query.get('key').get('char'), 'execute_options': execute_options.get('key').get('char'), 'filter_options': filter_options.get('key').get('char'), 'rows_limit': rows_limit.get('key').get('char'), 'filter_dialog': filter_dialog.get('key').get('char'), 'delete_row': delete_row.get('key').get('char'), 'paste_row': paste_row.get('key').get('char'), 'copy_row': copy_row.get('key').get('char'), 'save_file': save_file.get('key').get('char'), 'open_file': open_file.get('key').get('char'), 'move_next': move_next.get('key').get('char'), 'move_previous': move_previous.get('key').get('char'), 'download_csv': download_csv.get('key').get('char'), 'execute_query': execute_query.get('key').get('char'), 'explain_query': explain_query.get('key').get('char'), 'explain_analyze_query': explain_analyze_query.get('key').get('char'), 'find_options': find_options.get('key').get('char') }, 'shortcuts': { 'conn_status': conn_status, 'clear_options': clear_options, 'cancel_query': cancel_query, 'execute_options': execute_options, 'filter_options': filter_options, 'rows_limit': rows_limit, 'filter_dialog': filter_dialog, 'delete_row': delete_row, 'paste_row': paste_row, 'copy_row': copy_row, 'save_file': save_file, 'open_file': open_file, 'move_next': move_next, 'move_previous': move_previous, 'download_csv': download_csv, 'execute_query': execute_query, 'explain_query': explain_query, 'explain_analyze_query': explain_analyze_query, 'find_options': find_options }, }
def index(): """Render and process the main browser window.""" # Register Gravatar module with the app only if required if config.SHOW_GRAVATAR_IMAGE: Gravatar( current_app, size=100, rating='g', default='retro', force_default=False, use_ssl=True, base_url=None ) # Check the browser is a support version # NOTE: If the checks here are updated, make sure the supported versions # at https://www.pgadmin.org/faq/#11 are updated to match! if config.CHECK_SUPPORTED_BROWSER: browser = request.user_agent.browser version = request.user_agent.version and int( request.user_agent.version.split('.')[0]) browser_name = None browser_known = True if browser == 'chrome' and version < 72: browser_name = 'Chrome' elif browser == 'firefox' and version < 65: browser_name = 'Firefox' # comparing EdgeHTML engine version elif browser == 'edge' and version < 18: browser_name = 'Edge' # browser version returned by edge browser is actual EdgeHTML # engine version. Below code gets actual browser version using # EdgeHTML version engine_to_actual_browser_version = { 16: 41, 17: 42, 18: 44 } version = engine_to_actual_browser_version.get(version, '< 44') elif browser == 'safari' and version < 12: browser_name = 'Safari' elif browser == 'msie': browser_name = 'Internet Explorer' elif browser != 'chrome' and browser != 'firefox' and \ browser != 'edge' and browser != 'safari': browser_name = browser browser_known = False if browser_name is not None: msg = render_template( MODULE_NAME + "/browser.html", version=version, browser=browser_name, known=browser_known ) flash(msg, 'warning') # Get the current version info from the website, and flash a message if # the user is out of date, and the check is enabled. if config.UPGRADE_CHECK_ENABLED: data = None url = '%s?version=%s' % (config.UPGRADE_CHECK_URL, config.APP_VERSION) current_app.logger.debug('Checking version data at: %s' % url) try: # Do not wait for more than 5 seconds. # It stuck on rendering the browser.html, while working in the # broken network. if os.path.exists(config.CA_FILE): response = urlreq.urlopen(url, data, 5, cafile=config.CA_FILE) else: response = urlreq.urlopen(url, data, 5) current_app.logger.debug( 'Version check HTTP response code: %d' % response.getcode() ) if response.getcode() == 200: data = json.loads(response.read().decode('utf-8')) current_app.logger.debug('Response data: %s' % data) except Exception: current_app.logger.exception('Exception when checking for update') if data is not None and \ data[config.UPGRADE_CHECK_KEY]['version_int'] > \ config.APP_VERSION_INT: msg = render_template( MODULE_NAME + "/upgrade.html", current_version=config.APP_VERSION, upgrade_version=data[config.UPGRADE_CHECK_KEY]['version'], product_name=config.APP_NAME, download_url=data[config.UPGRADE_CHECK_KEY]['download_url'] ) flash(msg, 'warning') auth_only_internal = False auth_source = [] if config.SERVER_MODE: if len(config.AUTHENTICATION_SOURCES) == 1\ and 'internal' in config.AUTHENTICATION_SOURCES: auth_only_internal = True auth_source = session['_auth_source_manager_obj'][ 'source_friendly_name'] response = Response(render_template( MODULE_NAME + "/index.html", username=current_user.username, auth_source=auth_source, is_admin=current_user.has_role("Administrator"), logout_url=_get_logout_url(), _=gettext, auth_only_internal=auth_only_internal )) # Set the language cookie after login, so next time the user will have that # same option at the login time. misc_preference = Preferences.module('misc') user_languages = misc_preference.preference( 'user_language' ) language = 'en' if user_languages: language = user_languages.get() or 'en' domain = dict() if config.COOKIE_DEFAULT_DOMAIN and\ config.COOKIE_DEFAULT_DOMAIN != 'localhost': domain['domain'] = config.COOKIE_DEFAULT_DOMAIN response.set_cookie("PGADMIN_LANGUAGE", value=language, path=config.COOKIE_DEFAULT_PATH, **domain) return response
def panel(trans_id, is_query_tool, editor_title): """ This method calls index.html to render the data grid. Args: trans_id: unique transaction id is_query_tool: True if panel calls when query tool menu is clicked. editor_title: Title of the editor """ # Let's fetch Script type URL from request if request.args and request.args['query_url'] != '': sURL = request.args['query_url'] else: sURL = None # Fetch server type from request if request.args and request.args['server_type'] != '': server_type = request.args['server_type'] else: server_type = None # We need client OS information to render correct Keyboard shortcuts user_agent = UserAgent(request.headers.get('User-Agent')) """ Animations and transitions are not automatically GPU accelerated and by default use browser's slow rendering engine. We need to set 'translate3d' value of '-webkit-transform' property in order to use GPU. After applying this property under linux, Webkit calculates wrong position of the elements so panel contents are not visible. To make it work, we need to explicitly set '-webkit-transform' property to 'none' for .ajs-notifier, .ajs-message, .ajs-modal classes. This issue is only with linux runtime application and observed in Query tool and debugger. When we open 'Open File' dialog then whole Query-tool panel content is not visible though it contains HTML element in back end. The port number should have already been set by the runtime if we're running in desktop mode. """ is_linux_platform = False from sys import platform as _platform if "linux" in _platform: is_linux_platform = True pref = Preferences.module('sqleditor') if pref.preference('new_browser_tab').get(): new_browser_tab = 'true' else: new_browser_tab = 'false' if is_query_tool == 'true': prompt_save_changes = pref.preference( 'prompt_save_query_changes').get() else: prompt_save_changes = pref.preference('prompt_save_data_changes').get() # Fetch the server details # bgcolor = None fgcolor = None if str(trans_id) in session['gridData']: # Fetch the object for the specified transaction id. # Use pickle.loads function to get the command object session_obj = session['gridData'][str(trans_id)] trans_obj = pickle.loads(session_obj['command_obj']) s = Server.query.filter_by(id=trans_obj.sid).first() if s and s.bgcolor: # If background is set to white means we do not have to change the # title background else change it as per user specified background if s.bgcolor != '#ffffff': bgcolor = s.bgcolor fgcolor = s.fgcolor or 'black' return render_template( "datagrid/index.html", _=gettext, uniqueId=trans_id, is_query_tool=is_query_tool, editor_title=editor_title, script_type_url=sURL, is_desktop_mode=app.PGADMIN_RUNTIME, is_linux=is_linux_platform, is_new_browser_tab=new_browser_tab, server_type=server_type, client_platform=user_agent.platform, bgcolor=bgcolor, fgcolor=fgcolor, # convert python boolean value to equivalent js boolean literal before # passing it to html template. prompt_save_changes='true' if prompt_save_changes else 'false')
def preferences(module=None, preference=None): """Fetch all/or requested preferences of pgAdmin IV.""" if module is not None and preference is not None: try: m = Preferences.module(module, create=False) if m is None: return Response(status=404) p = m.preference(preference) if p is None: return Response(status=404) return ajax_response( response=p.to_json(), status=200 ) except Exception as e: return internal_server_error(errormsg=str(e)) # Load Preferences pref = Preferences.preferences() res = [] def label(p): return gettext(p['label']) for m in pref: if len(m['categories']): om = { "id": m['id'], "label": gettext(m['label']), "inode": True, "open": True, "branch": [] } for c in m['categories']: for p in c['preferences']: if 'label' in p and p['label'] is not None: p['label'] = gettext(p['label']) if 'help_str' in p and p['help_str'] is not None: p['help_str'] = gettext(p['help_str']) oc = { "id": c['id'], "mid": m['id'], "label": gettext(c['label']), "inode": False, "open": False, "preferences": sorted(c['preferences'], key=label) } (om['branch']).append(oc) om['branch'] = sorted(om['branch'], key=label) res.append(om) return ajax_response( response=sorted(res, key=label), status=200 )
def properties(self, gid, sid, did, scid, tid): """ This function will show the properties of the selected table node. Args: gid: Server Group ID sid: Server ID did: Database ID scid: Schema ID scid: Schema ID tid: Table ID Returns: JSON of selected table node """ SQL = render_template( "/".join([self.table_template_path, 'properties.sql']), did=did, scid=scid, tid=tid, datlastsysoid=self.datlastsysoid ) status, res = self.conn.execute_dict(SQL) if not status: return internal_server_error(errormsg=res) if len(res['rows']) == 0: return gone(gettext("The specified table could not be found.")) # We will check the threshold set by user before executing # the query because that can cause performance issues # with large result set pref = Preferences.module('browser') table_row_count_pref = pref.preference('table_row_count_threshold') table_row_count_threshold = table_row_count_pref.get() estimated_row_count = int(res['rows'][0].get('reltuples', 0)) # If estimated rows are greater than threshold then if estimated_row_count and \ estimated_row_count > table_row_count_threshold: res['rows'][0]['rows_cnt'] = str(table_row_count_threshold) + '+' # If estimated rows is lower than threshold then calculate the count elif estimated_row_count and \ table_row_count_threshold >= estimated_row_count: SQL = render_template( "/".join( [self.table_template_path, 'get_table_row_count.sql'] ), data=res['rows'][0] ) status, count = self.conn.execute_scalar(SQL) if not status: return internal_server_error(errormsg=count) res['rows'][0]['rows_cnt'] = count # If estimated_row_count is zero then set the row count with same elif not estimated_row_count: res['rows'][0]['rows_cnt'] = estimated_row_count return super(TableView, self).properties( gid, sid, did, scid, tid, res )
def compare_dictionaries(**kwargs): """ This function will compare the two dictionaries. :param kwargs: :return: """ view_object = kwargs.get('view_object') source_params = kwargs.get('source_params') target_params = kwargs.get('target_params') target_schema = kwargs.get('target_schema') group_name = kwargs.get('group_name') source_dict = kwargs.get('source_dict') target_dict = kwargs.get('target_dict') node = kwargs.get('node') node_label = kwargs.get('node_label') ignore_keys = kwargs.get('ignore_keys', None) source_schema_name = kwargs.get('source_schema_name') dict1 = copy.deepcopy(source_dict) dict2 = copy.deepcopy(target_dict) # Find the duplicate keys in both the dictionaries dict1_keys = set(dict1.keys()) dict2_keys = set(dict2.keys()) intersect_keys = dict1_keys.intersection(dict2_keys) # Add gid to the params source_params['gid'] = target_params['gid'] = 1 # Keys that are available in source and missing in target. added = dict1_keys - dict2_keys source_only = _get_source_list(added=added, source_dict=source_dict, node=node, source_params=source_params, view_object=view_object, node_label=node_label, group_name=group_name, source_schema_name=source_schema_name, target_schema=target_schema) target_only = [] # Keys that are available in target and missing in source. removed = dict2_keys - dict1_keys target_only = _get_target_list(removed, target_dict, node, target_params, view_object, node_label, group_name) pref = Preferences.module('schema_diff') ignore_owner = pref.preference('ignore_owner').get() # if ignore_owner if True then add all the possible owner keys to the # ignore keys. if ignore_owner: owner_keys = [ 'owner', 'eventowner', 'funcowner', 'fdwowner', 'fsrvowner', 'lanowner', 'relowner', 'seqowner', 'typeowner' ] ignore_keys = ignore_keys + owner_keys # Compare the values of duplicates keys. other_param = { "dict1": dict1, "dict2": dict2, "ignore_keys": ignore_keys, "source_params": source_params, "target_params": target_params, "group_name": group_name, "target_schema": target_schema } identical, different = _get_identical_and_different_list( intersect_keys, source_dict, target_dict, node, node_label, view_object, **other_param) return source_only + target_only + different + identical
def compare(trans_id, source_sid, source_did, source_scid, target_sid, target_did, target_scid): """ This function will compare the two schemas. """ # Check the transaction and connection status status, error_msg, diff_model_obj, session_obj = \ check_transaction_status(trans_id) if error_msg == gettext('Transaction ID not found in the session.'): return make_json_response(success=0, errormsg=error_msg, status=404) # Server version compatibility check status, msg = check_version_compatibility(source_sid, target_sid) if not status: return make_json_response(success=0, errormsg=msg, status=428) comparison_result = [] diff_model_obj.set_comparison_info(gettext("Comparing objects..."), 0) update_session_diff_transaction(trans_id, session_obj, diff_model_obj) try: pref = Preferences.module('schema_diff') ignore_whitespaces = pref.preference('ignore_whitespaces').get() all_registered_nodes = SchemaDiffRegistry.get_registered_nodes() node_percent = round(100 / len(all_registered_nodes)) total_percent = 0 for node_name, node_view in all_registered_nodes.items(): view = SchemaDiffRegistry.get_node_view(node_name) if hasattr(view, 'compare'): msg = gettext('Comparing {0}').\ format(gettext(view.blueprint.collection_label)) diff_model_obj.set_comparison_info(msg, total_percent) # Update the message and total percentage in session object update_session_diff_transaction(trans_id, session_obj, diff_model_obj) res = view.compare(source_sid=source_sid, source_did=source_did, source_scid=source_scid, target_sid=target_sid, target_did=target_did, target_scid=target_scid, ignore_whitespaces=ignore_whitespaces) if res is not None: comparison_result = comparison_result + res total_percent = total_percent + node_percent msg = gettext("Successfully compare the specified schemas.") total_percent = 100 diff_model_obj.set_comparison_info(msg, total_percent) # Update the message and total percentage done in session object update_session_diff_transaction(trans_id, session_obj, diff_model_obj) except Exception as e: app.logger.exception(e) return make_json_response(data=comparison_result)
def are_dictionaries_identical(source_dict, target_dict, ignore_keys): """ This function is used to recursively compare two dictionaries with same keys. :param source_dict: source dict :param target_dict: target dict :param ignore_keys: ignore keys to compare :return: """ pref = Preferences.module('schema_diff') ignore_whitespaces = pref.preference('ignore_whitespaces').get() src_keys = set(source_dict.keys()) tar_keys = set(target_dict.keys()) # Keys that are available in source and missing in target. src_only = src_keys - tar_keys # Keys that are available in target and missing in source. tar_only = tar_keys - src_keys # If number of keys are different in source and target then # return False if len(src_only) != len(tar_only): current_app.logger.debug("Schema Diff: Number of keys are different " "in source and target") return False # If number of keys are same but key is not present in target then # return False for key in src_only: if key not in tar_only: current_app.logger.debug( "Schema Diff: Number of keys are same but key is not" " present in target") return False for key in source_dict.keys(): # Continue if key is available in ignore_keys if key in ignore_keys: continue if isinstance(source_dict[key], dict): if not are_dictionaries_identical(source_dict[key], target_dict[key], ignore_keys): return False elif isinstance(source_dict[key], list): # Sort the source and target list on the basis of # list key array. source_dict[key], target_dict[key] = sort_list( source_dict[key], target_dict[key]) # Compare the source and target lists if not are_lists_identical(source_dict[key], target_dict[key], ignore_keys): return False else: source_value = source_dict[key] target_value = target_dict[key] # Check if ignore whitespaces or not. source_value, target_value = check_for_ignore_whitespaces( ignore_whitespaces, source_value, target_value) # We need a proper solution as sometimes we observe that # source_value is '' and target_value is None or vice versa # in such situation we shown the comparison as different # which is wrong. if (source_value == '' and target_value is None) or \ (source_value is None and target_value == ''): continue if source_value != target_value: current_app.logger.debug( "Schema Diff: Object name: '{0}', Source Value: '{1}', " "Target Value: '{2}', Key: '{3}'".format( source_dict['name'] if 'name' in source_dict else '', source_value, target_value, key)) return False return True
def index(): """Render and process the main browser window.""" # Register Gravatar module with the app only if required if config.SHOW_GRAVATAR_IMAGE: Gravatar(current_app, size=100, rating='g', default='retro', force_default=False, use_ssl=True, base_url=None) # Get the current version info from the website, and flash a message if # the user is out of date, and the check is enabled. if config.UPGRADE_CHECK_ENABLED: data = None url = '%s?version=%s' % (config.UPGRADE_CHECK_URL, config.APP_VERSION) current_app.logger.debug('Checking version data at: %s' % url) try: # Do not wait for more than 5 seconds. # It stuck on rendering the browser.html, while working in the # broken network. if os.path.exists(config.CA_FILE): response = urlreq.urlopen(url, data, 5, cafile=config.CA_FILE) else: response = urlreq.urlopen(url, data, 5) current_app.logger.debug('Version check HTTP response code: %d' % response.getcode()) if response.getcode() == 200: data = json.loads(response.read().decode('utf-8')) current_app.logger.debug('Response data: %s' % data) except Exception: current_app.logger.exception('Exception when checking for update') if data is not None: if data[config.UPGRADE_CHECK_KEY]['version_int'] > \ config.APP_VERSION_INT: msg = render_template( MODULE_NAME + "/upgrade.html", current_version=config.APP_VERSION, upgrade_version=data[config.UPGRADE_CHECK_KEY]['version'], product_name=config.APP_NAME, download_url=data[ config.UPGRADE_CHECK_KEY]['download_url']) flash(msg, 'warning') auth_only_internal = False auth_source = [] if config.SERVER_MODE: if len(config.AUTHENTICATION_SOURCES) == 1\ and 'internal' in config.AUTHENTICATION_SOURCES: auth_only_internal = True auth_source = session['_auth_source_manager_obj'][ 'source_friendly_name'] response = Response( render_template(MODULE_NAME + "/index.html", username=current_user.username, auth_source=auth_source, is_admin=current_user.has_role("Administrator"), logout_url=_get_logout_url(), _=gettext, auth_only_internal=auth_only_internal)) # Set the language cookie after login, so next time the user will have that # same option at the login time. misc_preference = Preferences.module('misc') user_languages = misc_preference.preference('user_language') language = 'en' if user_languages: language = user_languages.get() or 'en' domain = dict() if config.COOKIE_DEFAULT_DOMAIN and\ config.COOKIE_DEFAULT_DOMAIN != 'localhost': domain['domain'] = config.COOKIE_DEFAULT_DOMAIN response.set_cookie("PGADMIN_LANGUAGE", value=language, path=config.COOKIE_DEFAULT_PATH, **domain) return response
def index(sid=None, did=None): """ Renders the welcome, server or database dashboard Args: sid: Server ID did: Database ID Returns: Welcome/Server/database dashboard """ rates = {} settings = {} prefs = Preferences.module('dashboards') # Get the server version if sid is not None: g.manager = get_driver( PG_DEFAULT_DRIVER).connection_manager(sid) g.conn = g.manager.connection() g.version = g.manager.version if not g.conn.connected(): g.version = 0 session_stats_refresh_pref = prefs.preference('session_stats_refresh') rates['session_stats_refresh'] = session_stats_refresh_pref.get() tps_stats_refresh_pref = prefs.preference('tps_stats_refresh') rates['tps_stats_refresh'] = tps_stats_refresh_pref.get() ti_stats_refresh_pref = prefs.preference('ti_stats_refresh') rates['ti_stats_refresh'] = ti_stats_refresh_pref.get() to_stats_refresh_pref = prefs.preference('to_stats_refresh') rates['to_stats_refresh'] = to_stats_refresh_pref.get() bio_stats_refresh_pref = prefs.preference('bio_stats_refresh') rates['bio_stats_refresh'] = bio_stats_refresh_pref.get() # Whether to display graphs and server activity preferences show_graphs_pref = prefs.preference('show_graphs') settings['show_graphs'] = show_graphs_pref.get() show_activity_pref = prefs.preference('show_activity') settings['show_activity'] = show_activity_pref.get() # Show the appropriate dashboard based on the identifiers passed to us if sid is None and did is None: return render_template('/dashboard/welcome_dashboard.html') if did is None: return render_template( '/dashboard/server_dashboard.html', sid=sid, rates=rates, version=g.version, settings=settings, server_type='hawq' if 'HAWQ'in g.manager.ver else g.manager.server_type ) else: return render_template( '/dashboard/database_dashboard.html', sid=sid, did=did, rates=rates, version=g.version, settings=settings, server_type='hawq' if 'HAWQ' in g.manager.ver else g.manager.server_type )
def utils(): layout = get_setting('Browser/Layout', default='') snippets = [] prefs = Preferences.module('paths') pg_help_path_pref = prefs.preference('pg_help_path') pg_help_path = pg_help_path_pref.get() edbas_help_path_pref = prefs.preference('edbas_help_path') edbas_help_path = edbas_help_path_pref.get() # Get sqleditor options prefs = Preferences.module('sqleditor') editor_tab_size_pref = prefs.preference('tab_size') editor_tab_size = editor_tab_size_pref.get() editor_use_spaces_pref = prefs.preference('use_spaces') editor_use_spaces = editor_use_spaces_pref.get() editor_wrap_code_pref = prefs.preference('wrap_code') editor_wrap_code = editor_wrap_code_pref.get() brace_matching_pref = prefs.preference('brace_matching') brace_matching = brace_matching_pref.get() insert_pair_brackets_perf = prefs.preference('insert_pair_brackets') insert_pair_brackets = insert_pair_brackets_perf.get() # This will be opposite of use_space option editor_indent_with_tabs = False if editor_use_spaces else True # Try to fetch current libpq version from the driver try: from config import PG_DEFAULT_DRIVER from pgadmin.utils.driver import get_driver driver = get_driver(PG_DEFAULT_DRIVER) pg_libpq_version = driver.libpq_version() except Exception: pg_libpq_version = 0 for submodule in current_blueprint.submodules: snippets.extend(submodule.jssnippets) return make_response( render_template('browser/js/utils.js', layout=layout, jssnippets=snippets, pg_help_path=pg_help_path, edbas_help_path=edbas_help_path, editor_tab_size=editor_tab_size, editor_use_spaces=editor_use_spaces, editor_wrap_code=editor_wrap_code, editor_brace_matching=brace_matching, editor_insert_pair_brackets=insert_pair_brackets, editor_indent_with_tabs=editor_indent_with_tabs, app_name=config.APP_NAME, app_version_int=config.APP_VERSION_INT, pg_libpq_version=pg_libpq_version, support_ssh_tunnel=config.SUPPORT_SSH_TUNNEL, logout_url=_get_logout_url()), 200, {'Content-Type': MIMETYPE_APP_JS})
def _init_query_tool(trans_id, connect, sgid, sid, did, **kwargs): # Create asynchronous connection using random connection id. conn_id = str(random.randint(1, 9999999)) manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid) if did is None: did = manager.did try: command_obj = ObjectRegistry.get_object('query_tool', conn_id=conn_id, sgid=sgid, sid=sid, did=did) except Exception as e: app.logger.error(e) return True, internal_server_error(errormsg=str(e)), '', '' try: conn = manager.connection(did=did, conn_id=conn_id, auto_reconnect=False, use_binary_placeholder=True, array_to_string=True) if connect: status, msg, is_ask_password, user, role, password = _connect( conn, **kwargs) if not status: app.logger.error(msg) if is_ask_password: server = Server.query.filter_by(id=sid).first() return True, make_json_response( success=0, status=428, result=render_template( 'servers/password.html', server_label=server.name, username=user, errmsg=msg, _=gettext, )), '', '' else: return True, internal_server_error( errormsg=str(msg)), '', '' except (ConnectionLost, SSHTunnelConnectionLost) as e: app.logger.error(e) raise except Exception as e: app.logger.error(e) return True, internal_server_error(errormsg=str(e)), '', '' if 'gridData' not in session: sql_grid_data = dict() else: sql_grid_data = session['gridData'] # Set the value of auto commit and auto rollback specified in Preferences pref = Preferences.module('sqleditor') command_obj.set_auto_commit(pref.preference('auto_commit').get()) command_obj.set_auto_rollback(pref.preference('auto_rollback').get()) # Use pickle to store the command object which will be used # later by the sql grid module. sql_grid_data[str(trans_id)] = { # -1 specify the highest protocol version available 'command_obj': pickle.dumps(command_obj, -1) } # Store the grid dictionary into the session variable session['gridData'] = sql_grid_data return False, '', conn_id, manager.version
def __init__(self, **kwargs): """ This method is used to initialize the class. Args: **kwargs : N number of parameters """ self.sid = kwargs['sid'] if 'sid' in kwargs else None self.conn = kwargs['conn'] if 'conn' in kwargs else None self.keywords = [] self.databases = [] self.functions = [] self.datatypes = [] self.dbmetadata = { 'tables': {}, 'views': {}, 'functions': {}, 'datatypes': {} } self.text_before_cursor = None self.name_pattern = re.compile("^[_a-z][_a-z0-9\$]*$") manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(self.sid) # we will set template path for sql scripts self.sql_path = 'sqlautocomplete/sql/#{0}#'.format(manager.version) self.search_path = [] schema_names = [] if self.conn.connected(): # Fetch the search path query = render_template("/".join([self.sql_path, 'schema.sql']), search_path=True) status, res = self.conn.execute_dict(query) if status: for record in res['rows']: self.search_path.append(record['schema']) # Fetch the schema names query = render_template("/".join([self.sql_path, 'schema.sql'])) status, res = self.conn.execute_dict(query) if status: for record in res['rows']: schema_names.append(record['schema']) pref = Preferences.module('sqleditor') keywords_in_uppercase = \ pref.preference('keywords_in_uppercase').get() # Fetch the keywords query = render_template("/".join([self.sql_path, 'keywords.sql'])) # If setting 'Keywords in uppercase' is set to True in # Preferences then fetch the keywords in upper case. if keywords_in_uppercase: query = render_template("/".join( [self.sql_path, 'keywords.sql']), upper_case=True) status, res = self.conn.execute_dict(query) if status: for record in res['rows']: # 'public' is a keyword in EPAS database server. Don't add # this into the list of keywords. # This is a hack to fix the issue in autocomplete. if record['word'].lower() == 'public': continue self.keywords.append(record['word']) self.prioritizer = PrevalenceCounter(self.keywords) self.reserved_words = set() for x in self.keywords: self.reserved_words.update(x.split()) self.all_completions = set(self.keywords) self.extend_schemata(schema_names) # Below are the configurable options in pgcli which we don't have # in pgAdmin4 at the moment. Setting the default value from the pgcli's # config file. self.signature_arg_style = '{arg_name} {arg_type}' self.call_arg_style = '{arg_name: <{max_arg_len}} := {arg_default}' self.call_arg_display_style = '{arg_name}' self.call_arg_oneliner_max = 2 self.search_path_filter = True self.generate_aliases = False self.insert_col_skip_patterns = [ re.compile(r'^now\(\)$'), re.compile(r'^nextval\(') ] self.qualify_columns = 'if_more_than_one_table' self.asterisk_column_order = 'table_order'
def utils(): layout = get_setting('Browser/Layout', default='') snippets = [] prefs = Preferences.module('paths') pg_help_path_pref = prefs.preference('pg_help_path') pg_help_path = pg_help_path_pref.get() edbas_help_path_pref = prefs.preference('edbas_help_path') edbas_help_path = edbas_help_path_pref.get() # Get sqleditor options prefs = Preferences.module('sqleditor') editor_tab_size_pref = prefs.preference('tab_size') editor_tab_size = editor_tab_size_pref.get() editor_use_spaces_pref = prefs.preference('use_spaces') editor_use_spaces = editor_use_spaces_pref.get() editor_wrap_code_pref = prefs.preference('wrap_code') editor_wrap_code = editor_wrap_code_pref.get() brace_matching_pref = prefs.preference('brace_matching') brace_matching = brace_matching_pref.get() insert_pair_brackets_perf = prefs.preference('insert_pair_brackets') insert_pair_brackets = insert_pair_brackets_perf.get() # This will be opposite of use_space option editor_indent_with_tabs = False if editor_use_spaces else True # Try to fetch current libpq version from the driver try: from config import PG_DEFAULT_DRIVER from pgadmin.utils.driver import get_driver driver = get_driver(PG_DEFAULT_DRIVER) pg_libpq_version = driver.libpq_version() except Exception as e: pg_libpq_version = 0 for submodule in current_blueprint.submodules: snippets.extend(submodule.jssnippets) return make_response( render_template( 'browser/js/utils.js', layout=layout, jssnippets=snippets, pg_help_path=pg_help_path, edbas_help_path=edbas_help_path, editor_tab_size=editor_tab_size, editor_use_spaces=editor_use_spaces, editor_wrap_code=editor_wrap_code, editor_brace_matching=brace_matching, editor_insert_pair_brackets=insert_pair_brackets, editor_indent_with_tabs=editor_indent_with_tabs, app_name=config.APP_NAME, pg_libpq_version=pg_libpq_version, support_ssh_tunnel=config.SUPPORT_SSH_TUNNEL ), 200, {'Content-Type': 'application/x-javascript'})
def index(): """Render and process the main browser window.""" # Get the Gravatar Gravatar(current_app, size=100, rating='g', default='retro', force_default=False, use_ssl=True, base_url=None) msg = None # Get the current version info from the website, and flash a message if # the user is out of date, and the check is enabled. if config.UPGRADE_CHECK_ENABLED: data = None url = '%s?version=%s' % (config.UPGRADE_CHECK_URL, config.APP_VERSION) current_app.logger.debug('Checking version data at: %s' % url) try: # Do not wait for more than 5 seconds. # It stuck on rendering the browser.html, while working in the # broken network. response = urlreq.urlopen(url, data, 5) current_app.logger.debug('Version check HTTP response code: %d' % response.getcode()) if response.getcode() == 200: data = json.loads(response.read().decode('utf-8')) current_app.logger.debug('Response data: %s' % data) except: current_app.logger.exception('Exception when checking for update') if data is not None: if data['pgadmin4']['version_int'] > config.APP_VERSION_INT: msg = render_template( MODULE_NAME + "/upgrade.html", current_version=config.APP_VERSION, upgrade_version=data['pgadmin4']['version'], product_name=config.APP_NAME, download_url=data['pgadmin4']['download_url']) flash(msg, 'warning') response = Response( render_template(MODULE_NAME + "/index.html", username=current_user.email, is_admin=current_user.has_role("Administrator"), _=gettext)) # Set the language cookie after login, so next time the user will have that # same option at the login time. misc_preference = Preferences.module('miscellaneous') user_languages = misc_preference.preference('user_language') language = 'en' if user_languages: language = user_languages.get() or 'en' response.set_cookie("PGADMIN_LANGUAGE", language) return response
def index(sid=None, did=None): """ Renders the welcome, server or database dashboard Args: sid: Server ID did: Database ID Returns: Welcome/Server/database dashboard """ rates = {} settings = {} prefs = Preferences.module('dashboards') # Get the server version if sid is not None: g.manager = get_driver( PG_DEFAULT_DRIVER).connection_manager(sid) g.conn = g.manager.connection() g.version = g.manager.version if not g.conn.connected(): g.version = 0 session_stats_refresh_pref = prefs.preference('session_stats_refresh') rates['session_stats_refresh'] = session_stats_refresh_pref.get() tps_stats_refresh_pref = prefs.preference('tps_stats_refresh') rates['tps_stats_refresh'] = tps_stats_refresh_pref.get() ti_stats_refresh_pref = prefs.preference('ti_stats_refresh') rates['ti_stats_refresh'] = ti_stats_refresh_pref.get() to_stats_refresh_pref = prefs.preference('to_stats_refresh') rates['to_stats_refresh'] = to_stats_refresh_pref.get() bio_stats_refresh_pref = prefs.preference('bio_stats_refresh') rates['bio_stats_refresh'] = bio_stats_refresh_pref.get() # Whether to display graphs and server activity preferences show_graphs_pref = prefs.preference('show_graphs') settings['show_graphs'] = show_graphs_pref.get() show_activity_pref = prefs.preference('show_activity') settings['show_activity'] = show_activity_pref.get() # Show the appropriate dashboard based on the identifiers passed to us if sid is None and did is None: return render_template('/dashboard/welcome_dashboard.html') if did is None: return render_template( '/dashboard/server_dashboard.html', sid=sid, rates=rates, version=g.version, settings=settings ) else: return render_template( '/dashboard/database_dashboard.html', sid=sid, did=did, rates=rates, version=g.version, settings=settings )