Example #1
0
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)
Example #2
0
    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
        )
Example #3
0
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()
Example #4
0
 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'
     )
Example #5
0
 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'
     )
Example #6
0
    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)
Example #7
0
 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')
     )
Example #8
0
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'})
Example #9
0
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"
    )
Example #10
0
    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')
        )
Example #11
0
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'})
Example #12
0
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
Example #13
0
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
Example #14
0
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'})
Example #15
0
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()
Example #16
0
    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
Example #17
0
    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'
Example #18
0
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
    })
Example #19
0
    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)
Example #20
0
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
Example #21
0
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,
    })
Example #22
0
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
Example #23
0
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()
Example #24
0
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)
Example #25
0
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
    })
Example #26
0
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
        },
    }
Example #27
0
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
Example #28
0
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')
Example #29
0
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
    )
Example #30
0
    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
        )
Example #31
0
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
Example #32
0
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)
Example #33
0
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
Example #34
0
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
Example #35
0
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
        )
Example #36
0
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})
Example #37
0
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
Example #38
0
    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'
Example #39
0
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'})
Example #40
0
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
Example #41
0
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
        )