Example #1
0
import sys
import json

import utils
import sensors
import db
import logger
import config
log = logger.get_logger(__name__)
conf = config.get_config()
import alerter

# define the web application
app = Flask(__name__, template_folder=conf["constants"]["base_dir"])
# apply gzip compression
if conf["gui"]["compress"]: Compress(app)


# render index if no page name is provided
@app.route('/')
def root():
    return render_template(conf["constants"]["web_template"])


# return favicon
@app.route('/favicon.ico')
def favicon():
    return send_from_directory(conf["constants"]["web_dir"], "favicon.ico")


# static folder (web)
Example #2
0
                 "".join(traceback.format_stack(limit=7)[:-1]))


np.seterrcall(np_err_handler)
np.seterr(all="call")

# Global variables, and also initializing the webapp using Flask framework:
path_root = "results/"
if_runningOnline = "DYNO" in os.environ  # detect whether on Heroku
# use cache only when in production mode; in other words, don't use cache on local machine
if_useCache = if_runningOnline
AUTH_CODE = "123"
# ongoingJobs = []

app = Flask(__name__)
Compress(app)  # https://github.com/libwilliam/flask-compress

# redis configuation, for SSE support:
# 'os.environ.get("REDIS_URL")' is for Heroku and "redis://localhost" is meant for localhost.
app.config["REDIS_URL"] = os.environ.get("REDIS_URL") or "redis://localhost"
app.register_blueprint(sse, url_prefix="/stream")

# load JSON schema for Puz file for validation:
with open("puzzles/schema.js") as f:
    schema = f.read()
schema = json.loads(schema)


@app.route("/plot", methods=["POST", "OPTIONS"])
def plot():
    startTime = time.time()  # start timer
Example #3
0
def configure_extensions(app):
    CORS(app, max_age=600)
    Compress(app)
Example #4
0
def create_app(app_name=None):
    # Configuration settings
    import config
    if not app_name:
        app_name = config.APP_NAME

    # Only enable password related functionality in server mode.
    if config.SERVER_MODE is True:
        # Some times we need to access these config params where application
        # context is not available (we can't use current_app.config in those
        # cases even with current_app.app_context())
        # So update these params in config itself.
        # And also these updated config values will picked up by application
        # since we are updating config before the application instance is
        # created.

        config.SECURITY_RECOVERABLE = True
        config.SECURITY_CHANGEABLE = True
        # Now we'll open change password page in alertify dialog
        # we don't want it to redirect to main page after password
        # change operation so we will open the same password change page again.
        config.SECURITY_POST_CHANGE_VIEW = 'browser.change_password'
    """Create the Flask application, startup logging and dynamically load
    additional modules (blueprints) that are found in this directory."""
    app = PgAdmin(__name__, static_url_path='/static')
    # Removes unwanted whitespace from render_template function
    app.jinja_env.trim_blocks = True
    app.config.from_object(config)
    app.config.update(dict(PROPAGATE_EXCEPTIONS=True))

    ##########################################################################
    # Setup logging and log the application startup
    ##########################################################################

    # We won't care about errors in the logging system, we are more
    # interested in application errors.
    logging.raiseExceptions = False

    # Add SQL level logging, and set the base logging level
    logging.addLevelName(25, 'SQL')
    app.logger.setLevel(logging.DEBUG)
    app.logger.handlers = []

    # We also need to update the handler on the webserver in order to see
    # request. Setting the level prevents werkzeug from setting up it's own
    # stream handler thus ensuring all the logging goes through the pgAdmin
    # logger.
    logger = logging.getLogger('werkzeug')
    logger.setLevel(config.CONSOLE_LOG_LEVEL)

    # Set SQLITE_PATH to TEST_SQLITE_PATH while running test cases
    if ('PGADMIN_TESTING_MODE' in os.environ
            and os.environ['PGADMIN_TESTING_MODE'] == '1'):
        config.SQLITE_PATH = config.TEST_SQLITE_PATH
        config.MASTER_PASSWORD_REQUIRED = False
        config.UPGRADE_CHECK_ENABLED = False

    # Ensure the various working directories exist
    from pgadmin.setup import create_app_data_directory, db_upgrade
    create_app_data_directory(config)

    # File logging
    fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8')
    fh.setLevel(config.FILE_LOG_LEVEL)
    fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT))
    app.logger.addHandler(fh)
    logger.addHandler(fh)

    # Console logging
    ch = logging.StreamHandler()
    ch.setLevel(config.CONSOLE_LOG_LEVEL)
    ch.setFormatter(logging.Formatter(config.CONSOLE_LOG_FORMAT))
    app.logger.addHandler(ch)
    logger.addHandler(ch)

    # Log the startup
    app.logger.info('########################################################')
    app.logger.info('Starting %s v%s...', config.APP_NAME, config.APP_VERSION)
    app.logger.info('########################################################')
    app.logger.debug("Python syspath: %s", sys.path)

    ##########################################################################
    # Setup i18n
    ##########################################################################

    # Initialise i18n
    babel = Babel(app)

    app.logger.debug('Available translations: %s' % babel.list_translations())

    @babel.localeselector
    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
            if current_user.is_authenticated:
                user_id = current_user.id
            else:
                user = user_datastore.get_user(config.DESKTOP_USER)
                if user is not None:
                    user_id = user.id
            user_language = Preferences.raw_value('miscellaneous',
                                                  'user_language', None,
                                                  user_id)
            if user_language is not None:
                language = user_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

    ##########################################################################
    # Setup authentication
    ##########################################################################

    app.config['SQLALCHEMY_DATABASE_URI'] = u'sqlite:///{0}?timeout={1}' \
        .format(config.SQLITE_PATH.replace(u'\\', u'/'),
                getattr(config, 'SQLITE_TIMEOUT', 500)
                )

    # Create database connection object and mailer
    db.init_app(app)

    ##########################################################################
    # Upgrade the schema (if required)
    ##########################################################################
    with app.app_context():
        # Run migration for the first time i.e. create database
        from config import SQLITE_PATH

        # If version not available, user must have aborted. Tables are not
        # created and so its an empty db
        if not os.path.exists(SQLITE_PATH) or get_version() == -1:
            db_upgrade(app)
        else:
            schema_version = get_version()

            # Run migration if current schema version is greater than the
            # schema version stored in version table
            if CURRENT_SCHEMA_VERSION >= schema_version:
                db_upgrade(app)

            # Update schema version to the latest
            if CURRENT_SCHEMA_VERSION > schema_version:
                set_version(CURRENT_SCHEMA_VERSION)
                db.session.commit()

        if os.name != 'nt':
            os.chmod(config.SQLITE_PATH, 0o600)

    Mail(app)

    import pgadmin.utils.paths as paths
    paths.init_app(app)

    # Setup Flask-Security
    user_datastore = SQLAlchemyUserDatastore(db, User, Role)
    security = Security(None, user_datastore)

    ##########################################################################
    # Setup security
    ##########################################################################
    with app.app_context():
        config.CSRF_SESSION_KEY = Keys.query.filter_by(
            name='CSRF_SESSION_KEY').first().value
        config.SECRET_KEY = Keys.query.filter_by(
            name='SECRET_KEY').first().value
        config.SECURITY_PASSWORD_SALT = Keys.query.filter_by(
            name='SECURITY_PASSWORD_SALT').first().value

    # Update the app.config with proper security keyes for signing CSRF data,
    # signing cookies, and the SALT for hashing the passwords.
    app.config.update(
        dict({
            'CSRF_SESSION_KEY': config.CSRF_SESSION_KEY,
            'SECRET_KEY': config.SECRET_KEY,
            'SECURITY_PASSWORD_SALT': config.SECURITY_PASSWORD_SALT,
            'SESSION_COOKIE_DOMAIN': config.SESSION_COOKIE_DOMAIN,
            # CSRF Token expiration till session expires
            'WTF_CSRF_TIME_LIMIT': getattr(config, 'CSRF_TIME_LIMIT', None),
            'WTF_CSRF_METHODS': ['GET', 'POST', 'PUT', 'DELETE'],
        }))

    security.init_app(app, user_datastore)

    # register custom unauthorised handler.
    app.login_manager.unauthorized_handler(pga_unauthorised)

    # Set the permanent session lifetime to the specified value in config file.
    app.permanent_session_lifetime = timedelta(
        days=config.SESSION_EXPIRATION_TIME)

    app.session_interface = create_session_interface(app,
                                                     config.SESSION_SKIP_PATHS)

    # Make the Session more secure against XSS & CSRF when running in web mode
    if config.SERVER_MODE and config.ENHANCED_COOKIE_PROTECTION:
        paranoid = Paranoid(app)
        paranoid.redirect_view = 'browser.index'

    ##########################################################################
    # Load all available server drivers
    ##########################################################################
    driver.init_app(app)

    ##########################################################################
    # Register language to the preferences after login
    ##########################################################################
    @user_logged_in.connect_via(app)
    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)

    ##########################################################################
    # Register any local servers we can discover
    ##########################################################################
    @user_logged_in.connect_via(app)
    def on_user_logged_in(sender, user):
        # Keep hold of the user ID
        user_id = user.id

        # Get the first server group for the user
        servergroup_id = 1
        servergroups = ServerGroup.query.filter_by(
            user_id=user_id).order_by("id")

        if servergroups.count() > 0:
            servergroup = servergroups.first()
            servergroup_id = servergroup.id
        '''Add a server to the config database'''
        def add_server(user_id, servergroup_id, name, superuser, port,
                       discovery_id, comment):
            # Create a server object if needed, and store it.
            servers = Server.query.filter_by(
                user_id=user_id, discovery_id=svr_discovery_id).order_by("id")

            if servers.count() > 0:
                return

            svr = Server(user_id=user_id,
                         servergroup_id=servergroup_id,
                         name=name,
                         host='localhost',
                         port=port,
                         maintenance_db='postgres',
                         username=superuser,
                         ssl_mode='prefer',
                         comment=svr_comment,
                         discovery_id=discovery_id)

            db.session.add(svr)
            db.session.commit()

        # Figure out what servers are present
        if winreg is not None:
            arch_keys = set()
            proc_arch = os.environ['PROCESSOR_ARCHITECTURE'].lower()

            try:
                proc_arch64 = os.environ['PROCESSOR_ARCHITEW6432'].lower()
            except Exception as e:
                proc_arch64 = None

            if proc_arch == 'x86' and not proc_arch64:
                arch_keys.add(0)
            elif proc_arch == 'x86' or proc_arch == 'amd64':
                arch_keys.add(winreg.KEY_WOW64_32KEY)
                arch_keys.add(winreg.KEY_WOW64_64KEY)

            for arch_key in arch_keys:
                for server_type in ('PostgreSQL', 'EnterpriseDB'):
                    try:
                        root_key = winreg.OpenKey(
                            winreg.HKEY_LOCAL_MACHINE,
                            "SOFTWARE\\" + server_type + "\Services", 0,
                            winreg.KEY_READ | arch_key)
                        for i in xrange(0, winreg.QueryInfoKey(root_key)[0]):
                            inst_id = winreg.EnumKey(root_key, i)
                            inst_key = winreg.OpenKey(root_key, inst_id)

                            svr_name = winreg.QueryValueEx(
                                inst_key, 'Display Name')[0]
                            svr_superuser = winreg.QueryValueEx(
                                inst_key, 'Database Superuser')[0]
                            svr_port = winreg.QueryValueEx(inst_key, 'Port')[0]
                            svr_discovery_id = inst_id
                            svr_comment = gettext(
                                "Auto-detected %s installation with the data "
                                "directory at %s" %
                                (winreg.QueryValueEx(inst_key,
                                                     'Display Name')[0],
                                 winreg.QueryValueEx(inst_key,
                                                     'Data Directory')[0]))

                            add_server(user_id, servergroup_id, svr_name,
                                       svr_superuser, svr_port,
                                       svr_discovery_id, svr_comment)

                            inst_key.Close()
                    except Exception as e:
                        pass
        else:
            # We use the postgres-winreg.ini file on non-Windows
            try:
                from configparser import ConfigParser
            except ImportError:
                from ConfigParser import ConfigParser  # Python 2

            registry = ConfigParser()

        try:
            registry.read('/etc/postgres-reg.ini')
            sections = registry.sections()

            # Loop the sections, and get the data from any that are PG or PPAS
            for section in sections:
                if (section.startswith('PostgreSQL/')
                        or section.startswith('EnterpriseDB/')):
                    svr_name = registry.get(section, 'Description')
                    svr_superuser = registry.get(section, 'Superuser')

                    # getint function throws exception if value is blank.
                    # Ex: Port=
                    # In such case we should handle the exception and continue
                    # to read the next section of the config file.
                    try:
                        svr_port = registry.getint(section, 'Port')
                    except ValueError:
                        continue

                    svr_discovery_id = section
                    description = registry.get(section, 'Description')
                    data_directory = registry.get(section, 'DataDirectory')
                    if hasattr(str, 'decode'):
                        description = description.decode('utf-8')
                        data_directory = data_directory.decode('utf-8')
                    svr_comment = gettext(u"Auto-detected %s installation "
                                          u"with the data directory at %s" %
                                          (description, data_directory))
                    add_server(user_id, servergroup_id, svr_name,
                               svr_superuser, svr_port, svr_discovery_id,
                               svr_comment)

        except Exception as e:
            pass

    @user_logged_in.connect_via(app)
    @user_logged_out.connect_via(app)
    def force_session_write(app, user):
        session.force_write = True

    @user_logged_in.connect_via(app)
    def store_crypt_key(app, user):
        # in desktop mode, master password is used to encrypt/decrypt
        # and is stored in the keyManager memory
        if config.SERVER_MODE:
            if 'password' in request.form:
                current_app.keyManager.set(request.form['password'])

    @user_logged_out.connect_via(app)
    def current_user_cleanup(app, user):
        from config import PG_DEFAULT_DRIVER
        from pgadmin.utils.driver import get_driver
        from flask import current_app

        # remove key
        current_app.keyManager.reset()

        for mdl in current_app.logout_hooks:
            try:
                mdl.on_logout(user)
            except Exception as e:
                current_app.logger.exception(e)

        _driver = get_driver(PG_DEFAULT_DRIVER)
        _driver.gc_own()

    ##########################################################################
    # Load plugin modules
    ##########################################################################
    for module in app.find_submodules('pgadmin'):
        app.logger.info('Registering blueprint module: %s' % module)
        app.register_blueprint(module)
        app.register_logout_hook(module)

    ##########################################################################
    # Handle the desktop login
    ##########################################################################

    @app.before_request
    def before_request():
        """Login the default user if running in desktop mode"""

        # Check the auth key is valid, if it's set, and we're not in server
        # mode, and it's not a help file request.
        if not config.SERVER_MODE and app.PGADMIN_KEY != '':
            if (('key' not in request.args
                 or request.args['key'] != app.PGADMIN_KEY)
                    and request.cookies.get('PGADMIN_KEY') != app.PGADMIN_KEY
                    and request.endpoint != 'help.static'):
                abort(401)

        if not config.SERVER_MODE and not current_user.is_authenticated:
            user = user_datastore.get_user(config.DESKTOP_USER)
            # Throw an error if we failed to find the desktop user, to give
            # the sysadmin a hint. We'll continue to try to login anyway as
            # that'll through a nice 500 error for us.
            if user is None:
                app.logger.error(
                    'The desktop user %s was not found in the configuration '
                    'database.' % config.DESKTOP_USER)
                abort(401)
            login_user(user)

        # if the server is restarted the in memory key will be lost
        # but the user session may still be active. Logout the user
        # to get the key again when login
        if config.SERVER_MODE and current_user.is_authenticated:
            if current_app.keyManager.get() is None and \
                    request.endpoint not in ('security.login',
                                             'security.logout'):
                logout_user()

    @app.after_request
    def after_request(response):
        if 'key' in request.args:
            domain = dict()
            if config.COOKIE_DEFAULT_DOMAIN and \
                    config.COOKIE_DEFAULT_DOMAIN != 'localhost':
                domain['domain'] = config.COOKIE_DEFAULT_DOMAIN
            response.set_cookie('PGADMIN_KEY',
                                value=request.args['key'],
                                path=config.COOKIE_DEFAULT_PATH,
                                **domain)

        # X-Frame-Options for security
        if config.X_FRAME_OPTIONS != "" and \
                config.X_FRAME_OPTIONS.lower() != "deny":
            response.headers["X-Frame-Options"] = config.X_FRAME_OPTIONS

        return response

    ##########################################################################
    # Cache busting
    ##########################################################################

    # Version number to be added to all static file url requests
    # This is used by url_for function when generating urls
    # This will solve caching issues when application is upgrading
    # This is called - Cache Busting
    @app.url_defaults
    def add_internal_version(endpoint, values):
        extensions = config.APP_VERSION_EXTN

        # Add the internal version only if it is set
        if config.APP_VERSION_PARAM is not None and \
           config.APP_VERSION_PARAM != '':
            # If there is a filename, add the version
            if 'filename' in values \
               and values['filename'].endswith(extensions):
                values[config.APP_VERSION_PARAM] = config.APP_VERSION_INT
            else:
                # Sometimes there may be direct endpoint for some files
                # There will be only one rule for such endpoints
                urls = [url for url in app.url_map.iter_rules(endpoint)]
                if len(urls) == 1 and urls[0].rule.endswith(extensions):
                    values[config.APP_VERSION_PARAM] = \
                        config.APP_VERSION_INT

    # Strip away internal version param before sending further to app as it was
    # required for cache busting only
    @app.url_value_preprocessor
    def strip_version_number(endpoint, values):
        if values and config.APP_VERSION_PARAM in values:
            values.pop(config.APP_VERSION_PARAM)

    ##########################################################################
    # Minify output. Not required in desktop mode
    ##########################################################################
    if not config.DEBUG and config.SERVER_MODE:
        from flask_compress import Compress
        Compress(app)

    @app.context_processor
    def inject_blueprint():
        """Inject a reference to the current blueprint, if any."""
        return {
            'current_app': current_app,
            'current_blueprint': current_blueprint
        }

    @app.errorhandler(Exception)
    def all_exception_handler(e):
        current_app.logger.error(e, exc_info=True)
        return internal_server_error(errormsg=str(e))

    # Exclude HTTPexception from above handler (all_exception_handler)
    # HTTPException are user defined exceptions and those should be returned
    # as is
    @app.errorhandler(HTTPException)
    def http_exception_handler(e):
        current_app.logger.error(e, exc_info=True)
        return e

    # Intialize the key manager
    app.keyManager = KeyManager()

    ##########################################################################
    # Protection against CSRF attacks
    ##########################################################################
    with app.app_context():
        pgCSRFProtect.init_app(app)

    ##########################################################################
    # All done!
    ##########################################################################
    return app
Example #5
0
    def __init__(self,
                 name='__main__',
                 server=None,
                 static_folder='static',
                 assets_folder=None,
                 assets_url_path='/assets',
                 assets_ignore='',
                 include_assets_files=True,
                 url_base_pathname=None,
                 assets_external_path=None,
                 requests_pathname_prefix=None,
                 routes_pathname_prefix=None,
                 compress=True,
                 meta_tags=None,
                 index_string=_default_index,
                 external_scripts=None,
                 external_stylesheets=None,
                 suppress_callback_exceptions=None,
                 components_cache_max_age=None,
                 **kwargs):

        # pylint-disable: too-many-instance-attributes
        if 'csrf_protect' in kwargs:
            warnings.warn(
                '''
                `csrf_protect` is no longer used,
                CSRF protection has been removed as it is no longer
                necessary.
                See https://github.com/plotly/dash/issues/141 for details.
                ''', DeprecationWarning)

        name = name if server is None else server.name
        self._assets_folder = assets_folder or os.path.join(
            flask.helpers.get_root_path(name), 'assets')
        self._assets_url_path = assets_url_path

        # allow users to supply their own flask server
        self.server = server or Flask(name, static_folder=static_folder)

        if 'assets' not in self.server.blueprints:
            self.server.register_blueprint(
                flask.Blueprint('assets',
                                'assets',
                                static_folder=self._assets_folder,
                                static_url_path=assets_url_path))

        env_configs = _configs.env_configs()

        url_base_pathname, routes_pathname_prefix, requests_pathname_prefix = \
            _configs.pathname_configs(
                url_base_pathname,
                routes_pathname_prefix,
                requests_pathname_prefix,
                environ_configs=env_configs)

        self.url_base_pathname = url_base_pathname
        self.config = _AttributeDict({
            'suppress_callback_exceptions':
            _configs.get_config('suppress_callback_exceptions',
                                suppress_callback_exceptions, env_configs,
                                False),
            'routes_pathname_prefix':
            routes_pathname_prefix,
            'requests_pathname_prefix':
            requests_pathname_prefix,
            'include_assets_files':
            _configs.get_config('include_assets_files', include_assets_files,
                                env_configs, True),
            'assets_external_path':
            _configs.get_config('assets_external_path', assets_external_path,
                                env_configs, ''),
            'components_cache_max_age':
            int(
                _configs.get_config('components_cache_max_age',
                                    components_cache_max_age, env_configs,
                                    2678400))
        })

        # list of dependencies
        self.callback_map = {}

        self._index_string = ''
        self.index_string = index_string
        self._meta_tags = meta_tags or []
        self._favicon = None

        if compress:
            # gzip
            Compress(self.server)

        @self.server.errorhandler(exceptions.PreventUpdate)
        def _handle_error(error):
            """Handle a halted callback and return an empty 204 response"""
            print(error, file=sys.stderr)
            return ('', 204)

        # static files from the packages
        self.css = Css()
        self.scripts = Scripts()

        self._external_scripts = external_scripts or []
        self._external_stylesheets = external_stylesheets or []

        self.assets_ignore = assets_ignore

        self.registered_paths = collections.defaultdict(set)

        # urls
        self.routes = []

        self._add_url(
            '{}_dash-layout'.format(self.config['routes_pathname_prefix']),
            self.serve_layout)

        self._add_url(
            '{}_dash-dependencies'.format(
                self.config['routes_pathname_prefix']), self.dependencies)

        self._add_url(
            '{}_dash-update-component'.format(
                self.config['routes_pathname_prefix']), self.dispatch,
            ['POST'])

        self._add_url(('{}_dash-component-suites'
                       '/<string:package_name>'
                       '/<path:path_in_package_dist>').format(
                           self.config['routes_pathname_prefix']),
                      self.serve_component_suites)

        self._add_url(
            '{}_dash-routes'.format(self.config['routes_pathname_prefix']),
            self.serve_routes)

        self._add_url(self.config['routes_pathname_prefix'], self.index)

        # catch-all for front-end routes, used by dcc.Location
        self._add_url(
            '{}<path:path>'.format(self.config['routes_pathname_prefix']),
            self.index)

        self._add_url(
            '{}_favicon.ico'.format(self.config['routes_pathname_prefix']),
            self._serve_default_favicon)

        self.server.before_first_request(self._setup_server)

        self._layout = None
        self._cached_layout = None
        self._dev_tools = _AttributeDict({'serve_dev_bundles': False})

        # add a handler for components suites errors to return 404
        self.server.errorhandler(exceptions.InvalidResourceError)(
            self._invalid_resources_handler)
Example #6
0
File: app.py Project: thehn/dtale
def build_app(url=None,
              reaper_on=True,
              app_root=None,
              additional_templates=None,
              **kwargs):
    """
    Builds :class:`flask:flask.Flask` application encapsulating endpoints for D-Tale's front-end

    :param url: optional parameter which sets the host & root for any internal endpoints (ex: pinging shutdown)
    :type url: str, optional
    :param reaper_on: whether to run auto-reaper subprocess
    :type reaper_on: bool
    :param app_root: Optional path to prepend to the routes of D-Tale. This is used when making use of
                     Jupyterhub server proxy
    :type app_root: str, optional
    :param additional_templates: path(s) to any other jinja templates you would like to load.  This comes into play if
                                 you're embedding D-Tale into your own Flask app
    :type: str, list, optional
    :return: :class:`flask:flask.Flask` application
    :rtype: :class:`dtale.app.DtaleFlask`
    """

    app = DtaleFlask(
        "dtale",
        reaper_on=reaper_on,
        static_url_path="/dtale/static",
        url=url,
        instance_relative_config=False,
        app_root=app_root,
    )
    app.config["SECRET_KEY"] = "Dtale"

    app.jinja_env.trim_blocks = True
    app.jinja_env.lstrip_blocks = True

    if app_root is not None:
        app.config["APPLICATION_ROOT"] = app_root
        app.jinja_env.globals["url_for"] = app.url_for
    app.jinja_env.globals["is_app_root_defined"] = is_app_root_defined

    if additional_templates:
        loaders = [app.jinja_loader]
        loaders += [
            jinja2.FileSystemLoader(loc)
            for loc in make_list(additional_templates)
        ]
        my_loader = jinja2.ChoiceLoader(loaders)
        app.jinja_loader = my_loader

    app.register_blueprint(dtale)

    compress = Compress()
    compress.init_app(app)

    def _root():
        return redirect("/dtale/{}".format(head_endpoint()))

    @app.route("/")
    def root():
        return _root()

    @app.route("/dtale")
    def dtale_base():
        """
        :class:`flask:flask.Flask` routes which redirect to dtale/main

        :return: 302 - flask.redirect('/dtale/main')
        """
        return _root()

    @app.route("/favicon.ico")
    def favicon():
        """
        :class:`flask:flask.Flask` routes which returns favicon

        :return: image/png
        """
        return redirect(app.url_for("static", filename="images/favicon.ico"))

    @app.route("/missing-js")
    def missing_js():
        missing_js_commands = (
            ">> cd [location of your local dtale repo]\n"
            ">> yarn install\n"
            ">> yarn run build  # or 'yarn run watch' if you're trying to develop"
        )
        return render_template("dtale/errors/missing_js.html",
                               missing_js_commands=missing_js_commands)

    @app.errorhandler(404)
    def page_not_found(e=None):
        """
        :class:`flask:flask.Flask` routes which returns favicon

        :param e: exception
        :return: text/html with exception information
        """
        return (
            render_template(
                "dtale/errors/404.html",
                page="",
                error=e,
                stacktrace=str(traceback.format_exc()),
            ),
            404,
        )

    @app.errorhandler(500)
    def internal_server_error(e=None):
        """
        :class:`flask:flask.Flask` route which returns favicon

        :param e: exception
        :return: text/html with exception information
        """
        return (
            render_template(
                "dtale/errors/500.html",
                page="",
                error=e,
                stacktrace=str(traceback.format_exc()),
            ),
            500,
        )

    def shutdown_server():
        global ACTIVE_HOST, ACTIVE_PORT
        """
        This function that checks if flask.request.environ['werkzeug.server.shutdown'] exists and
        if so, executes that function
        """
        logger.info("Executing shutdown...")
        func = request.environ.get("werkzeug.server.shutdown")
        if func is None:
            raise RuntimeError("Not running with the Werkzeug Server")
        func()
        global_state.cleanup()
        ACTIVE_PORT = None
        ACTIVE_HOST = None

    @app.route("/shutdown")
    def shutdown():
        """
        :class:`flask:flask.Flask` route for initiating server shutdown

        :return: text/html with server shutdown message
        """
        app.clear_reaper()
        shutdown_server()
        return "Server shutting down..."

    @app.before_request
    def before_request():
        """
        Logic executed before each :attr:`flask:flask.request`

        :return: text/html with server shutdown message
        """
        app.build_reaper()

    @app.route("/site-map")
    def site_map():
        """
        :class:`flask:flask.Flask` route listing all available flask endpoints

        :return: JSON of all flask enpoints [
            [endpoint1, function path1],
            ...,
            [endpointN, function pathN]
        ]
        """
        def has_no_empty_params(rule):
            defaults = rule.defaults or ()
            arguments = rule.arguments or ()
            return len(defaults) >= len(arguments)

        links = []
        for rule in app.url_map.iter_rules():
            # Filter out rules we can't navigate to in a browser
            # and rules that require parameters
            if "GET" in rule.methods and has_no_empty_params(rule):
                url = app.url_for(rule.endpoint, **(rule.defaults or {}))
                links.append((url, rule.endpoint))
        return jsonify(links)

    @app.route("/version-info")
    def version_info():
        """
        :class:`flask:flask.Flask` route for retrieving version information about D-Tale

        :return: text/html version information
        """
        _, version = retrieve_meta_info_and_version("dtale")
        return str(version)

    @app.route("/health")
    def health_check():
        """
        :class:`flask:flask.Flask` route for checking if D-Tale is up and running

        :return: text/html 'ok'
        """
        return "ok"

    with app.app_context():

        from .dash_application import views as dash_views

        app = dash_views.add_dash(app)
        return app
Example #7
0
def register_extensions(app):
    """ register extensions to the app """
    app.jinja_env.add_extension('jinja2.ext.do')  # Global values in jinja

    # Uncomment to enable profiler
    # See scripts/profile_analyzer.py to analyze output
    # app = setup_profiler(app)

    # Compress app responses with gzip
    compress = Compress()
    compress.init_app(app)

    # Influx db time-series database
    db.init_app(app)
    influx_db.init_app(app)

    # Limit authentication blueprint requests to 200 per minute
    limiter = Limiter(app, key_func=get_ip_address)
    limiter.limit("200/minute")(routes_authentication.blueprint)

    # Language translations
    babel = Babel(app)

    @babel.localeselector
    def get_locale():
        try:
            user = User.query.filter(
                User.id == flask_login.current_user.id).first()
            if user and user.language != '':
                for key in LANGUAGES:
                    if key == user.language:
                        return key
        # Bypass endpoint test error "'AnonymousUserMixin' object has no attribute 'id'"
        except AttributeError:
            pass
        return request.accept_languages.best_match(LANGUAGES.keys())

    # User login management
    login_manager = flask_login.LoginManager()
    login_manager.init_app(app)

    @login_manager.user_loader
    def user_loader(user_id):
        user = User.query.filter(User.id == user_id).first()
        if not user:
            return
        return user

    @login_manager.unauthorized_handler
    def unauthorized():
        flash(gettext('Please log in to access this page'), "error")
        return redirect(url_for('routes_authentication.do_login'))

    # Create and populate database if it doesn't exist
    with app.app_context():
        db.create_all()
        populate_db()

        # This is disabled because there's a bug that messes up user databases
        # The upgrade script will execute alembic to upgrade the database
        # alembic_upgrade_db()

    # Check user option to force all web connections to use SSL
    # Fail if the URI is empty (pytest is running)
    if app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://':
        with session_scope(
                app.config['SQLALCHEMY_DATABASE_URI']) as new_session:
            misc = new_session.query(Misc).first()
            if misc and misc.force_https:
                SSLify(app)
Example #8
0
from flask import Flask, abort, request, session
from flask_compress import Compress  # type: ignore
from flask_socketio import SocketIO, emit  # type: ignore

from .constants import DEFAULT_GDB_EXECUTABLE, STATIC_DIR, TEMPLATE_DIR
from .http_routes import blueprint
from .http_util import is_cross_origin
from .sessionmanager import SessionManager, DebugSession

logger = logging.getLogger(__file__)
# Create flask application and add some configuration keys to be used in various callbacks
app = Flask(__name__,
            template_folder=str(TEMPLATE_DIR),
            static_folder=str(STATIC_DIR))
Compress(
    app
)  # add gzip compression to Flask. see https://github.com/libwilliam/flask-compress
app.register_blueprint(blueprint)
app.config["initial_binary_and_args"] = []
app.config["gdb_path"] = DEFAULT_GDB_EXECUTABLE
app.config["gdb_command"] = None
app.config["TEMPLATES_AUTO_RELOAD"] = True
app.config["project_home"] = None
app.config["remap_sources"] = {}
manager = SessionManager()
app.config["_manager"] = manager
app.secret_key = binascii.hexlify(os.urandom(24)).decode("utf-8")
socketio = SocketIO(manage_session=False)


@app.before_request
Example #9
0
def create_app(config='CTFd.config.Config'):
    app = CTFdFlask(__name__)
    Compress(app)
    with app.app_context():
        app.config.from_object(config)

        theme_loader = ThemeLoader(os.path.join(app.root_path, 'themes'),
                                   followlinks=True)
        app.jinja_loader = theme_loader

        from CTFd.models import db, Teams, Solves, Challenges, WrongKeys, Keys, Tags, Files, Tracking

        url = make_url(app.config['SQLALCHEMY_DATABASE_URI'])
        if url.drivername == 'postgres':
            url.drivername = 'postgresql'

        if url.drivername.startswith('mysql'):
            url.query['charset'] = 'utf8mb4'

        # Creates database if the database database does not exist
        if not database_exists(url):
            if url.drivername.startswith('mysql'):
                create_database(url, encoding='utf8mb4')
            else:
                create_database(url)

        # This allows any changes to the SQLALCHEMY_DATABASE_URI to get pushed back in
        # This is mostly so we can force MySQL's charset
        app.config['SQLALCHEMY_DATABASE_URI'] = str(url)

        # Register database
        db.init_app(app)

        # Register Flask-Migrate
        migrate.init_app(app, db)

        # Alembic sqlite support is lacking so we should just create_all anyway
        if url.drivername.startswith('sqlite'):
            db.create_all()
        else:
            if len(db.engine.table_names()) == 0:
                # This creates tables instead of db.create_all()
                # Allows migrations to happen properly
                migrate_upgrade()
            elif 'alembic_version' not in db.engine.table_names():
                # There is no alembic_version because CTFd is from before it had migrations
                # Stamp it to the base migration
                if confirm_upgrade():
                    migrate_stamp(revision='cb3cfcc47e2f')
                    run_upgrade()
                else:
                    exit()

        app.db = db
        app.VERSION = __version__

        cache.init_app(app)
        app.cache = cache

        update_check(force=True)

        version = utils.get_config('ctf_version')

        # Upgrading from an older version of CTFd
        if version and (StrictVersion(version) < StrictVersion(__version__)):
            if confirm_upgrade():
                run_upgrade()
            else:
                exit()

        if not version:
            utils.set_config('ctf_version', __version__)

        if not utils.get_config('ctf_theme'):
            utils.set_config('ctf_theme', 'core')

        from CTFd.views import views
        from CTFd.challenges import challenges
        from CTFd.scoreboard import scoreboard
        from CTFd.auth import auth
        from CTFd.admin import admin, admin_statistics, admin_challenges, admin_pages, admin_scoreboard, admin_keys, admin_teams
        from CTFd.utils import init_utils, init_errors, init_logs

        init_utils(app)
        init_errors(app)
        init_logs(app)

        app.register_blueprint(views)
        app.register_blueprint(challenges)
        app.register_blueprint(scoreboard)
        app.register_blueprint(auth)

        app.register_blueprint(admin)
        app.register_blueprint(admin_statistics)
        app.register_blueprint(admin_challenges)
        app.register_blueprint(admin_teams)
        app.register_blueprint(admin_scoreboard)
        app.register_blueprint(admin_keys)
        app.register_blueprint(admin_pages)

        from CTFd.plugins import init_plugins

        init_plugins(app)

        return app
Example #10
0
    def setUp(self):
        self.app = Flask(__name__)
        self.app.testing = True

        Compress(self.app)
Example #11
0
    def create_flask_app(self):
        try:
            from flask import Flask, request
            from flask_compress import Compress
            # from flask_cors import CORS
            from flask_json import FlaskJSON, as_json, JsonError
        except ImportError:
            raise ImportError()

        app = Flask(__name__)
        #app.config['SWAGGER'] = {
        #    'title':'Colors API',
        #    'uiversion':3,
        #    "openapi":"3.0.2"
        #}
        self.create_classify_worker()

        @app.route('/tts-classify', methods=['POST'])
        @as_json
        def tts_classify():
            req_data = request.form if request.form else request.json
            # req_data['req_id'] = uuid.uuid1()
            # req_id = req_data['req_id']
            texts = req_data['texts'] # text list
            if not isinstance(texts, list):
                texts = [texts]
            req_num = len(texts)
            text_ids = []
            st = int(time.time() * 1000)
            for k in range(req_num):
                textid = uuid.uuid1().hex
                text_a = texts[k]
                text_b = None
                # input_item = DataItem(textid,text_a,None,None)
                text_ids.append(textid)

                input_item = {
                    "guid":textid,
                    "text_a":text_a,
                    "text_b":text_b,
                }
                self.sender.send_json(jsonapi.dumps(input_item))
                # self.ready_to_classify_que.put(input_item)
                self.logger.debug("put item:%s"%(textid))

            req_time = time.time()
            req_data['req_time'] = req_time
            # self.ready_to_classify_que.put(req_data)

            collect_num = 0
            pred_labels = [0]*req_num
            for k in range(req_num):
                while text_ids[k] not in self.classify_res:
                    continue
                pred_labels[k] = self.classify_res[text_ids[k]]
                self.classify_res.pop(text_ids[k])

            res_data = {
                "pred_labels":pred_labels
            }
            ed = int(time.time()*1000)
            cost = ed - st
            self.logger.debug("[timecost] %d ms"%(cost))
            return res_data
        # CORS(app, origins=self.args.cors)
        FlaskJSON(app)
        Compress().init_app(app)
        return app
Example #12
0
 def test_delayed_init(self):
     compress = Compress()
     compress.init_app(self.app)
Example #13
0
 def test_constructor_init(self):
     Compress(self.app)
Example #14
0
def create_app(settings_override=None):
    """
    Create a Flask application using the app factory pattern.

    :param settings_override: Override settings
    :return: Flask app
    """
    app = Flask(__name__, instance_relative_config=True)

    app.config.from_object('config.settings')
    app.config.from_pyfile('settings.py', silent=True)

    # Setting app server name and cookie domain
    if os.environ.get('PRODUCTION') == 'True':
        # Set the app server name
        app.config['SERVER_NAME'] = 'getschedulr.com'
        app.config['REMEMBER_COOKIE_DOMAIN'] = '.getschedulr.com'
    else:
        # Set the app server name
        SERVER_NAME = 'f691a605a823.ngrok.io'
        app.config['SERVER_NAME'] = SERVER_NAME
        app.config['REMEMBER_COOKIE_DOMAIN'] = '.' + SERVER_NAME

        # Disable CSRF in dev
        app.config['WTF_CSRF_ENABLED'] = False

    # Keeps the app from crashing on reload
    app.config['SQLALCHEMY_POOL_RECYCLE'] = 499
    app.config['SQLALCHEMY_POOL_TIMEOUT'] = 120
    app.static_folder = 'static'
    app.static_url_path = '/static'

    # CORS
    app.config['CORS_HEADERS'] = 'Content-Type'

    # Whitenoise
    # app.wsgi_app = WhiteNoise(app.wsgi_app, root='static/')

    if settings_override:
        app.config.update(settings_override)

    stripe.api_key = app.config.get('STRIPE_KEY')
    stripe.api_version = '2018-02-28'

    middleware(app)
    error_templates(app)
    exception_handler(app)
    app.register_blueprint(admin)
    app.register_blueprint(page)
    app.register_blueprint(contact)
    app.register_blueprint(user)
    app.register_blueprint(base)
    app.register_blueprint(calendar)
    app.register_blueprint(api)
    app.register_blueprint(billing)
    app.register_blueprint(errors)
    app.register_error_handler(404, page_not_found)
    app.register_error_handler(500, internal_error)
    template_processors(app)
    extensions(app)
    authentication(app, User)

    # Compress Flask app
    COMPRESS_MIMETYPES = ['text/html' 'text/css', 'application/json']
    COMPRESS_LEVEL = 6
    COMPRESS_MIN_SIZE = 500
    Compress(app)

    @app.errorhandler(500)
    def error_502(e):
        return render_template('errors/500.html')

    @app.errorhandler(404)
    def error_404(e):
        return render_template('errors/404.html')

    @app.errorhandler(502)
    def error_502(e):
        return render_template('errors/500.html')

    return app
Example #15
0
                  template_folder="../templates")

try:
    import config
    c3bottles.config.from_object(config)
except ImportError:
    c3bottles.config.update(SQLALCHEMY_DATABASE_URI="sqlite:///c3bottles.db",
                            SQLALCHEMY_TRACK_MODIFICATIONS=False,
                            SECRET_KEY=pwgen(64),
                            BABEL_TRANSLATION_DIRECTORIES="../translations")
    print("\nWARNING: c3bottles is not configured properly and this\n"
          "instance fell back to the default configuration. This means\n"
          "that the secret key will change on every restart of the\n"
          "server and all users will be logged out forcibly!\n")

Compress(c3bottles)

db = SQLAlchemy(c3bottles, session_options={"autoflush": False})

lm = LoginManager(c3bottles)

bcrypt = Bcrypt(c3bottles)

csrf = CSRFProtect(c3bottles)

babel = Babel(c3bottles)

languages = ("en", "de")
locales = {l: Locale(l) for l in languages}
language_list = sorted([l for l in languages],
                       key=lambda k: locales[k].get_display_name())
Example #16
0
    def __init__(self,
                 name=None,
                 server=None,
                 filename=None,
                 sharing=None,
                 app_url=None,
                 url_base_pathname='/',
                 csrf_protect=True):
        # allow users to supply their own flask server
        if server is not None:
            self.server = server
        else:
            if name is None:
                name = 'dash'
            self.server = Flask(name)

        if self.server.secret_key is None:
            # If user supplied their own server, they might've supplied a
            # secret_key with it
            secret_key_name = 'dash_{}_secret_key'.format(
                # TODO - check for other illegal characters
                name.replace('.', '_'))
            secret_key = os.environ.get(secret_key_name,
                                        SeaSurf()._generate_token())
            os.environ[secret_key_name] = secret_key
            self.server.secret_key = secret_key

        if filename is not None:
            fid = plotly_api.create_or_overwrite_dash_app(
                filename, sharing, app_url)
            self.fid = fid
            self.app_url = app_url
            self.sharing = sharing
            self.access_codes = self.create_access_codes()
        else:
            self.fid = None
            self.access_codes = None

        self.url_base_pathname = url_base_pathname

        # list of dependencies
        self.callback_map = {}

        # gzip
        Compress(self.server)

        # csrf protect
        if csrf_protect:
            self._csrf = SeaSurf(self.server)

        # static files from the packages
        self.css = Css()
        self.scripts = Scripts()
        self.registered_paths = {}

        # urls
        self.server.add_url_rule('{}_dash-login'.format(
            self.url_base_pathname),
                                 view_func=authentication.login,
                                 methods=['post'])

        self.server.add_url_rule('{}_dash-layout'.format(
            self.url_base_pathname),
                                 view_func=self.serve_layout)

        self.server.add_url_rule('{}_dash-dependencies'.format(
            self.url_base_pathname),
                                 view_func=self.dependencies)

        self.server.add_url_rule('{}_dash-update-component'.format(
            self.url_base_pathname),
                                 view_func=self.dispatch,
                                 methods=['POST'])

        self.server.add_url_rule(
            ('{}_dash-component-suites'
             '/<string:package_name>'
             '/<path:path_in_package_dist>').format(self.url_base_pathname),
            view_func=self.serve_component_suites)

        self.server.add_url_rule('{}_dash-routes'.format(
            self.url_base_pathname),
                                 view_func=self.serve_routes)

        self.server.add_url_rule(self.url_base_pathname, view_func=self.index)

        # catch-all for front-end routes
        self.server.add_url_rule('{}<path:path>'.format(
            self.url_base_pathname),
                                 view_func=self.index)

        self.server.before_first_request(self._setup_server)

        self._layout = None
        self.routes = []
Example #17
0
from flexget.webserver import register_app, register_home

log = logging.getLogger('webui')

manager = None
debug = False
app_base = None

ui_base = os.path.dirname(os.path.realpath(__file__))
ui_src = os.path.join(ui_base, 'src')
ui_dist = os.path.join(ui_base, 'app')
bower_components = os.path.join(ui_base, 'bower_components')

webui_app = Flask(__name__)
Compress(webui_app)
webui_app.url_path = '/'


@webui_app.route('/<path:path>')
def serve_app(path):
    if debug:
        if path.startswith('bower_components'):
            return send_from_directory(
                bower_components, path.lstrip('bower_components').lstrip('/')
            )

        if os.path.exists(os.path.join(ui_src, path)):
            return send_from_directory(ui_src, path)

    if not app_base:
Example #18
0
from flask import Flask
from flask_compress import Compress
from models import db

PUBLIC_KEY = 'i18183574422'
PRIVATE_KEY = 'DWHmS0mwLkNTIUJJhP6bTmAN4WpKshVJomDSdeZ3'

app = Flask(__name__)
app.config.from_pyfile('app.cfg')
db.init_app(app)

compress = Compress(app)

import views
Example #19
0
def create_app():
    # setup flask
    app = Flask("jazzband")
    # load decoupled config variables
    app.config.from_object("jazzband.config")

    @app.context_processor
    def app_context_processor():
        return {
            "about": about_pages,
            "news": news_pages,
            "User": User,
            "Project": Project,
            "config": app.config,
        }

    @app.after_request
    def add_vary_header(response):
        response.vary.add("Cookie")
        response.headers["Jazzband"] = "We are all part of this."
        return response

    talisman.init_app(
        app,
        force_https=app.config["IS_PRODUCTION"],
        force_file_save=True,
        content_security_policy=app.config["CSP_RULES"],
        content_security_policy_report_only=app.config["CSP_REPORT_ONLY"],
        content_security_policy_report_uri=app.config["CSP_REPORT_URI"],
        feature_policy=app.config["FEATURE_POLICY"],
    )

    postgres.init_app(app)

    redis.init_app(app)

    Migrate(app, postgres)

    cache.init_app(app)

    admin.init_app(app)

    cli.init_app(app)

    spinach.init_app(app)

    errors.init_app(app)

    if app.config["IS_PRODUCTION"]:
        app.wsgi_app = ProxyFix(app.wsgi_app)
        app.wsgi_app = WhiteNoise(app.wsgi_app, root="static/")

    mail.init_app(app)

    hooks.init_app(app)

    # setup session store
    session_store = RedisStore(redis)
    KVSessionExtension(session_store, app)

    Compress(app)

    about_pages.init_app(app)
    news_pages.init_app(app)

    login_manager.init_app(app)

    from . import blueprints  # noqa

    blueprints.init_app(app)

    return app
Example #20
0
login = LoginManager()  # flask-login
login.login_view = 'auth.login'
login.login_message = _l('Please login to access this page.')
mail = Mail()
moment = Moment()
gravatar = Gravatar(app=None,
                    size=100,
                    rating='g',
                    default='robohash',
                    force_default=False,
                    force_lower=False,
                    use_ssl=True,
                    base_url=None)
bootstrap = Bootstrap()  # flask-bootstrap
cache = Cache()  # flask-caching
compress = Compress()  # flask-compress
babel = Babel()  # flask-babel


def create_app(config_class=Config):
    app = Flask(__name__)
    app.config.from_object(config_class)

    db.init_app(app)
    migrate.init_app(app, db)
    login.init_app(app)
    mail.init_app(app)
    moment.init_app(app)
    gravatar.init_app(app)
    bootstrap.init_app(app)
    compress.init_app(app)
Example #21
0
                default=default or sort_choices[0],
                help='Sort by attribute',
            )

        return pagination


api_app = Flask(__name__,
                template_folder=os.path.join(__path__[0], 'templates'))
api_app.config['REMEMBER_COOKIE_NAME'] = 'flexget.token'
api_app.config['DEBUG'] = True
api_app.config['ERROR_404_HELP'] = False
api_app.url_map.strict_slashes = False

CORS(api_app, expose_headers='Link, Total-Count, Count, ETag')
Compress(api_app)

api = API(
    api_app,
    title='Flexget API v{}'.format(__version__),
    version=__version__,
    description=
    'View and manage flexget core operations and plugins. Open each endpoint view for usage information.'
    ' Navigate to http://flexget.com/API for more details.',
    format_checker=format_checker,
)

base_message = {
    'type': 'object',
    'properties': {
        'status_code': {
Example #22
0
def build_app(reaper_on=True, hide_shutdown=False):
    """
    Builds Flask application encapsulating endpoints for D-Tale's front-end

    :return: Flask application
    :rtype: :class:`dtale.app.DtaleFlask`
    """

    app = DtaleFlask('dtale', reaper_on=reaper_on, static_url_path='')
    app.config['SECRET_KEY'] = 'Dtale'
    app.config['HIDE_SHUTDOWN'] = hide_shutdown

    app.jinja_env.trim_blocks = True
    app.jinja_env.lstrip_blocks = True
    app.register_blueprint(dtale)

    compress = Compress()
    compress.init_app(app)

    _, version = retrieve_meta_info_and_version('dtale')
    template = dict(
        info={
            'title': 'D-Tale',
            'version': version,
            'description': 'Web Client for Visualizing Pandas Objects',
            'contact': {
                'name': 'Man Alpha Technology',
                'email': '*****@*****.**',
                'url': 'https://github.com/man-group/dtale'
            },
        },
        host=socket.gethostname(),
        schemes=['http'],
    )
    try:
        from flasgger import Swagger  # flake8: NOQA
        Swagger(app, template=template)
    except ImportError:
        logger.debug(
            'flasgger dependency not found, please install to enable feature')

    @app.route('/')
    @app.route('/dtale')
    @swag_from('swagger/dtale/root.yml')
    def root():
        """
        Flask routes which redirect to dtale/main

        :return: 302 - flask.redirect('/dtale/main')
        """
        return redirect('/dtale/main')

    @app.route('/favicon.ico')
    def favicon():
        """
        Flask routes which returns favicon

        :return: image/png
        """
        return redirect(url_for('static', filename='images/favicon.ico'))

    @app.errorhandler(404)
    def page_not_found(e=None):
        """
        Flask routes which returns favicon

        :param e: exception
        :return: text/html with exception information
        """
        logger.exception(e)
        return render_template('dtale/errors/404.html',
                               page='',
                               error=e,
                               stacktrace=str(traceback.format_exc())), 404

    @app.errorhandler(500)
    def internal_server_error(e=None):
        """
        Flask route which returns favicon

        :param e: exception
        :return: text/html with exception information
        """
        logger.exception(e)
        return render_template('dtale/errors/500.html',
                               page='',
                               error=e,
                               stacktrace=str(traceback.format_exc())), 500

    def shutdown_server():
        """
        This function that checks if flask.request.environ['werkzeug.server.shutdown'] exists and
        if so, executes that function
        """
        logger.info('Executing shutdown...')
        func = request.environ.get('werkzeug.server.shutdown')
        if func is None:
            raise RuntimeError('Not running with the Werkzeug Server')
        func()
        cleanup(app.port)

    @app.route('/shutdown')
    @swag_from('swagger/dtale/shutdown.yml')
    def shutdown():
        """
        Flask route for initiating server shutdown

        :return: text/html with server shutdown message
        """
        app.clear_reaper()
        shutdown_server()
        return 'Server shutting down...'

    @app.before_request
    def before_request():
        """
        Logic executed before each :attr:`flask:flask.request`

        :return: text/html with server shutdown message
        """
        app.build_reaper()

    @app.route('/site-map')
    @swag_from('swagger/dtale/site-map.yml')
    def site_map():
        """
        Flask route listing all available flask endpoints

        :return: JSON of all flask enpoints [
            [endpoint1, function path1],
            ...,
            [endpointN, function pathN]
        ]
        """
        def has_no_empty_params(rule):
            defaults = rule.defaults or ()
            arguments = rule.arguments or ()
            return len(defaults) >= len(arguments)

        links = []
        for rule in app.url_map.iter_rules():
            # Filter out rules we can't navigate to in a browser
            # and rules that require parameters
            if "GET" in rule.methods and has_no_empty_params(rule):
                url = url_for(rule.endpoint, **(rule.defaults or {}))
                links.append((url, rule.endpoint))
        return jsonify(links)

    @app.route('/version-info')
    @swag_from('swagger/dtale/version-info.yml')
    def version_info():
        """
        Flask route for retrieving version information about D-Tale

        :return: text/html version information
        """
        _, version = retrieve_meta_info_and_version('dtale')
        return str(version)

    @app.route('/health')
    @swag_from('swagger/dtale/health.yml')
    def health_check():
        """
        Flask route for checking if D-Tale is up and running

        :return: text/html 'ok'
        """
        return 'ok'

    return app
Example #23
0
def create_app():
    # Create flask app
    app = Flask(__name__)

    # Which config to use
    lzapi_mode = os.environ.get("LZAPI_MODE")
    if lzapi_mode is None:
        raise Exception(
            "No API mode designated. Set the LZAPI_MODE environment variable to 'dev' or 'prod'"
        )

    # Config file given mode
    config_file = os.path.join(app.root_path,
                               "../../etc/config-{}.py".format(lzapi_mode))
    if not os.path.isfile(config_file):
        raise IOError(
            "Could not find configuration file {} for API mode {}".format(
                config_file, lzapi_mode))

    # Load config
    app.config.from_pyfile(config_file)

    # Set mode
    app.config["LZAPI_MODE"] = lzapi_mode

    # Enable cross-domain headers on all routes
    CORS(app)

    # Enable compression support
    Compress(app)

    # Setup Postgres DB
    from . import db
    db.init_app(app)

    # Setup redis
    from . import redis_client
    redis_client.init_app(app)

    # Setup helpers
    from . import helpers
    helpers.init_app(app)

    # Setup error handlers
    from . import errors
    errors.init_app(app)

    # Register routes with app
    with app.app_context():
        from . import routes
        app.register_blueprint(routes.bp)

    # JSON encoder for datetimes
    app.json_encoder = CustomJSONEncoder

    # If gunicorn is attached, route loggers there
    try:
        gunicorn_logger = logging.getLogger('gunicorn.error')
        app.logger.handlers = gunicorn_logger.handlers
        app.logger.setLevel(gunicorn_logger.level)
    except Exception as e:
        app.logger.warning("Could not attach to gunicorn logger: " + str(e))

    app.logger.info("Flask app initialized")

    return app
Example #24
0
def _init_sqlalchemy():
    database = SQLAlchemy(application)
    database.init_app(application)
    application.session_interface = SqlAlchemySessionInterface(
        application, database, "test_sessions", "test_sess_")
    application.permanent_session_lifetime = datetime.timedelta(hours=1)


_configure_logs()  # NOTE: this needs to happen before starting the application
# Load default config and override config from an environment variable
application = Flask(__name__)
_load_config()
_init_sqlalchemy()

Compress(application)
cache = Cache(application, config={"CACHE_TYPE": "simple"})
mail = Mail(application)

try:
    db = psycopg2.connect(
        host=application.config["DB_HOST"],
        database=application.config["DB_DATABASE"],
        user=application.config["DB_USER"],
        password=application.config["DB_PASSWORD"],
        port=application.config["DB_PORT"],
    )
    c = db.cursor()
    c.execute("select external_id, internal_id from individuals")
    headers = [h[0] for h in c.description]
Example #25
0
allow_origins = ['https://playground.daiiz.dev']
if os.environ.get('DEV_MODE', '0') == '1':
    allow_origins.append('http://localhost:3003')
    print('allow_origins:', allow_origins)

app = Flask(__name__)
CORS(app,
     resources={
         r"/api/generate": {
             "origins": allow_origins,
             "methods": ['POST', 'OPTIONS']
         }
     })
app.config["COMPRESS_MIMETYPES"] = ["image/png"]
app.config["COMPRESS_ALGORITHM"] = ["gzip", "deflate"]
compress = Compress()
compress.init_app(app)


def parse_thumbnail_size(request):
    size_range = [100, 2000]
    size = 1000  # default size
    try:
        size = min(int(request.args.get("size", "1000")), size_range[1])
        if size < size_range[0]:
            size = size_range[0]
    except Exception as e:
        print(e)
    return size

"""
Cache responses timeout.

CACHE_DEFAULT_TIMEOUT : int
"""

CACHE.init_app(APP)

APP.config.update(
    COMPRESS_LEVEL=3,
    COMPRESS_CACHE_KEY=lambda x: x.full_path,
    COMPRESS_CACHE_BACKEND=lambda: SimpleCache(default_timeout=  # noqa
                                               CACHE_DEFAULT_TIMEOUT),
)

Compress(APP)

IMAGES_DIRECTORY = os.path.join(os.getcwd(), 'static', 'images')
"""
Images directory.

IMAGES_DIRECTORY : unicode
"""


def _null_to_None(data):
    """
    Converts *Javascript* originated *null* and *undefined* strings
    to `None`. Non-matching data will be passed untouched.

    Parameters
Example #27
0
def build_app(url,
              host=None,
              reaper_on=True,
              hide_shutdown=False,
              github_fork=False):
    """
    Builds :class:`flask:flask.Flask` application encapsulating endpoints for D-Tale's front-end

    :return: :class:`flask:flask.Flask` application
    :rtype: :class:`dtale.app.DtaleFlask`
    """

    app = DtaleFlask('dtale',
                     reaper_on=reaper_on,
                     static_url_path='',
                     url=url,
                     instance_relative_config=False)
    app.config['SECRET_KEY'] = 'Dtale'
    app.config['HIDE_SHUTDOWN'] = hide_shutdown
    app.config['GITHUB_FORK'] = github_fork

    app.jinja_env.trim_blocks = True
    app.jinja_env.lstrip_blocks = True
    app.register_blueprint(dtale)

    compress = Compress()
    compress.init_app(app)

    @app.route('/')
    @app.route('/dtale')
    def root():
        """
        :class:`flask:flask.Flask` routes which redirect to dtale/main

        :return: 302 - flask.redirect('/dtale/main')
        """
        return redirect('/dtale/main/{}'.format(head_data_id()))

    @app.route('/favicon.ico')
    def favicon():
        """
        :class:`flask:flask.Flask` routes which returns favicon

        :return: image/png
        """
        return redirect(url_for('static', filename='images/favicon.ico'))

    @app.route('/missing-js')
    def missing_js():
        missing_js_commands = (
            '>> cd [location of your local dtale repo]\n'
            '>> yarn install\n'
            ">> yarn run build  # or 'yarn run watch' if you're trying to develop"
        )
        return render_template('dtale/errors/missing_js.html',
                               missing_js_commands=missing_js_commands)

    @app.errorhandler(404)
    def page_not_found(e=None):
        """
        :class:`flask:flask.Flask` routes which returns favicon

        :param e: exception
        :return: text/html with exception information
        """
        return render_template('dtale/errors/404.html',
                               page='',
                               error=e,
                               stacktrace=str(traceback.format_exc())), 404

    @app.errorhandler(500)
    def internal_server_error(e=None):
        """
        :class:`flask:flask.Flask` route which returns favicon

        :param e: exception
        :return: text/html with exception information
        """
        return render_template('dtale/errors/500.html',
                               page='',
                               error=e,
                               stacktrace=str(traceback.format_exc())), 500

    def shutdown_server():
        global ACTIVE_HOST, ACTIVE_PORT
        """
        This function that checks if flask.request.environ['werkzeug.server.shutdown'] exists and
        if so, executes that function
        """
        logger.info('Executing shutdown...')
        func = request.environ.get('werkzeug.server.shutdown')
        if func is None:
            raise RuntimeError('Not running with the Werkzeug Server')
        func()
        global_state.cleanup()
        ACTIVE_PORT = None
        ACTIVE_HOST = None

    @app.route('/shutdown')
    def shutdown():
        """
        :class:`flask:flask.Flask` route for initiating server shutdown

        :return: text/html with server shutdown message
        """
        app.clear_reaper()
        shutdown_server()
        return 'Server shutting down...'

    @app.before_request
    def before_request():
        """
        Logic executed before each :attr:`flask:flask.request`

        :return: text/html with server shutdown message
        """
        app.build_reaper()

    @app.route('/site-map')
    def site_map():
        """
        :class:`flask:flask.Flask` route listing all available flask endpoints

        :return: JSON of all flask enpoints [
            [endpoint1, function path1],
            ...,
            [endpointN, function pathN]
        ]
        """
        def has_no_empty_params(rule):
            defaults = rule.defaults or ()
            arguments = rule.arguments or ()
            return len(defaults) >= len(arguments)

        links = []
        for rule in app.url_map.iter_rules():
            # Filter out rules we can't navigate to in a browser
            # and rules that require parameters
            if "GET" in rule.methods and has_no_empty_params(rule):
                url = url_for(rule.endpoint, **(rule.defaults or {}))
                links.append((url, rule.endpoint))
        return jsonify(links)

    @app.route('/version-info')
    def version_info():
        """
        :class:`flask:flask.Flask` route for retrieving version information about D-Tale

        :return: text/html version information
        """
        _, version = retrieve_meta_info_and_version('dtale')
        return str(version)

    @app.route('/health')
    def health_check():
        """
        :class:`flask:flask.Flask` route for checking if D-Tale is up and running

        :return: text/html 'ok'
        """
        return 'ok'

    with app.app_context():

        from .dash_application import views as dash_views
        app = dash_views.add_dash(app)
        return app
Example #28
0
def create_app():
    """Flask application factory."""
    app = Flask(__name__, static_folder="js")
    app.config["PROPAGATE_EXCEPTIONS"] = True
    app.config["TREE"] = os.getenv("TREE")
    app.config["GRAMPS_EXCLUDE_PRIVATE"] = Boolean(
        os.getenv("GRAMPS_EXCLUDE_PRIVATE"))
    app.config["GRAMPS_EXCLUDE_LIVING"] = Boolean(
        os.getenv("GRAMPS_EXCLUDE_LIVING"))
    app.config["TREE"] = os.getenv("TREE")
    if app.config["TREE"] is None or app.config["TREE"] == "":
        raise ValueError("You have to set the `TREE` environment variable.")
    app.config["GRAMPS_S3_BUCKET_NAME"] = os.getenv("GRAMPS_S3_BUCKET_NAME")
    app.config["PASSWORD"] = os.getenv("PASSWORD", "")
    app.config["GRAMPS_USER_DB_URI"] = os.getenv("GRAMPS_USER_DB_URI", "")
    app.config["GRAMPS_AUTH_PROVIDER"] = os.getenv("GRAMPS_AUTH_PROVIDER", "")

    if app.config["GRAMPS_AUTH_PROVIDER"] == "password":
        auth_provider = SingleUser(password=app.config["PASSWORD"])
    elif app.config["GRAMPS_AUTH_PROVIDER"] == "none":
        auth_provider = None
    else:
        auth_provider = SQLAuth(db_uri=app.config["GRAMPS_USER_DB_URI"])

    app.logger.setLevel(logging.INFO)
    app.logger.info("Opening family tree '{}'".format(app.config["TREE"]))

    limiter = Limiter(app, key_func=get_remote_address)

    # called once here in case Db's constructor raises
    Db(app.config["TREE"])

    CORS(app)
    Compress(app)
    api = Api(app)
    cache = Cache(app,
                  config={
                      "CACHE_TYPE": "filesystem",
                      "CACHE_DIR": "appcache"
                  })

    app.config["JWT_TOKEN_LOCATION"] = ["headers", "query_string"]
    app.config["JWT_ACCESS_TOKEN_EXPIRES"] = datetime.timedelta(minutes=15)
    app.config["JWT_REFRESH_TOKEN_EXPIRES"] = datetime.timedelta(days=30)
    app.config["JWT_SECRET_KEY"] = get_jwt_secret_key()

    jwt = JWTManager(app)

    @app.route("/", methods=["GET", "POST"])
    def send_js_index():
        return send_from_directory(app.static_folder, "index.html")

    @app.route("/<path:path>", methods=["GET", "POST"])
    def send_js(path):
        if path and os.path.exists(os.path.join(app.static_folder, path)):
            return send_from_directory(app.static_folder, path)
        else:
            return send_from_directory(app.static_folder, "index.html")

    @app.route("/api/login", methods=["POST"])
    @limiter.limit("1/second")
    def login():
        if app.config["GRAMPS_AUTH_PROVIDER"] == "none":
            ret = {"access_token": "1", "refresh_token": "1"}
            return jsonify(ret), 200
        if not request.is_json:
            return jsonify({"msg": "Missing JSON in request"}), 400
        username = request.json.get("username", None)
        password = request.json.get("password", None)
        from .auth import User

        if not auth_provider.authorized(username, password):
            return jsonify({"msg": "Wrong username or password"}), 401
        ret = {
            "access_token": create_access_token(identity=username),
            "refresh_token": create_refresh_token(identity=username),
        }
        return jsonify(ret), 200

    def jwt_required_ifauth(fn):
        """Check JWT unless authentication is disabled"""
        @wraps(fn)
        def wrapper(*args, **kwargs):
            if app.config["GRAMPS_AUTH_PROVIDER"] != "none":
                verify_jwt_in_request()
            return fn(*args, **kwargs)

        return wrapper

    def jwt_refresh_token_required_ifauth(fn):
        """Check JWT unless authentication is disabled"""
        @wraps(fn)
        def wrapper(*args, **kwargs):
            if app.config["GRAMPS_AUTH_PROVIDER"] != "none":
                verify_jwt_refresh_token_in_request()
            return fn(*args, **kwargs)

        return wrapper

    @app.route("/api/refresh", methods=["POST"])
    @jwt_refresh_token_required_ifauth
    def refresh():
        if app.config["GRAMPS_AUTH_PROVIDER"] == "none":
            ret = {"access_token": "1"}
            return jsonify(ret), 200
        current_user = get_jwt_identity()
        ret = {"access_token": create_access_token(identity=current_user)}
        return jsonify(ret), 200

    parser = reqparse.RequestParser()
    parser.add_argument("strings", type=str)
    parser.add_argument("fmt", type=str)

    @app.before_request
    def before_request():
        if not get_db().dbstate.is_open():
            get_db().open()

    app.teardown_appcontext(close_db)

    class ProtectedResource(Resource):
        method_decorators = [jwt_required_ifauth]

    class People(ProtectedResource):
        @cache.cached()
        def get(self):
            return get_people(get_db())

    class Families(ProtectedResource):
        @cache.cached()
        def get(self):
            return get_families(get_db())

    class Events(ProtectedResource):
        @cache.cached()
        def get(self):
            return get_events(get_db())

    class Places(ProtectedResource):
        @cache.cached()
        def get(self):
            return get_places(get_db())

    class Citations(ProtectedResource):
        @cache.cached()
        def get(self):
            return get_citations(get_db())

    class Sources(ProtectedResource):
        @cache.cached()
        def get(self):
            return get_sources(get_db())

    class Repositories(ProtectedResource):
        @cache.cached()
        def get(self):
            return get_repositories(get_db())

    class MediaObjects(ProtectedResource):
        @cache.cached()
        def get(self):
            return get_media(get_db())

    class DbInfo(ProtectedResource):
        @cache.cached()
        def get(self):
            return get_db_info(get_db())

    class FullTree(ProtectedResource):
        @cache.cached()
        def get(self):
            return {
                "people": get_people(get_db()),
                "families": get_families(get_db()),
                "events": get_events(get_db()),
                "places": get_places(get_db()),
                "citations": get_citations(get_db()),
                "sources": get_sources(get_db()),
                "repositories": get_repositories(get_db()),
                "media": get_media(get_db()),
                "dbinfo": get_db_info(get_db()),
            }

    class Translate(Resource):
        @cache.cached()
        def get(self):
            args = parser.parse_args()
            try:
                strings = json.loads(args["strings"])
                lang = args.get("lang")
            except (json.decoder.JSONDecodeError, TypeError, ValueError) as e:
                return {"error": str(e)}
            return {"data": get_translation(strings, lang=lang)}

    class Languages(Resource):
        @cache.cached()
        def get(self):
            return {"data": get_languages()}

    class Note(ProtectedResource):
        @cache.cached(query_string=True)
        def get(self, gramps_id):
            args = parser.parse_args()
            fmt = args.get("fmt") or "html"
            return get_note(get_db(), gramps_id, fmt=fmt)

    api.add_resource(People, "/api/people")
    api.add_resource(Families, "/api/families")
    api.add_resource(Events, "/api/events")
    api.add_resource(Places, "/api/places")
    api.add_resource(Citations, "/api/citations")
    api.add_resource(Sources, "/api/sources")
    api.add_resource(MediaObjects, "/api/mediaobjects")
    api.add_resource(Repositories, "/api/repositories")
    api.add_resource(Translate, "/api/translate")
    api.add_resource(Languages, "/api/languages")
    api.add_resource(DbInfo, "/api/dbinfo")
    api.add_resource(FullTree, "/api/tree")
    api.add_resource(Note, "/api/note/<string:gramps_id>")

    def get_media_handler(handle):
        info = get_media_info(get_db(), handle)
        if app.config["GRAMPS_S3_BUCKET_NAME"]:
            return S3Handler(handle,
                             info,
                             bucket_name=app.config["GRAMPS_S3_BUCKET_NAME"])
        else:
            return FileHandler(handle, info)

    @app.route("/api/media/<string:handle>")
    @jwt_required_ifauth
    def show_image(handle):
        handler = get_media_handler(handle)
        return handler.send_file()

    @app.route("/api/thumbnail/<string:handle>/<int:size>")
    @jwt_required_ifauth
    @cache.cached()
    def show_thumbnail_square(handle, size):
        handler = get_media_handler(handle)
        return handler.send_thumbnail_square(size)

    @app.route(
        "/api/thumbnail/<string:handle>/<int:size>/<int:x1>/<int:y1>/<int:x2>/<int:y2>"
    )
    @jwt_required_ifauth
    @cache.cached()
    def show_thumbnail_square_cropped(handle, size, x1, y1, x2, y2):
        handler = get_media_handler(handle)
        return handler.send_thumbnail_square_cropped(size, x1, y1, x2, y2)

    return app
Example #29
0
import os
from flask import Flask, request, jsonify, abort, make_response, redirect, url_for, send_from_directory, send_file
from flask_restful import Api, Resource, reqparse
from flask_httpauth import HTTPBasicAuth
from flask_compress import Compress
from util import Database
from werkzeug.utils import secure_filename
from requests.auth import HTTPDigestAuth
import requests
import hashlib
from PIL import Image
import io

app = Flask(__name__, static_url_path="")
api = Api(app)
Compress(app)
auth = HTTPBasicAuth()
db = Database()


@auth.get_password
def get_password(username):
    return db.getPassword(username)


@auth.error_handler
def unauthorized():
    # return 403 instead of 401 to prevent default browser dialog
    return make_response(jsonify({'message': 'Unauthorized access'}), 403)

Example #30
0
File: app.py Project: bcgov/gwa-api
def create_app(test_config=None):

    log = logging.getLogger(__name__)

    # a = connexion.FlaskApp(__name__, specification_dir='v1/spec/')

    # a.add_api('v1.yaml', arguments={
    #     "tokeninfo_url": discovery["introspection_endpoint"],
    #     "authorization_url": discovery["authorization_endpoint"],
    #     "accesstoken_url": discovery["token_endpoint"]
    # })

    # app = a.app
    app = Flask(__name__)

    conf = config.Config()
    if test_config is None:
        app.config.update(conf.data)
    else:
        # load the test config if passed in
        app.config.update(conf.data)
        app.config.update(test_config)

    ##Routes##
    v1.Register(app)
    v2.Register(app)
    Compress(app)

    @app.before_request
    def before_request():
        from timeit import default_timer as timer

        g.request_start_time = timer()
        g.request_time = lambda: "%s" % (timer() - g.request_start_time)
        resp = Response()
        resp.headers['Content-Type'] = ["application/json"]

    @app.after_request
    def after_request(response):
        set_cors_headers_on_response(response)
        log.debug('Rendered in %ss', g.request_time())
        return response

    @app.errorhandler(HTTPStatus.NOT_FOUND)
    def not_found(param):
        content = jsonify({"error": "Not Found", "code": HTTPStatus.NOT_FOUND})
        return make_response(content, HTTPStatus.NOT_FOUND)

    @app.errorhandler(HTTPStatus.INTERNAL_SERVER_ERROR)
    def internal_server_error(error):
        log.error("Internal Error %s - %s" % (request.remote_addr, str(error)))
        content = jsonify({
            "error": "{error}",
            "code": HTTPStatus.INTERNAL_SERVER_ERROR
        })
        log.error(request.get_data())
        log.error(request.form)
        log.error(request.headers)
        return make_response(content, HTTPStatus.INTERNAL_SERVER_ERROR)

    @app.errorhandler(HTTPStatus.BAD_REQUEST)
    def bad_request_error(error):
        log.error("Bad Request %s - %s" % (request.remote_addr, str(error)))
        content = jsonify({
            "error": "Bad Request",
            "code": HTTPStatus.BAD_REQUEST
        })
        log.error(request.get_data())
        log.error(request.form)
        log.error(request.headers)
        return make_response(content, HTTPStatus.BAD_REQUEST)

    @app.errorhandler(JoseError)
    def forbidden(error):
        log.error("Denied access %s - %s" % (request.remote_addr, str(error)))
        content = jsonify({"error": "Invalid Token"})
        return make_response(content, HTTPStatus.UNAUTHORIZED)

    @app.errorhandler(ExpiredTokenError)
    def expired_token(error):
        content = jsonify({"error": "Token Expired"})
        return make_response(content, HTTPStatus.UNAUTHORIZED)

    @app.route('/', methods=['GET'], strict_slashes=False)
    def index():
        """
        Returns a list of valid API version endpoints
        :return: JSON of valid API version endpoints
        """
        return jsonify([url_for(".v1.get_status", _external=True)])

    @app.route('/version', methods=['GET'], strict_slashes=False)
    def version():
        """
        Get the current version of the api
        """
        from os import environ
        hash = ""
        if environ.get('GITHASH') is not None:
            hash = environ.get("GITHASH")

        # import pkg_resources  # part of setuptools
        # print(pkg_resources)
        # v = pkg_resources.get_distribution("gwa-kong").version
        v = ""

        version = v
        if hash != "":
            version += "-" + hash

        responseObj = {"v": v, "hash": hash, "version": version}
        return jsonify(responseObj)

    return app