Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
__init__.py308 linesDownload Raw Back to misc
1##########################################################################2#3# pgAdmin 4 - PostgreSQL Tools4#5# Copyright (C) 2013 - 2024, The pgAdmin Development Team6# This software is released under the PostgreSQL Licence7#8##########################################################################9 10"""A blueprint module providing utility functions for the application."""11 12from pgadmin.utils import driver13from flask import render_template, Response, request, current_app14from flask.helpers import url_for15from flask_babel import gettext16from pgadmin.user_login_check import pga_login_required17from pathlib import Path18from pgadmin.utils import PgAdminModule, replace_binary_path, \19    get_binary_path_versions20from pgadmin.utils.csrf import pgCSRFProtect21from pgadmin.utils.session import cleanup_session_files22from pgadmin.misc.themes import get_all_themes23from pgadmin.utils.constants import MIMETYPE_APP_JS, UTILITIES_ARRAY24from pgadmin.utils.ajax import precondition_required, make_json_response, \25    internal_server_error26from pgadmin.utils.heartbeat import log_server_heartbeat, \27    get_server_heartbeat, stop_server_heartbeat28import config29import time30import json31import os32from urllib.request import urlopen33from pgadmin.settings import get_setting, store_setting34 35MODULE_NAME = 'misc'36 37 38class MiscModule(PgAdminModule):39    LABEL = gettext('Miscellaneous')40 41    def register_preferences(self):42        """43        Register preferences for this module.44        """45        lang_options = []46        for lang in config.LANGUAGES:47            lang_options.append(48                {49                    'label': config.LANGUAGES[lang],50                    'value': lang51                }52            )53 54        # Register options for the User language settings55        self.preference.register(56            'user_language', 'user_language',57            gettext("User language"), 'options', 'en',58            category_label=gettext('User language'),59            options=lang_options,60            control_props={61                'allowClear': False,62            }63        )64 65        theme_options = []66 67        for theme, theme_data in (get_all_themes()).items():68            theme_options.append({69                'label': theme_data['disp_name']70                .replace('_', ' ')71                .replace('-', ' ')72                .title(),73                'value': theme,74                'preview_src': url_for(75                    'static', filename='js/generated/img/' +76                                       theme_data['preview_img']77                )78            })79 80        self.preference.register(81            'themes', 'theme',82            gettext("Theme"), 'options', 'standard',83            category_label=gettext('Themes'),84            options=theme_options,85            control_props={86                'allowClear': False,87            },88            help_str=gettext(89                'A refresh is required to apply the theme. Above is the '90                'preview of the theme'91            )92        )93 94    def get_exposed_url_endpoints(self):95        """96        Returns:97            list: a list of url endpoints exposed to the client.98        """99        return ['misc.ping', 'misc.index', 'misc.cleanup',100                'misc.validate_binary_path', 'misc.log_heartbeat',101                'misc.stop_heartbeat', 'misc.get_heartbeat',102                'misc.upgrade_check']103 104    def register(self, app, options):105        """106        Override the default register function to automagically register107        sub-modules at once.108        """109        from .bgprocess import blueprint as module110        self.submodules.append(module)111 112        from .cloud import blueprint as module113        self.submodules.append(module)114 115        from .dependencies import blueprint as module116        self.submodules.append(module)117 118        from .dependents import blueprint as module119        self.submodules.append(module)120 121        from .file_manager import blueprint as module122        self.submodules.append(module)123 124        from .statistics import blueprint as module125        self.submodules.append(module)126 127        super().register(app, options)128 129 130# Initialise the module131blueprint = MiscModule(MODULE_NAME, __name__)132 133 134##########################################################################135# A special URL used to "ping" the server136##########################################################################137@blueprint.route("/", endpoint='index')138def index():139    return ''140 141 142##########################################################################143# A special URL used to "ping" the server144##########################################################################145@blueprint.route("/ping")146@pgCSRFProtect.exempt147def ping():148    """Generate a "PING" response to indicate that the server is alive."""149    return "PING"150 151 152# For Garbage Collecting closed connections153@blueprint.route("/cleanup", methods=['POST'])154@pgCSRFProtect.exempt155def cleanup():156    driver.ping()157    # Cleanup session files.158    cleanup_session_files()159    return ""160 161 162@blueprint.route("/heartbeat/log", methods=['POST'])163@pgCSRFProtect.exempt164def log_heartbeat():165    data = None166    if hasattr(request.data, 'decode'):167        data = request.data.decode('utf-8')168 169    if data != '':170        data = json.loads(data)171 172    status, msg = log_server_heartbeat(data)173    if status:174        return make_json_response(data=msg, status=200)175    else:176        return make_json_response(data=msg, status=404)177 178 179@blueprint.route("/heartbeat/stop", methods=['POST'])180@pgCSRFProtect.exempt181def stop_heartbeat():182    data = None183    if hasattr(request.data, 'decode'):184        data = request.data.decode('utf-8')185 186    if data != '':187        data = json.loads(data)188 189    _, msg = stop_server_heartbeat(data)190    return make_json_response(data=msg,191                              status=200)192 193 194@blueprint.route("/get_heartbeat/<int:sid>", methods=['GET'])195@pgCSRFProtect.exempt196def get_heartbeat(sid):197    heartbeat_data = get_server_heartbeat(sid)198    return make_json_response(data=heartbeat_data,199                              status=200)200 201 202##########################################################################203# A special URL used to shut down the server204##########################################################################205@blueprint.route("/shutdown", methods=('get', 'post'))206@pgCSRFProtect.exempt207def shutdown():208    if config.SERVER_MODE is not True:209        func = request.environ.get('werkzeug.server.shutdown')210        if func is None:211            raise RuntimeError('Not running with the Werkzeug Server')212        func()213        return 'SHUTDOWN'214    else:215        return ''216 217 218##########################################################################219# A special URL used to validate the binary path220##########################################################################221@blueprint.route("/validate_binary_path",222                 endpoint="validate_binary_path",223                 methods=["POST"])224@pga_login_required225def validate_binary_path():226    """227    This function is used to validate the specified utilities path by228    running the utilities with their versions.229    """230    data = None231    if hasattr(request.data, 'decode'):232        data = request.data.decode('utf-8')233 234    if data != '':235        data = json.loads(data)236 237    version_str = ''238 239    # Do not allow storage dir as utility path240    if 'utility_path' in data and data['utility_path'] is not None and \241        Path(config.STORAGE_DIR) != Path(data['utility_path']) and \242            Path(config.STORAGE_DIR) not in Path(data['utility_path']).parents:243        binary_versions = get_binary_path_versions(data['utility_path'])244        for utility, version in binary_versions.items():245            if version is None:246                version_str += "<b>" + utility + ":</b> " + \247                               "not found on the specified binary path.<br/>"248            else:249                version_str += "<b>" + utility + ":</b> " + version + "<br/>"250    else:251        return precondition_required(gettext('Invalid binary path.'))252 253    return make_json_response(data=gettext(version_str), status=200)254 255 256@blueprint.route("/upgrade_check", endpoint="upgrade_check",257                 methods=['GET'])258@pga_login_required259def upgrade_check():260    # Get the current version info from the website, and flash a message if261    # the user is out of date, and the check is enabled.262    ret = {263        "outdated": False,264    }265    if config.UPGRADE_CHECK_ENABLED:266        last_check = get_setting('LastUpdateCheck', default='0')267        today = time.strftime('%Y%m%d')268        if int(last_check) < int(today):269            data = None270            url = '%s?version=%s' % (271                config.UPGRADE_CHECK_URL, config.APP_VERSION)272            current_app.logger.debug('Checking version data at: %s' % url)273            try:274                # Do not wait for more than 5 seconds.275                # It stuck on rendering the browser.html, while working in the276                # broken network.277                if os.path.exists(config.CA_FILE):278                    response = urlopen(url, data, 5, cafile=config.CA_FILE)279                else:280                    response = urlopen(url, data, 5)281                current_app.logger.debug(282                    'Version check HTTP response code: %d' % response.getcode()283                )284 285                if response.getcode() == 200:286                    data = json.loads(response.read().decode('utf-8'))287                    current_app.logger.debug('Response data: %s' % data)288            except Exception:289                current_app.logger.exception(290                    'Exception when checking for update')291                return internal_server_error('Failed to check for update')292 293            if data is not None and \294                data[config.UPGRADE_CHECK_KEY]['version_int'] > \295                    config.APP_VERSION_INT:296                ret = {297                    "outdated": True,298                    "current_version": config.APP_VERSION,299                    "upgrade_version": data[config.UPGRADE_CHECK_KEY][300                        'version'],301                    "product_name": config.APP_NAME,302                    "download_url": data[config.UPGRADE_CHECK_KEY][303                        'download_url']304                }305 306        store_setting('LastUpdateCheck', today)307    return make_json_response(data=ret)308 
codekingpro/portable-devtools · Team Ai