Example #1
0
def create_app(settings_ns):

    babel = Babel()
    app = Flask(
        __name__,
        static_url_path="/static",
        static_folder="static",
        instance_relative_config=False,
    )

    app.config.from_object(settings_ns)

    app.register_blueprint(main_bp)
    app.jinja_env.filters["clean_uri"] = clean_uri
    app.context_processor(utility_processor)
    babel.init_app(app)

    if app.config["DEBUG"]:
        try:
            from flask_debugtoolbar import DebugToolbarExtension
        except ImportError:
            LOGGER.info('cannot import lib "flask_debugtoolbar". '
                        'Make sure it is installed and available in the '
                        'import path.')
        else:
            toolbar = DebugToolbarExtension()
            toolbar.init_app(app)

    return app
Example #2
0
def register_babel(app):
    babel = Babel()
    babel.init_app(app)

    class CustomJSONEncoder(JSONEncoder):
        """This class adds support for lazy translation texts to Flask's
        JSON encoder. This is necessary when flashing translated texts."""

        def default(self, obj):
            from speaklater import is_lazy_string
            if is_lazy_string(obj):
                try:
                    return unicode(obj)  # python 2
                except NameError:
                    return str(obj)  # python 3
            return super(CustomJSONEncoder, self).default(obj)

    app.json_encoder = CustomJSONEncoder

    @babel.localeselector
    def get_locale():
        user = getattr(g, 'user', None)
        if user is not None:
            if g.user.is_authenticated:
                return user.setting.locale or 'zh'
        return request.accept_languages.best_match(app.config[
            'LANGUAGES'].keys())

    @babel.timezoneselector
    def get_timezone():
        user = getattr(g, 'user', None)
        if user is not None:
            if g.user.is_authenticated:
                return user.setting.timezone or 'UTC'
        return 'UTC'
Example #3
0
def register_babel(app):
    translations = os.path.abspath(os.path.join(
        os.path.dirname(__file__), os.pardir, 'translations'))
    domain = Domain(translations)
    babel = Babel(default_domain=domain)
    babel.init_app(app)

    class CustomJSONEncoder(JSONEncoder):
        """This class adds support for lazy translation texts to Flask's
        JSON encoder. This is necessary when flashing translated texts."""

        def default(self, obj):
            from speaklater import is_lazy_string
            if is_lazy_string(obj):
                try:
                    return unicode(obj)  # python 2
                except NameError:
                    return str(obj)  # python 3
            return super(CustomJSONEncoder, self).default(obj)

    app.json_encoder = CustomJSONEncoder

    @babel.localeselector
    def get_locale():
        return request.accept_languages.best_match(['zh', 'en'])

    @babel.timezoneselector
    def get_timezone():
        return 'UTC'
Example #4
0
    def __init__(self, app=None, date_formats=None, localeselector=None,
                 timezoneselector=None,
                 entry_point_group='invenio_i18n.translations'):
        """Initialize extension.

        :param app: Flask application.
        :param data_formats: Override default date/time formatting.
        :param localeselector: Callback function used for locale selection.
            (Default: :func:`invenio_i18n.selectors.get_locale()`)
        :param timezoneselector: Callback function used for timezone selection.
            (Default: ``BABEL_DEFAULT_TIMEZONE``)
        :param entry_point_group: Entrypoint used to load translations from.
            Set to ``None`` to not load translations from entry points.
        """
        self.domain = MultidirDomain()
        self.babel = Babel(
            date_formats=date_formats,
            configure_jinja=True,
            default_domain=self.domain,
        )
        self.localeselector = localeselector
        self.timezoneselector = timezoneselector
        self.entry_point_group = entry_point_group
        self._locales_cache = None
        self._languages_cache = None

        if app:
            self.init_app(app)
Example #5
0
    def __init__(self, app=None, date_formats=None, localeselector=None,
                 timezoneselector=None,
                 entry_point_group='invenio_i18n.translations'):
        """Initialize extension."""
        self.babel = Babel(
            date_formats=date_formats,
            configure_jinja=True,
            default_domain=MultidirDomain())

        self.localeselector = localeselector
        self.timezoneselector = timezoneselector
        self.entry_point_group = entry_point_group
        self._locales_cache = None
        self._languages_cache = None

        if app:
            self.init_app(app)
Example #6
0
def create_app(config_filename="config.py",
               app_name=None,
               register_blueprints=True):
    # App configuration
    app = Flask(app_name or __name__)
    app.config.from_pyfile(config_filename)

    socketio.init_app(app, message_queue=app.config["SOCKETIO_MESSAGE_QUEUE"])

    app.jinja_env.add_extension("jinja2.ext.with_")
    app.jinja_env.add_extension("jinja2.ext.do")

    if HAS_SENTRY:
        app.config["SENTRY_RELEASE"] = raven.fetch_git_sha(
            os.path.dirname(__file__))
        sentry = Sentry(app, dsn=app.config["SENTRY_DSN"])  # noqa: F841
        print("Sentry support activated")
        print("Sentry DSN: %s" % app.config["SENTRY_DSN"])

    if app.config["DEBUG"] is True:
        app.jinja_env.auto_reload = True
        app.logger.setLevel(logging.DEBUG)

    # Logging
    if not app.debug:
        formatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s "
                                      "[in %(pathname)s:%(lineno)d]")
        file_handler = RotatingFileHandler("%s/errors_app.log" % os.getcwd(),
                                           "a", 1000000, 1)
        file_handler.setLevel(logging.DEBUG)
        file_handler.setFormatter(formatter)
        app.logger.addHandler(file_handler)

    mail.init_app(app)
    migrate = Migrate(app, db)  # noqa: F841
    babel = Babel(app)  # noqa: F841
    toolbar = DebugToolbarExtension(app)  # noqa: F841

    db.init_app(app)

    git_version = ""
    gitpath = os.path.join(os.getcwd(), ".git")
    if os.path.isdir(gitpath):
        git_version = subprocess.check_output(
            ["git", "rev-parse", "--short", "HEAD"])
        if git_version:
            git_version = git_version.strip().decode("UTF-8")

    @babel.localeselector
    def get_locale():
        # if a user is logged in, use the locale from the user settings
        identity = getattr(g, "identity", None)
        if identity is not None and identity.id:
            return identity.user.locale
        # otherwise try to guess the language from the user accept
        # header the browser transmits.  We support fr/en in this
        # example.  The best match wins.
        return request.accept_languages.best_match(["fr", "en"])

    @babel.timezoneselector
    def get_timezone():
        identity = getattr(g, "identity", None)
        if identity is not None and identity.id:
            return identity.user.timezone

    @app.before_request
    def before_request():
        cfg = {
            "PYAIRWAVES_VERSION_VER": VERSION,
            "PYAIRWAVES_VERSION_GIT": git_version,
            "PYAIRWAVES_VERSION": "{0} ({1})".format(VERSION, git_version),
        }
        g.cfg = cfg

    @app.errorhandler(InvalidUsage)
    def handle_invalid_usage(error):
        response = jsonify(error.to_dict())
        response.status_code = error.status_code
        return response

    if register_blueprints:
        from controllers.main import bp_main

        app.register_blueprint(bp_main)

    @app.errorhandler(404)
    def page_not_found(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 404,
            "message": gettext("Page not found"),
            "e": msg,
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 404

    @app.errorhandler(403)
    def err_forbidden(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 403,
            "message": gettext("Access forbidden"),
            "e": msg,
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 403

    @app.errorhandler(410)
    def err_gone(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 410,
            "message": gettext("Gone"),
            "e": msg
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 410

    if not app.debug:

        @app.errorhandler(500)
        def err_failed(msg):
            pcfg = {
                "title": gettext("Whoops, something failed."),
                "error": 500,
                "message": gettext("Something is broken"),
                "e": msg,
            }
            return render_template("error_page.jinja2", pcfg=pcfg), 500

    @app.after_request
    def set_x_powered_by(response):
        response.headers["X-Powered-By"] = "pyAirwaves"
        return response

    # Other commands
    @app.cli.command()
    def routes():
        """Dump all routes of defined app"""
        table = texttable.Texttable()
        table.set_deco(texttable.Texttable().HEADER)
        table.set_cols_dtype(["t", "t", "t"])
        table.set_cols_align(["l", "l", "l"])
        table.set_cols_width([50, 30, 80])

        table.add_rows([["Prefix", "Verb", "URI Pattern"]])

        for rule in sorted(app.url_map.iter_rules(), key=lambda x: str(x)):
            methods = ",".join(rule.methods)
            table.add_row([rule.endpoint, methods, rule])

        print(table.draw())

    @app.cli.command()
    def config():
        """Dump config"""
        pp(app.config)

    @app.cli.command()
    def seed():
        """Seed database with default content"""
        # make_db_seed(db)
        pass

    @app.cli.command()
    def download_and_ingest_faa():
        """Downloads and ingest FAA datas"""
        utils_download_and_ingest_faa()

    @app.cli.command()
    def update_db():
        """Downloads and ingest various datas"""
        update_all_db()

    @app.cli.command()
    def import_aircrafts():
        """Ingest aircrafts"""
        update_aircrafts()

    @app.cli.command()
    def import_registrations():
        """Ingest registrations"""
        update_registrations()

    return app
    webapp.config['MAIL_USE_SSL'] = app.smtp['use_ssl']
    webapp.config['MAIL_USE_TLS'] = app.smtp['use_tls']
    webapp.config['MAIL_PORT'] = app.smtp['port']

###############################################################################
# Initialize standard Flask extensions

db.init_app(webapp)

csrf = CSRFProtect(webapp)
security = Security(webapp, user_datastore,
                    login_form=CustomLoginForm,
                    register_form=CustomRegisterForm)
mail = Mail(webapp)
migrate = Migrate(webapp, db)
babel = Babel(webapp)

###############################################################################
# Hooks


@webapp.before_first_request
def init_database():
    """Initiate database and create admin user"""
    db.create_all()
    for role_definition in app.role_definitions:
        name = role_definition['name']
        description = role_definition['description']
        permissions = role_definition['permissions']
        level = role_definition['level']
        user_datastore.find_or_create_role(
Example #8
0
def app(request):
    app = Flask(__name__)
    app.response_class = Response
    app.debug = True
    app.config["SECRET_KEY"] = "secret"
    app.config["TESTING"] = True
    app.config["LOGIN_DISABLED"] = False
    app.config["WTF_CSRF_ENABLED"] = False
    app.config["SECURITY_TWO_FACTOR_SECRET"] = {
        "1": "TjQ9Qa31VOrfEzuPy4VHQWPCTmRzCnFzMKLxXYiZu9B"
    }
    app.config["SECURITY_TWO_FACTOR_SMS_SERVICE"] = "test"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

    app.config["SECURITY_PASSWORD_SALT"] = "salty"
    # Make this plaintext for most tests - reduces unit test time by 50%
    app.config["SECURITY_PASSWORD_HASH"] = "plaintext"
    # Make this hex_md5 for token tests
    app.config["SECURITY_HASHING_SCHEMES"] = ["hex_md5"]
    app.config["SECURITY_DEPRECATED_HASHING_SCHEMES"] = []

    for opt in [
            "changeable",
            "recoverable",
            "registerable",
            "trackable",
            "passwordless",
            "confirmable",
            "two_factor",
    ]:
        app.config["SECURITY_" + opt.upper()] = opt in request.keywords

    pytest_major = int(pytest.__version__.split(".")[0])
    if pytest_major >= 4:
        marker_getter = request.node.get_closest_marker
    else:
        marker_getter = request.keywords.get
    settings = marker_getter("settings")
    babel = marker_getter("babel")
    if settings is not None:
        for key, value in settings.kwargs.items():
            app.config["SECURITY_" + key.upper()] = value

    mail = Mail(app)
    if babel is None or babel.args[0]:
        Babel(app)
    app.json_encoder = JSONEncoder
    app.mail = mail

    @app.route("/")
    def index():
        return render_template("index.html", content="Home Page")

    @app.route("/profile")
    @login_required
    def profile():
        return render_template("index.html", content="Profile Page")

    @app.route("/post_login")
    @login_required
    def post_login():
        return render_template("index.html", content="Post Login")

    @app.route("/http")
    @http_auth_required
    def http():
        return "HTTP Authentication"

    @app.route("/http_custom_realm")
    @http_auth_required("My Realm")
    def http_custom_realm():
        return render_template("index.html", content="HTTP Authentication")

    @app.route("/token", methods=["GET", "POST"])
    @auth_token_required
    def token():
        return render_template("index.html", content="Token Authentication")

    @app.route("/multi_auth")
    @auth_required("session", "token", "basic")
    def multi_auth():
        return render_template("index.html",
                               content="Session, Token, Basic auth")

    @app.route("/post_logout")
    def post_logout():
        return render_template("index.html", content="Post Logout")

    @app.route("/post_register")
    def post_register():
        return render_template("index.html", content="Post Register")

    @app.route("/post_confirm")
    def post_confirm():
        return render_template("index.html", content="Post Confirm")

    @app.route("/admin")
    @roles_required("admin")
    def admin():
        return render_template("index.html", content="Admin Page")

    @app.route("/admin_and_editor")
    @roles_required("admin", "editor")
    def admin_and_editor():
        return render_template("index.html", content="Admin and Editor Page")

    @app.route("/admin_or_editor")
    @roles_accepted("admin", "editor")
    def admin_or_editor():
        return render_template("index.html", content="Admin or Editor Page")

    @app.route("/simple")
    @roles_accepted("simple")
    def simple():
        return render_template("index.html", content="SimplePage")

    @app.route("/admin_perm")
    @permissions_accepted("full-write", "super")
    def admin_perm():
        return render_template("index.html",
                               content="Admin Page with full-write or super")

    @app.route("/admin_perm_required")
    @permissions_required("full-write", "super")
    def admin_perm_required():
        return render_template("index.html", content="Admin Page required")

    @app.route("/unauthorized")
    def unauthorized():
        return render_template("unauthorized.html")

    @app.route("/page1")
    def page_1():
        return "Page 1"

    @app.route("/json", methods=["GET", "POST"])
    def echo_json():
        return jsonify(flask_request.get_json())

    return app
Example #9
0
def create_app(config_filename="config.py",
               app_name=None,
               register_blueprints=True):
    # App configuration
    app = Flask(app_name or __name__)
    app.config.from_pyfile(config_filename)

    Bootstrap(app)

    app.jinja_env.add_extension("jinja2.ext.with_")
    app.jinja_env.add_extension("jinja2.ext.do")
    app.jinja_env.globals.update(is_admin=is_admin)
    app.jinja_env.filters["localize"] = dt_utc_to_user_tz
    app.jinja_env.filters["show_date_no_offset"] = show_date_no_offset

    if HAS_SENTRY:
        app.config["SENTRY_RELEASE"] = raven.fetch_git_sha(
            os.path.dirname(__file__))
        sentry = Sentry(app, dsn=app.config["SENTRY_DSN"])  # noqa: F841
        print(" * Sentry support activated")
        print(" * Sentry DSN: %s" % app.config["SENTRY_DSN"])

    if app.config["DEBUG"] is True:
        app.jinja_env.auto_reload = True
        app.logger.setLevel(logging.DEBUG)

    # Logging
    if not app.debug:
        formatter = logging.Formatter(
            "%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]"
        )
        file_handler = RotatingFileHandler("%s/errors_app.log" % os.getcwd(),
                                           "a", 1000000, 1)
        file_handler.setLevel(logging.DEBUG)
        file_handler.setFormatter(formatter)
        app.logger.addHandler(file_handler)

    mail.init_app(app)
    migrate = Migrate(app, db)  # noqa: F841
    babel = Babel(app)  # noqa: F841
    toolbar = DebugToolbarExtension(app)  # noqa: F841

    db.init_app(app)

    # Setup Flask-Security
    security = Security(  # noqa: F841
        app,
        user_datastore,
        register_form=ExtendedRegisterForm,
        confirm_register_form=ExtendedRegisterForm)

    @FlaskSecuritySignals.password_reset.connect_via(app)
    @FlaskSecuritySignals.password_changed.connect_via(app)
    def log_password_reset(sender, user):
        if not user:
            return
        # add_user_log(user.id, user.id, "user", "info", "Your password has been changed !")

    @FlaskSecuritySignals.reset_password_instructions_sent.connect_via(app)
    def log_reset_password_instr(sender, user, token):
        if not user:
            return
        # add_user_log(user.id, user.id, "user", "info", "Password reset instructions sent.")

    git_version = ""
    gitpath = os.path.join(os.getcwd(), ".git")
    if os.path.isdir(gitpath):
        git_version = subprocess.check_output(
            ["git", "rev-parse", "--short", "HEAD"])
        if git_version:
            git_version = git_version.strip().decode("UTF-8")

    @babel.localeselector
    def get_locale():
        # if a user is logged in, use the locale from the user settings
        # FIXME: not implemented yet
        # identity = getattr(g, "identity", None)
        # if identity is not None and identity.id:
        #     return identity.user.locale
        # otherwise try to guess the language from the user accept
        # header the browser transmits.  We support fr/en in this
        # example.  The best match wins.
        return request.accept_languages.best_match(["fr", "en"])

    @babel.timezoneselector
    def get_timezone():
        # identity = getattr(g, "identity", None)
        # if identity is not None and identity.id:
        #     return identity.user.timezone
        # FIXME: not implemented yet
        pass

    @app.before_request
    def before_request():
        cfg = {
            "AHRL_VERSION_VER": VERSION,
            "AHRL_VERSION_GIT": git_version,
            "AHRL_VERSION": "{0} ({1})".format(VERSION, git_version),
        }
        g.cfg = cfg

    @app.errorhandler(InvalidUsage)
    def handle_invalid_usage(error):
        response = jsonify(error.to_dict())
        response.status_code = error.status_code
        return response

    pictures = UploadSet("pictures", IMAGES)
    configure_uploads(app, pictures)
    patch_request_class(app, 5 * 1024 * 1024)  # 5m limit

    if register_blueprints:
        from controllers.admin import bp_admin

        app.register_blueprint(bp_admin)

        from controllers.contacts import bp_contacts

        app.register_blueprint(bp_contacts)

        from controllers.logbooks import bp_logbooks

        app.register_blueprint(bp_logbooks)

        from controllers.main import bp_main

        app.register_blueprint(bp_main)

        from controllers.notes import bp_notes

        app.register_blueprint(bp_notes)

        from controllers.qsos import bp_qsos

        app.register_blueprint(bp_qsos)

        from controllers.tools import bp_tools

        app.register_blueprint(bp_tools)

        from controllers.users import bp_users

        app.register_blueprint(bp_users)

        from controllers.extapi import bp_extapi

        app.register_blueprint(bp_extapi)

    @app.route("/uploads/<string:thing>/<path:stuff>", methods=["GET"])
    def get_uploads_stuff(thing, stuff):
        if app.debug:
            directory = safe_join(app.config["UPLOADS_DEFAULT_DEST"], thing)
            app.logger.debug(f"serving {stuff} from {directory}")
            return send_from_directory(directory, stuff, as_attachment=True)
        else:
            app.logger.debug(f"X-Accel-Redirect serving {stuff}")
            resp = Response("")
            resp.headers[
                "Content-Disposition"] = f"attachment; filename={stuff}"
            resp.headers[
                "X-Accel-Redirect"] = f"/_protected/media/tracks/{thing}/{stuff}"
            return resp

    @app.errorhandler(404)
    def page_not_found(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 404,
            "message": gettext("Page not found"),
            "e": msg,
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 404

    @app.errorhandler(403)
    def err_forbidden(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 403,
            "message": gettext("Access forbidden"),
            "e": msg,
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 403

    @app.errorhandler(410)
    def err_gone(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 410,
            "message": gettext("Gone"),
            "e": msg
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 410

    if not app.debug:

        @app.errorhandler(500)
        def err_failed(msg):
            pcfg = {
                "title": gettext("Whoops, something failed."),
                "error": 500,
                "message": gettext("Something is broken"),
                "e": msg,
            }
            return render_template("error_page.jinja2", pcfg=pcfg), 500

    @app.after_request
    def set_x_powered_by(response):
        response.headers["X-Powered-By"] = "ahrl"
        return response

    # Commands from Flask CLI

    @app.cli.command()
    def routes():
        """Dump all routes of defined app"""
        table = texttable.Texttable()
        table.set_deco(texttable.Texttable().HEADER)
        table.set_cols_dtype(["t", "t", "t"])
        table.set_cols_align(["l", "l", "l"])
        table.set_cols_width([50, 30, 80])

        table.add_rows([["Prefix", "Verb", "URI Pattern"]])

        for rule in sorted(app.url_map.iter_rules(), key=lambda x: str(x)):
            methods = ",".join(rule.methods)
            table.add_row([rule.endpoint, methods, rule])

        print(table.draw())

    @app.cli.command()
    def config():
        """Dump config"""
        pp(app.config)

    @app.cli.command()
    def seed():
        """Seed database with default content"""
        make_db_seed(db)

    @app.cli.command()
    def createuser():
        """Create an user"""
        username = click.prompt("Username", type=str)
        email = click.prompt("Email", type=str)
        password = click.prompt("Password",
                                type=str,
                                hide_input=True,
                                confirmation_prompt=True)
        while True:
            role = click.prompt("Role [admin/user]", type=str)
            if role == "admin" or role == "user":
                break

        if click.confirm("Do you want to continue ?"):
            role = Role.query.filter(Role.name == role).first()
            if not role:
                raise click.UsageError("Roles not present in database")
            u = user_datastore.create_user(name=username,
                                           email=email,
                                           password=encrypt_password(password),
                                           roles=[role])

            db.session.commit()

            if FSConfirmable.requires_confirmation(u):
                FSConfirmable.send_confirmation_instructions(u)
                print("Look at your emails for validation instructions.")

    @app.cli.group()
    def cron():
        """Commands to be run regullary"""
        pass

    @cron.command()
    @click.option("--file",
                  default=None,
                  help="Local file to import instead of downloading",
                  type=click.Path(exists=True))
    def update_dxcc_from_cty(file):
        """Update DXCC tables from cty.xml"""
        print("-- STARTED on {0}".format(datetime.datetime.now()))
        update_dxcc_from_cty_xml(file)
        print("-- FINISHED on {0}".format(datetime.datetime.now()))

    @cron.command()
    def update_qsos_countries():
        """Update QSOs with empty country"""
        print("-- STARTED on {0}".format(datetime.datetime.now()))
        update_qsos_without_countries()
        print("-- FINISHED on {0}".format(datetime.datetime.now()))

    @cron.command()
    @click.option("--dryrun",
                  default=False,
                  help="Dry run, doesn't commit anything")
    def sync_to_eqsl(dryrun=False):
        """Push to eQSL logs with requested eQSL sync"""
        print("-- STARTED on {0}".format(datetime.datetime.now()))
        cron_sync_eqsl(dryrun)
        print("-- FINISHED on {0}".format(datetime.datetime.now()))

    @cron.command()
    @click.option("--dryrun",
                  default=False,
                  help="Dry run, doesn't commit anything")
    def sync_from_eqsl(dryrun=False):
        """Fetch from eQSL logs """
        print("-- STARTED on {0}".format(datetime.datetime.now()))
        cron_sync_from_eqsl(dryrun)
        print("-- FINISHED on {0}".format(datetime.datetime.now()))

    @cron.command()
    def update_qsos_hamqth():
        """Update QSOs with datas from HamQTH"""
        print("-- STARTED on {0}".format(datetime.datetime.now()))
        update_qsos_from_hamqth()
        print("-- FINISHED on {0}".format(datetime.datetime.now()))

    @cron.command()
    def populate_logs_gridsquare():
        """Update QSOs with empty gridsquare cache"""
        print("-- STARTED on {0}".format(datetime.datetime.now()))
        populate_logs_gridsquare_cache()
        print("-- FINISHED on {0}".format(datetime.datetime.now()))

    return app
Example #10
0
# -*- coding: utf-8 -*-

from flask import Flask, request, session
from flask_sqlalchemy import SQLAlchemy
from flask_babelex import Babel, Domain, lazy_gettext

from wtforms import validators

from plumbum import Plumbum, ModelView

sqla_domain = Domain(domain='sqla-babel', dirname='locales')

# Create application
app = Flask(__name__)
babel = Babel(app, default_domain=sqla_domain)

app.config['SECRET_KEY'] = '1234'

app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sample_data.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['PLUMBUM_DEBUG_TEMPLATE'] = False

db = SQLAlchemy(app)


@babel.localeselector
def get_locale():
    override = request.args.get('lang')

    if override:
def create_app():
    
    
    # Create Flask app load app.config
    app = Flask(__name__)
    app.config.from_object(__name__+'.ConfigClass')

    # Initialize Flask-BabelEx
    babel = Babel(app)
    # Initialize Flask-SQLAlchemy
    @babel.localeselector
    def get_locale():
       translations = [str(translation) for translation in babel.list_translations()]
    #   return request.accept_languages.best_match(translations)
    # @babel.localeselector
    #def get_locale():
    #   if request.args.get('lang'):
    #       session['lang'] = request.args.get('lang')
    #       return session.get('lang', 'tr')

    db = SQLAlchemy(app)

    # Define the User data-model.
    # NB: Make sure to add flask_user UserMixin !!!
    class User(db.Model, UserMixin):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        active = db.Column('is_active', db.Boolean(), nullable=False, server_default='1')

        # User authentication information. The collation='NOCASE' is required
        # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'.
        email = db.Column(db.String(255, collation='NOCASE'), nullable=False, unique=True)
        email_confirmed_at = db.Column(db.DateTime())
        password = db.Column(db.String(255), nullable=False, server_default='')

        # User information
        first_name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='')
        last_name = db.Column(db.String(100, collation='NOCASE'), nullable=False, server_default='')

        # Define the relationship to Role via UserRoles
        roles = db.relationship('Role', secondary='user_roles')

    # Define the Role data-model
    class Role(db.Model):
        __tablename__ = 'roles'
        id = db.Column(db.Integer(), primary_key=True)
        name = db.Column(db.String(50), unique=True)

    # Define the UserRoles association table
    class UserRoles(db.Model):
        __tablename__ = 'user_roles'
        id = db.Column(db.Integer(), primary_key=True)
        user_id = db.Column(db.Integer(), db.ForeignKey('users.id', ondelete='CASCADE'))
        role_id = db.Column(db.Integer(), db.ForeignKey('roles.id', ondelete='CASCADE'))

    # Setup Flask-User and specify the User data-model
    user_manager = UserManager(app, db, User)

    # Create all database tables
    db.create_all()

    # Create '*****@*****.**' user with no roles
    if not User.query.filter(User.email == '*****@*****.**').first():
        user = User(
            email='*****@*****.**',
            email_confirmed_at=datetime.datetime.utcnow(),
            password=user_manager.hash_password('Password1'),
        )
        db.session.add(user)
        db.session.commit()

    # Create '*****@*****.**' user with 'Admin' and 'Agent' roles
    if not User.query.filter(User.email == '*****@*****.**').first():
        user = User(
            email='*****@*****.**',
            email_confirmed_at=datetime.datetime.utcnow(),
            password=user_manager.hash_password('Password1'),
        )
        user.roles.append(Role(name='Admin'))
        user.roles.append(Role(name='Agent'))
        db.session.add(user)
        db.session.commit()


    @app.route('/')
        def home_page():
            return render_template_string("""
                    {% extends "flask_user_layout.html" %}
                    {% block content %}
                        <h2>{%trans%}Ana sayfa{%endtrans%}</h2>
                        <h1>{%trans%}Bu web sitesinin anasayfasıdır{%endtrans%}</h1>
                        <p><a href={{ url_for('user.register') }}>{%trans%}Kayıt ol{%endtrans%}</a></p>
                        <p><a href={{ url_for('user.login') }}>{%trans%}Giriş Yap{%endtrans%}</a></p>
                        <p><a href={{ url_for('home_page') }}>{%trans%}Ana sayfa{%endtrans%}</a> (Herkes erişebilir)</p>
                        <p><a href={{ url_for('member_page') }}>{%trans%}Üye sayfası{%endtrans%}</a> (Giriş gerekli: [email protected] / Password1)</p>
                        <p><a href={{ url_for('admin_page') }}>{%trans%}Admin sayfası{%endtrans%}</a> (Rol gerekli: [email protected] / Password1)</p>
                        <p><a href={{ url_for('user.logout') }}>{%trans%}Çıkış{%endtrans%}</a></p>
                    {% endblock %}
                    """)
Example #12
0
def create_app(config_name):
    app = Flask(config_name)
    app.config.from_object(config[config_name])

    # 全局响应头
    @app.after_request
    def after_request(response):
        if "Access-Control-Allow-Origin" not in response.headers.keys():
            response.headers['Access-Control-Allow-Origin'] = '*'
        if request.method == 'OPTIONS':
            response.headers[
                'Access-Control-Allow-Methods'] = 'DELETE, GET, POST, PUT'
            headers = request.headers.get('Access-Control-Request-Headers')
            if headers:
                response.headers['Access-Control-Allow-Headers'] = headers
        return response

    # 自定义错误日志
    handler = logging.FileHandler('app.log', encoding='UTF-8')
    logging_format = logging.Formatter(
        '%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s'
    )
    handler.setFormatter(logging_format)
    app.logger.addHandler(handler)

    def init_login():
        login_manager = login.LoginManager()
        login_manager.setup_app(app)

        # Create user loader function
        @login_manager.user_loader
        def load_user(user_id):
            return AdminUser.objects(id=user_id).first()

    @app.errorhandler(404)
    def page_not_found(e):
        return jsonify(msg='404 page not found')

    # 注册所有蓝图
    for bp_name in blueprints:
        bp = import_string(bp_name)
        app.register_blueprint(bp)

    config[config_name].init_app(app)
    babel = Babel(app)
    db.init_app(app)
    docs.init_app(app)
    admin.init_app(app)
    init_login()
    limiter.init_app(app)
    celery.init_app(app)
    redis.init_app(app)
    celery.conf.update(app.config)

    db.register_connection(db='ultrabear_homework',
                           alias="home",
                           port=PORT,
                           username=NAME,
                           password=PWD)
    # 跨域
    CORS(app, supports_credentials=True)
    return app
Example #13
0
def app(request):
    """Flask application fixture."""
    # Set temporary instance path for sqlite
    instance_path = tempfile.mkdtemp()
    app = Flask('testapp', instance_path=instance_path)

    app.config.update(
        SQLALCHEMY_DATABASE_URI=os.environ.get(
            'SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'
        ),
        TESTING=True,
        SECRET_KEY='SECRET_KEY',
        SQLALCHEMY_TRACK_MODIFICATIONS=False,
        JSONSCHEMAS_ENDPOINT='/schema',
        JSONSCHEMAS_HOST='ils.test.rero.ch',
        RECORDS_UI_ENDPOINTS={
            "doc": {
                "pid_type": "doc",
                "route": "/documents/<pid_value>",
                "template": "rero_ils/detailed_view_documents_items.html"
            }
        }
    )

    InvenioDB(app)
    InvenioPIDStore(app)
    InvenioRecords(app)
    InvenioAccounts(app)
    REROILSAPP(app)
    InvenioAccess(app)
    InvenioJSONSchemas(app)
    InvenioRecordsUI(app)
    Menu(app)
    Babel(app)
    app.register_blueprint(item_blueprint)

    @app.route('/test/login')
    def login():
        from flask_security import login_user
        from flask import request as flask_request

        role = flask_request.args.get('role')
        if role:
            datastore.create_role(name=role)
            datastore.add_role_to_user(user, role)
        datastore.commit()
        login_user(user)
        return "Logged In"

    @app.route('/test/login')
    def logout():
        from flask_security import logout_user
        logout_user()
        return "Logged Out"

    from invenio_db import db as db_
    with app.app_context():
        if not database_exists(str(db_.engine.url)):
            create_database(str(db_.engine.url))
        db_.create_all()
        security = LocalProxy(lambda: app.extensions['security'])
        datastore = LocalProxy(lambda: security.datastore)
        user = datastore.create_user(
            email='*****@*****.**',
            active=True,
            password=hash_password('aafaf4as5fa')
        )
        yield app

        # Teardown instance path.
        db_.session.remove()
        db_.drop_all()
        shutil.rmtree(instance_path)
Example #14
0
def create_app():
    """ Flask application factory """

    # Create Flask app load app.config
    app = Flask(__name__)
    app.config.from_object(__name__ + '.ConfigClass')

    # Initialize Flask-BabelEx
    babel = Babel(app)
    # Initialize Flask-SQLAlchemy
    @babel.localeselector
    def get_locale():
        translations = [
            str(translation) for translation in babel.list_translations()
        ]

    #   return request.accept_languages.best_match(translations)
    # @babel.localeselector
    #def get_locale():
    #   if request.args.get('lang'):
    #       session['lang'] = request.args.get('lang')
    #       return session.get('lang', 'tr')

    db = SQLAlchemy(app)

    # Define the User data-model.
    # NB: Make sure to add flask_user UserMixin !!!
    class User(db.Model, UserMixin):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        active = db.Column('is_active',
                           db.Boolean(),
                           nullable=False,
                           server_default='1')

        # User authentication information. The collation='NOCASE' is required
        # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'.
        email = db.Column(db.String(255, collation='NOCASE'),
                          nullable=False,
                          unique=True)
        email_confirmed_at = db.Column(db.DateTime())
        password = db.Column(db.String(255), nullable=False, server_default='')

        # User information
        first_name = db.Column(db.String(100, collation='NOCASE'),
                               nullable=False,
                               server_default='')
        last_name = db.Column(db.String(100, collation='NOCASE'),
                              nullable=False,
                              server_default='')

        # Define the relationship to Role via UserRoles
        roles = db.relationship('Role', secondary='user_roles')

    # Define the Role data-model
    class Role(db.Model):
        __tablename__ = 'roles'
        id = db.Column(db.Integer(), primary_key=True)
        name = db.Column(db.String(50), unique=True)

    # Define the UserRoles association table
    class UserRoles(db.Model):
        __tablename__ = 'user_roles'
        id = db.Column(db.Integer(), primary_key=True)
        user_id = db.Column(db.Integer(),
                            db.ForeignKey('users.id', ondelete='CASCADE'))
        role_id = db.Column(db.Integer(),
                            db.ForeignKey('roles.id', ondelete='CASCADE'))

    # Setup Flask-User and specify the User data-model
    user_manager = UserManager(app, db, User)

    # Create all database tables
    db.create_all()

    # The Home page is accessible to anyone
    @app.route('/')
    def home():
        return render_template('/index.html')

    @app.route('/üye')
    def uye():
        veriler = User.query.all()

        return render_template('/üye.html', veriler=veriler)

    @app.route('/add', methods=["POST"])
    def adduser():
        email = request.form.get("e-mail")
        sifre = request.form.get("sifre")
        email_confirmed_at = datetime.datetime.utcnow()
        newuser = User(email=email,
                       password=sifre,
                       email_confirmed_at=email_confirmed_at)
        db.session.add(newuser)
        db.session.commit()
        return redirect(url_for("uye"))

    return app
Example #15
0
class InvenioI18N(object):
    """Invenio I18N extension."""

    def __init__(self, app=None, date_formats=None, localeselector=None,
                 timezoneselector=None,
                 entry_point_group='invenio_i18n.translations'):
        """Initialize extension.

        :param app: Flask application.
        :param data_formats: Override default date/time formatting.
        :param localeselector: Callback function used for locale selection.
            (Default: :func:`invenio_i18n.selectors.get_locale()`)
        :param timezoneselector: Callback function used for timezone selection.
            (Default: ``BABEL_DEFAULT_TIMEZONE``)
        :param entry_point_group: Entrypoint used to load translations from.
            Set to ``None`` to not load translations from entry points.
        """
        self.domain = MultidirDomain()
        self.babel = Babel(
            date_formats=date_formats,
            configure_jinja=True,
            default_domain=self.domain,
        )
        self.localeselector = localeselector
        self.timezoneselector = timezoneselector
        self.entry_point_group = entry_point_group
        self._locales_cache = None
        self._languages_cache = None

        if app:
            self.init_app(app)

    def init_app(self, app):
        """Flask application initialization.

        The initialization will:

         * Set default values for the configuration variables.
         * Load translations from paths specified in
           ``I18N_TRANSLATIONS_PATHS``.
         * Load translations from ``app.root_path>/translations`` if it exists.
         * Load translations from a specified entry point.
         * Add ``toutc`` and ``tousertimezone`` template filters.
         * Install a custom JSON encoder on app.
        """
        self.init_config(app)

        # Initialize Flask-BabelEx
        self.babel.init_app(app)
        self.babel.localeselector(self.localeselector or get_locale)
        self.babel.timezoneselector(self.timezoneselector or get_timezone)

        # 1. Paths listed in I18N_TRANSLATIONS_PATHS
        for p in app.config.get('I18N_TRANSLATIONS_PATHS', []):
            self.domain.add_path(p)
        # 2. <app.root_path>/translations
        app_translations = os.path.join(app.root_path, 'translations')
        if os.path.exists(app_translations):
            self.domain.add_path(app_translations)
        # 3. Entrypoints
        if self.entry_point_group:
            self.domain.add_entrypoint(self.entry_point_group)

        # Register blueprint if URL is set.
        if app.config['I18N_SET_LANGUAGE_URL'] \
           and app.config['I18N_LANGUAGES']:
            app.register_blueprint(
                blueprint, url_prefix=app.config['I18N_SET_LANGUAGE_URL'])

        # Register Jinja2 template filters for date formatting (Flask-Babel
        # already installs other filters).
        app.add_template_filter(filter_to_utc, name='toutc')
        app.add_template_filter(filter_to_user_timezone, name='tousertimezone')
        app.add_template_filter(filter_language_name, name='language_name')
        app.add_template_filter(
            filter_language_name_local, name='language_name_local')
        app.context_processor(lambda: dict(current_i18n=current_i18n))

        # Lazy string aware JSON encoder.
        app.json_encoder = get_lazystring_encoder(app)

        app.extensions['invenio-i18n'] = self

    def init_config(self, app):
        """Initialize configuration."""
        for k in dir(config):
            if k.startswith('I18N_'):
                app.config.setdefault(k, getattr(config, k))

    def iter_languages(self):
        """Iterate over list of languages."""
        default_lang = self.babel.default_locale.language
        default_title = self.babel.default_locale.get_display_name(
            default_lang)

        yield (default_lang, default_title)

        for l, title in current_app.config.get('I18N_LANGUAGES', []):
            yield l, title

    def get_languages(self):
        """Get list of languages."""
        if self._languages_cache is None:
            self._languages_cache = list(self.iter_languages())
        return self._languages_cache

    def get_locales(self):
        """Get a list of supported locales.

        Computes the list using ``I18N_LANGUAGES`` configuration variable.
        """
        if self._locales_cache is None:
            langs = [self.babel.default_locale]
            for l, dummy_title in current_app.config.get('I18N_LANGUAGES', []):
                langs.append(self.babel.load_locale(l))
            self._locales_cache = langs
        return self._locales_cache

    @property
    def locale(self):
        """Get current locale."""
        return get_current_locale()

    @property
    def language(self):
        """Get current language code."""
        return get_current_locale().language

    @property
    def timezone(self):
        """Get current timezone."""
        return get_current_timezone()
Example #16
0
class InvenioI18N(object):
    """Invenio I18N module."""
    def __init__(self,
                 app=None,
                 date_formats=None,
                 localeselector=None,
                 timezoneselector=None,
                 entrypoint='invenio_i18n.translations'):
        """Initialize extension."""
        self.babel = Babel(date_formats=date_formats,
                           configure_jinja=True,
                           default_domain=MultidirDomain())

        self.localeselector = localeselector
        self.timezoneselector = timezoneselector
        self.entrypoint = entrypoint
        self._locales_cache = None

        if app:
            self.init_app(app)

    def init_app(self, app):
        """Flask application initialization."""
        # Initialize Flask-BabelEx
        app.config.setdefault("I18N_LANGUAGES", [])

        # TODO: allow to plug custom localeselector and timezoneselector
        self.babel.init_app(app)
        self.babel.localeselector(self.localeselector or get_locale)
        self.babel.timezoneselector(self.timezoneselector or get_timezone)

        # Add paths to search for message catalogs
        domain = self.babel._default_domain
        # 1. Paths listed in I18N_TRANSLATIONS_PATHS
        for p in app.config.get("I18N_TRANSLATIONS_PATHS", []):
            domain.add_path(p)
        # 2. <app.root_path>/translations
        app_translations = os.path.join(app.root_path, 'translations')
        if os.path.exists(app_translations):
            domain.add_path(app_translations)
        # 3. Entrypoints
        if self.entrypoint:
            domain.add_entrypoint(self.entrypoint)

        # Register Jinja2 template filters for date formatting (Flask-Babel
        # already installs other filters).
        app.add_template_filter(filter_to_utc, name="toutc")
        app.add_template_filter(filter_to_user_timezone, name="tousertimezone")

        # Lazy string aware JSON encoder.
        app.json_encoder = get_lazystring_encoder(app)

        app.extensions['invenio-i18n'] = self

    def get_locales(self):
        """Get a list of supported locales."""
        if self._locales_cache is None:
            langs = [self.babel.default_locale]
            for l in current_app.config.get('I18N_LANGUAGES', []):
                langs.append(self.babel.load_locale(l))
            self._locales_cache = langs
        return self._locales_cache
Example #17
0
def create_app():
    """ Flask application factory """

    # Create Flask app load app.config
    app = Flask(__name__)
    app.config.from_object(__name__ + '.ConfigClass')

    # Initialize Flask-BabelEx
    babel = Babel(app)
    # Initialize Flask-SQLAlchemy
    @babel.localeselector
    def get_locale():
        translations = [
            str(translation) for translation in babel.list_translations()
        ]

    #   return request.accept_languages.best_match(translations)
    # @babel.localeselector
    #def get_locale():
    #   if request.args.get('lang'):
    #       session['lang'] = request.args.get('lang')
    #       return session.get('lang', 'tr')

    db = SQLAlchemy(app)

    # Define the User data-model.
    # NB: Make sure to add flask_user UserMixin !!!
    class User(db.Model, UserMixin):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        active = db.Column('is_active',
                           db.Boolean(),
                           nullable=False,
                           server_default='1')

        # User authentication information. The collation='NOCASE' is required
        # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'.
        email = db.Column(db.String(255, collation='NOCASE'),
                          nullable=False,
                          unique=True)
        email_confirmed_at = db.Column(db.DateTime())
        password = db.Column(db.String(255), nullable=False, server_default='')

        # User information
        first_name = db.Column(db.String(100, collation='NOCASE'),
                               nullable=False,
                               server_default='')
        last_name = db.Column(db.String(100, collation='NOCASE'),
                              nullable=False,
                              server_default='')

        # Define the relationship to Role via UserRoles
        roles = db.relationship('Role', secondary='user_roles')

    # Define the Role data-model
    class Role(db.Model):
        __tablename__ = 'roles'
        id = db.Column(db.Integer(), primary_key=True)
        name = db.Column(db.String(50), unique=True)

    # Define the UserRoles association table
    class UserRoles(db.Model):
        __tablename__ = 'user_roles'
        id = db.Column(db.Integer(), primary_key=True)
        user_id = db.Column(db.Integer(),
                            db.ForeignKey('users.id', ondelete='CASCADE'))
        role_id = db.Column(db.Integer(),
                            db.ForeignKey('roles.id', ondelete='CASCADE'))

    # Setup Flask-User and specify the User data-model
    user_manager = UserManager(app, db, User)

    # Create all database tables
    db.create_all()

    # The Home page is accessible to anyone
    @app.route('/')
    def index():

        return render_template("index.html")

    @app.route('/üye')
    def uye():
        veriler = User.query.all()
        return render_template("üye.html", veriler=veriler)

    @app.route('/members')
    @login_required  # Use of @login_required decorator
    def member_page():
        return render_template_string("""
                {% extends "flask_user_layout.html" %}
                {% block content %}
                    <h2>{%trans%}Üyeler sayfası {%endtrans%}</h2>
                    <h1>{%trans%}Sisteme giriş yapanlar bu sayfayı görüntüleyebilir{%endtrans%}</h1>
                    <p><a href={{ url_for('user.register') }}>{%trans%}Kayıt ol{%endtrans%}</a></p>
                    <p><a href={{ url_for('user.login') }}>{%trans%}Giriş Yap{%endtrans%}</a></p>
                    <p><a href={{ url_for('home_page') }}>{%trans%}Ana sayfa{%endtrans%}</a> (Herkes erişebilir)</p>
                    <p><a href={{ url_for('member_page') }}>{%trans%}Üye sayfası{%endtrans%}</a> (Giriş gerekli: [email protected] / Password1)</p>
                    <p><a href={{ url_for('admin_page') }}>{%trans%}Admin sayfası{%endtrans%}</a> (Rol gerekli: [email protected] / Password1)</p>
                    <p><a href={{ url_for('user.logout') }}>{%trans%}Çıkış{%endtrans%}</a></p>
                {% endblock %}
                """)

    @app.route('/admin')
    @roles_required('Admin')  #Use of @roles_required decorator
    def admin_page():
        return render_template_string("""
                {% extends "flask_user_layout.html" %}
                {% block content %}
                    <h2>{%trans%}Admin Sayfası{%endtrans%}</h2>
                    <h1>{%trans%}Bu yalnızca adminlerin giriş yapabildiği bir sayfadır{%endtrans%}</h1>
                    <p><a href={{ url_for('user.register') }}>{%trans%}Kayıt ol{%endtrans%}</a></p>
                    <p><a href={{ url_for('user.login') }}>{%trans%}Giriş Yap{%endtrans%}</a></p>
                    <p><a href={{ url_for('home_page') }}>{%trans%}Ana sayfa{%endtrans%}</a> (Herkes erişebilir)</p>
                    <p><a href={{ url_for('member_page') }}>{%trans%}Üye sayfası{%endtrans%}</a> (Giriş gerekli: [email protected] / Password1)</p>
                    <p><a href={{ url_for('admin_page') }}>{%trans%}Admin sayfası{%endtrans%}</a> (Rol gerekli: [email protected] / Password1)</p>
                    <p><a href={{ url_for('user.logout') }}>{%trans%}Çıkış{%endtrans%}</a></p>
                {% endblock %}
                """)

    @app.route('/add', methods=["POST"])
    def adduser():
        email = request.form.get("e-mail")
        sifre = request.form.get("sifre")
        email_confirmed_at = datetime.datetime.utcnow()
        newuser = User(email=email,
                       password=sifre,
                       email_confirmed_at=email_confirmed_at)
        db.session.add(newuser)
        db.session.commit()
        return redirect(url_for("uye"))

    return app
Example #18
0
        "ck": "ck_%(table_name)s_%(constraint_name)s",
        "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
        "pk": "pk_%(table_name)s"
    }
    metadata = MetaData(naming_convention=convention)
else:
    metadata = MetaData()

basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.env'))
db = SQLAlchemy(metadata=metadata)
migrate = Migrate()
mail = Mail()
security = Security()
socketio = SocketIO()
babelobject = Babel()
moment = Moment()

avatars = UploadSet('avatars', IMAGES)


# Fixes bug: url_for generates http endpoints instead of https which causes mixed-content-errors
class ReverseProxied(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        scheme = environ.get('HTTP_X_FORWARDED_PROTO')
        if scheme:
            environ['wsgi.url_scheme'] = scheme
        return self.app(environ, start_response)
Example #19
0
def create_app(config_filename="config.py",
               app_name=None,
               register_blueprints=True):
    # App configuration
    app = Flask(app_name or __name__)
    app.config.from_pyfile(config_filename)

    Bootstrap(app)

    app.jinja_env.add_extension("jinja2.ext.with_")
    app.jinja_env.add_extension("jinja2.ext.do")
    app.jinja_env.globals.update(is_admin=is_admin)
    app.jinja_env.globals.update(duration_elapsed_human=duration_elapsed_human)
    app.jinja_env.globals.update(duration_song_human=duration_song_human)

    if HAS_SENTRY:
        sentry_sdk.init(
            app.config["SENTRY_DSN"],
            integrations=[SentryFlaskIntegration(),
                          SentryCeleryIntegration()],
            release=f"{VERSION} ({GIT_VERSION})",
        )
        print(" * Sentry Flask/Celery support activated")
        print(" * Sentry DSN: %s" % app.config["SENTRY_DSN"])

    if app.config["DEBUG"] is True:
        app.jinja_env.auto_reload = True
        app.logger.setLevel(logging.DEBUG)

    # Logging
    if not app.debug:
        formatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s "
                                      "[in %(pathname)s:%(lineno)d]")
        file_handler = RotatingFileHandler("%s/errors_app.log" % os.getcwd(),
                                           "a", 1000000, 1)
        file_handler.setLevel(logging.DEBUG)
        file_handler.setFormatter(formatter)
        app.logger.addHandler(file_handler)

    mail.init_app(app)
    migrate = Migrate(app, db)  # noqa: F841
    babel = Babel(app)  # noqa: F841
    app.babel = babel
    toolbar = DebugToolbarExtension(app)  # noqa: F841

    db.init_app(app)

    # ActivityPub backend
    back = Reel2BitsBackend()
    ap.use_backend(back)

    # Setup Flask-Security
    security = Security(  # noqa: F841
        app,
        user_datastore,
        register_form=ExtendedRegisterForm,
        confirm_register_form=ExtendedRegisterForm)

    @FlaskSecuritySignals.password_reset.connect_via(app)
    @FlaskSecuritySignals.password_changed.connect_via(app)
    def log_password_reset(sender, user):
        if not user:
            return
        add_user_log(user.id, user.id, "user", "info",
                     "Your password has been changed !")

    @FlaskSecuritySignals.reset_password_instructions_sent.connect_via(app)
    def log_reset_password_instr(sender, user, token):
        if not user:
            return
        add_user_log(user.id, user.id, "user", "info",
                     "Password reset instructions sent.")

    @FlaskSecuritySignals.user_registered.connect_via(app)
    def create_actor_for_registered_user(app, user, confirm_token):
        if not user:

            return
        actor = create_actor(user)
        actor.user = user
        actor.user_id = user.id
        db.session.add(actor)
        db.session.commit()

    @babel.localeselector
    def get_locale():
        # if a user is logged in, use the locale from the user settings
        identity = getattr(g, "identity", None)
        if identity is not None and identity.id:
            return identity.user.locale
        # otherwise try to guess the language from the user accept
        # header the browser transmits.  We support fr/en in this
        # example.  The best match wins.
        return request.accept_languages.best_match(AVAILABLE_LOCALES)

    @babel.timezoneselector
    def get_timezone():
        identity = getattr(g, "identity", None)
        if identity is not None and identity.id:
            return identity.user.timezone

    @app.before_request
    def before_request():
        _config = Config.query.first()
        if not _config:
            flash(gettext("Config not found"), "error")

        cfg = {
            "REEL2BITS_VERSION_VER": VERSION,
            "REEL2BITS_VERSION_GIT": GIT_VERSION,
            "REEL2BITS_VERSION": "{0} ({1})".format(VERSION, GIT_VERSION),
            "app_name": _config.app_name,
            "app_description": _config.app_description,
        }
        g.cfg = cfg

    @app.errorhandler(InvalidUsage)
    def handle_invalid_usage(error):
        response = jsonify(error.to_dict())
        response.status_code = error.status_code
        return response

    sounds = UploadSet("sounds", AUDIO)
    configure_uploads(app, sounds)
    patch_request_class(app, 500 * 1024 * 1024)  # 500m limit

    if register_blueprints:
        from controllers.main import bp_main

        app.register_blueprint(bp_main)

        from controllers.users import bp_users

        app.register_blueprint(bp_users)

        from controllers.admin import bp_admin

        app.register_blueprint(bp_admin)

        from controllers.sound import bp_sound

        app.register_blueprint(bp_sound)

        from controllers.albums import bp_albums

        app.register_blueprint(bp_albums)

        from controllers.search import bp_search

        app.register_blueprint(bp_search)

        from controllers.api.v1.well_known import bp_wellknown

        app.register_blueprint(bp_wellknown)

        from controllers.api.v1.nodeinfo import bp_nodeinfo

        app.register_blueprint(bp_nodeinfo)

        from controllers.api.v1.activitypub import bp_ap

        app.register_blueprint(bp_ap)

    @app.route("/uploads/<string:thing>/<path:stuff>", methods=["GET"])
    def get_uploads_stuff(thing, stuff):
        if app.testing:
            directory = safe_join(app.config["UPLOADS_DEFAULT_DEST"], thing)
            app.logger.debug(f"serving {stuff} from {directory}")
            return send_from_directory(directory, stuff, as_attachment=True)
        else:
            app.logger.debug(f"X-Accel-Redirect serving {stuff}")
            resp = Response("")
            resp.headers[
                "Content-Disposition"] = f"attachment; filename={stuff}"
            resp.headers[
                "X-Accel-Redirect"] = f"/_protected/media/{thing}/{stuff}"
            resp.headers[
                "Content-Type"] = ""  # empty it so Nginx will guess it correctly
            return resp

    @app.errorhandler(404)
    def page_not_found(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 404,
            "message": gettext("Page not found"),
            "e": msg,
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 404

    @app.errorhandler(403)
    def err_forbidden(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 403,
            "message": gettext("Access forbidden"),
            "e": msg,
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 403

    @app.errorhandler(410)
    def err_gone(msg):
        pcfg = {
            "title": gettext("Whoops, something failed."),
            "error": 410,
            "message": gettext("Gone"),
            "e": msg
        }
        return render_template("error_page.jinja2", pcfg=pcfg), 410

    if not app.debug:

        @app.errorhandler(500)
        def err_failed(msg):
            pcfg = {
                "title": gettext("Whoops, something failed."),
                "error": 500,
                "message": gettext("Something is broken"),
                "e": msg,
            }
            return render_template("error_page.jinja2", pcfg=pcfg), 500

    @app.after_request
    def set_x_powered_by(response):
        response.headers["X-Powered-By"] = "reel2bits"
        return response

    # Other commands
    @app.cli.command()
    def routes():
        """Dump all routes of defined app"""
        table = texttable.Texttable()
        table.set_deco(texttable.Texttable().HEADER)
        table.set_cols_dtype(["t", "t", "t"])
        table.set_cols_align(["l", "l", "l"])
        table.set_cols_width([50, 30, 80])

        table.add_rows([["Prefix", "Verb", "URI Pattern"]])

        for rule in sorted(app.url_map.iter_rules(), key=lambda x: str(x)):
            methods = ",".join(rule.methods)
            table.add_row([rule.endpoint, methods, rule])

        print(table.draw())

    @app.cli.command()
    def config():
        """Dump config"""
        pp(app.config)

    @app.cli.command()
    def seed():
        """Seed database with default content"""
        make_db_seed(db)

    @app.cli.command()
    def createuser():
        """Create an user"""
        username = click.prompt("Username", type=str)
        email = click.prompt("Email", type=str)
        password = click.prompt("Password",
                                type=str,
                                hide_input=True,
                                confirmation_prompt=True)
        while True:
            role = click.prompt("Role [admin/user]", type=str)
            if role == "admin" or role == "user":
                break

        if click.confirm("Do you want to continue ?"):
            role = Role.query.filter(Role.name == role).first()
            if not role:
                raise click.UsageError("Roles not present in database")
            u = user_datastore.create_user(name=username,
                                           email=email,
                                           password=encrypt_password(password),
                                           roles=[role])

            actor = create_actor(u)
            actor.user = u
            actor.user_id = u.id
            db.session.add(actor)

            db.session.commit()

            if FSConfirmable.requires_confirmation(u):
                FSConfirmable.send_confirmation_instructions(u)
                print("Look at your emails for validation instructions.")

    return app
Example #20
0
from opac_schema.v1.models import (
    Collection,
    Sponsor,
    Journal,
    Issue,
    Article,
    News,
    Pages,
    PressRelease,
    AuditLogEntry)

login_manager = LoginManager()
dbmongo = MongoEngine()
dbsql = SQLAlchemy()
mail = Mail()
babel = Babel()
sentry = Sentry()
cache = Cache()


from .main import custom_filters  # noqa


logger = logging.getLogger(__name__)


class RegexConverter(BaseConverter):
    def __init__(self, url_map, *items):
        super(RegexConverter, self).__init__(url_map)
        self.regex = items[0]
Example #21
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(logging.INFO)

    # 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
    ##########################################################################
    if not config.DEBUG:
        from flask_htmlmin import HTMLMIN
        HTMLMIN(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 #22
0
def create_app():
    app = Flask(__name__)
    app.config.from_object(youjiao_config)

    # flask_sqlalchemy
    # import ipdb; ipdb.set_trace()
    db.init_app(app)

    # flask_redis
    redis_cli.init_app(app)

    # flask_debug
    if app.config.get('DEBUG'):
        DebugToolbarExtension(app)

    # flask_login
    login_manager.user_loader(load_user)
    login_manager.login_view = 'user_view.login'
    login_manager.init_app(app)

    # flask_jwt
    jwt.init_app(app)

    # flask_principal
    Principal(app)
    identity_loaded.connect_via(app)(_on_identity_loaded)

    # flask_wtf csrf
    csrf = CsrfProtect()
    csrf.init_app(app)
    app.before_request(check_csrf(csrf))

    # flask_babel
    Babel(app)

    # flask_limiter
    limiter.init_app(app)

    # flask_qiniu
    flask_qiniu.init_app(app)

    # flask_admin
    admin.init_app(app)

    # register blueprint
    app.register_blueprint(content_bp)

    app.register_blueprint(user_bp)

    app.register_blueprint(user_api_bp)

    # import ipdb; ipdb.set_trace()
    app.register_blueprint(book_bp)
    app.register_blueprint(book_api_bp)
    app.register_blueprint(user_util_api_bp)
    app.register_blueprint(media_bp)
    app.register_blueprint(online_course_bp)

    # register subscriber
    user_connect(app)

    # register home page
    app.add_url_rule('/', 'index', index)

    with open(os.path.join(os.getcwd(), 'youjiao/static/assets.json.py'),
              'r') as assets:
        app.assets = json.load(assets)

    return app
Example #23
0
def create_app(app_name=None):
    # Configuration settings
    import config
    if not app_name:
        app_name = config.APP_NAME

    # Check if app is created for CLI operations or Web
    cli_mode = False
    if app_name.endswith('-cli'):
        cli_mode = True

    # 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

    if not cli_mode:
        # Ensure the various working directories exist
        from pgadmin.setup import create_app_data_directory
        create_app_data_directory(config)

        # File logging
        from pgadmin.utils.enhanced_log_rotation import \
            EnhancedRotatingFileHandler
        fh = EnhancedRotatingFileHandler(config.LOG_FILE,
                                         config.LOG_ROTATION_SIZE,
                                         config.LOG_ROTATION_AGE,
                                         config.LOG_ROTATION_MAX_LOG_FILES)

        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
            user_id = None
            if current_user.is_authenticated:
                user_id = current_user.id
            else:
                user = user_datastore.find_user(email=config.DESKTOP_USER)
                if user is not None:
                    user_id = user.id
            user_language = Preferences.raw_value('misc', 'user_language',
                                                  'user_language', 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'] = 'sqlite:///{0}?timeout={1}' \
        .format(config.SQLITE_PATH.replace('\\', '/'),
                getattr(config, 'SQLITE_TIMEOUT', 500)
                )

    # Override USER_DOES_NOT_EXIST and INVALID_PASSWORD messages from flask.
    app.config['SECURITY_MSG_USER_DOES_NOT_EXIST'] = \
        app.config['SECURITY_MSG_INVALID_PASSWORD'] = \
        (gettext("Incorrect username or password."), "error")

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

    ##########################################################################
    # Upgrade the schema (if required)
    ##########################################################################
    def backup_db_file():
        """
        Create a backup of the current database file
        and create new database file with default settings.
        """
        backup_file_name = "{0}.{1}".format(
            SQLITE_PATH,
            datetime.now().strftime('%Y%m%d%H%M%S'))
        os.rename(SQLITE_PATH, backup_file_name)
        app.logger.error('Exception in database migration.')
        app.logger.info('Creating new database file.')
        try:
            db_upgrade(app)
            os.environ['CORRUPTED_DB_BACKUP_FILE'] = backup_file_name
            app.logger.info('Database migration completed.')
        except Exception as e:
            app.logger.error('Database migration failed')
            app.logger.error(traceback.format_exc())
            raise RuntimeError('Migration failed')

    def upgrade_db():
        """
        Execute the migrations.
        """
        try:
            db_upgrade(app)
            os.environ['CORRUPTED_DB_BACKUP_FILE'] = ''
        except Exception as e:
            backup_db_file()

        # check all tables are present in the db.
        is_db_error, invalid_tb_names = check_db_tables()
        if is_db_error:
            app.logger.error('Table(s) {0} are missing in the'
                             ' database'.format(invalid_tb_names))
            backup_db_file()

    with app.app_context():
        # Run migration for the first time i.e. create database
        from config import SQLITE_PATH
        from pgadmin.setup import db_upgrade

        # 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:
            # If running in cli mode then don't try to upgrade, just raise
            # the exception
            if not cli_mode:
                upgrade_db()
            else:
                if not os.path.exists(SQLITE_PATH):
                    raise FileNotFoundError('SQLite database file "' +
                                            SQLITE_PATH + '" does not exists.')
                raise RuntimeError(
                    'The configuration database file is not valid.')
        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:
                upgrade_db()
            else:
                # check all tables are present in the db.
                is_db_error, invalid_tb_names = check_db_tables()
                if is_db_error:
                    app.logger.error('Table(s) {0} are missing in the'
                                     ' database'.format(invalid_tb_names))
                    backup_db_file()

            # 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)

    # Don't bother paths when running in cli mode
    if not cli_mode:
        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'],
            # Disable deliverable check for email addresss
            'SECURITY_EMAIL_VALIDATOR_ARGS':
            config.SECURITY_EMAIL_VALIDATOR_ARGS
        }))

    if 'SCRIPT_NAME' in os.environ and os.environ["SCRIPT_NAME"]:
        app.config.update(dict({'APPLICATION_ROOT':
                                os.environ["SCRIPT_NAME"]}))

    app.config.update(
        dict({
            'INTERNAL': INTERNAL,
            'LDAP': LDAP,
            'KERBEROS': KERBEROS,
            'OAUTH2': OAUTH2,
            'WEBSERVER': WEBSERVER
        }))

    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)

    if not cli_mode:
        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)
    authenticate.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('misc')
            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:
                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 range(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 {0} installation with the data "
                                "directory at {1}").format(
                                    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:
                        pass
        else:
            # We use the postgres-winreg.ini file on non-Windows
            from configparser import ConfigParser

            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')
                    svr_comment = gettext(
                        "Auto-detected {0} installation "
                        "with the data directory at {1}").format(
                            description, data_directory)
                    add_server(user_id, servergroup_id, svr_name,
                               svr_superuser, svr_port, svr_discovery_id,
                               svr_comment)

        except Exception:
            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 and '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

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

        # remove key
        current_app.keyManager.reset()

        _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)

    @app.before_request
    def limit_host_addr():
        """
        This function validate the hosts from ALLOWED_HOSTS before allowing
        HTTP request to avoid Host Header Injection attack
        :return: None/JSON response with 403 HTTP status code
        """
        client_host = str(request.host).split(':')[0]
        valid = True
        allowed_hosts = config.ALLOWED_HOSTS

        if len(allowed_hosts) != 0:
            regex = re.compile(
                r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:/\d{1,2}|)')
            # Create separate list for ip addresses and host names
            ip_set = list(filter(lambda ip: regex.match(ip), allowed_hosts))
            host_set = list(
                filter(lambda ip: not regex.match(ip), allowed_hosts))
            is_ip = regex.match(client_host)
            if is_ip:
                ip_address = []
                for ip in ip_set:
                    ip_address.extend(list(ipaddress.ip_network(ip)))
                valid = ip_address.__contains__(
                    ipaddress.ip_address(client_host))
            else:
                valid = host_set.__contains__(client_host)

        if not valid:
            return make_json_response(status=403,
                                      success=0,
                                      errormsg=_("403 FORBIDDEN"))

    ##########################################################################
    # 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_INT_KEY != '' and (
            ('key' not in request.args
             or request.args['key'] != app.PGADMIN_INT_KEY) and
                request.cookies.get('PGADMIN_INT_KEY') != app.PGADMIN_INT_KEY
                and request.endpoint != 'help.static'):
            abort(401)

        if not config.SERVER_MODE and not current_user.is_authenticated:
            user = user_datastore.find_user(email=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)
        elif config.SERVER_MODE and \
                not current_user.is_authenticated and \
                request.endpoint in ('redirects.index', 'security.login'):
            if app.PGADMIN_EXTERNAL_AUTH_SOURCE in [KERBEROS, WEBSERVER]:
                return authenticate.login()
        # 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 and \
            app.PGADMIN_EXTERNAL_AUTH_SOURCE not in [
                KERBEROS, OAUTH2, WEBSERVER] and \
                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_INT_KEY',
                                value=request.args['key'],
                                path=config.COOKIE_DEFAULT_PATH,
                                secure=config.SESSION_COOKIE_SECURE,
                                httponly=config.SESSION_COOKIE_HTTPONLY,
                                samesite=config.SESSION_COOKIE_SAMESITE,
                                **domain)

        SecurityHeaders.set_response_headers(response)
        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)

    from pgadmin.misc.themes import themes
    themes(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!
    ##########################################################################
    socketio.init_app(app)
    return app
Example #24
0
import sys

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_babelex import Babel

app = Flask(__name__)
babel = Babel(app)  # 国际化

app.config.from_object('config')
db = SQLAlchemy(app)

from app import routers
def create_app():
    """ Flask application factory """

    # Create Flask app load app.config
    app = Flask(__name__)
    app.config.from_object(__name__ + '.ConfigClass')

    # Initialize Flask-BabelEx
    babel = Babel(app)
    # Initialize Flask-SQLAlchemy
    @babel.localeselector
    def get_locale():
        translations = [
            str(translation) for translation in babel.list_translations()
        ]

    #   return request.accept_languages.best_match(translations)
    # @babel.localeselector
    #def get_locale():
    #   if request.args.get('lang'):
    #       session['lang'] = request.args.get('lang')
    #       return session.get('lang', 'tr')

    db = SQLAlchemy(app)

    # Define the User data-model.
    # NB: Make sure to add flask_user UserMixin !!!
    class User(db.Model, UserMixin):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        active = db.Column('is_active',
                           db.Boolean(),
                           nullable=False,
                           server_default='1')

        # User authentication information. The collation='NOCASE' is required
        # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'.
        email = db.Column(db.String(255, collation='NOCASE'),
                          nullable=False,
                          unique=True)
        email_confirmed_at = db.Column(db.DateTime())
        password = db.Column(db.String(255), nullable=False, server_default='')

        # User information
        first_name = db.Column(db.String(100, collation='NOCASE'),
                               nullable=False,
                               server_default='')
        last_name = db.Column(db.String(100, collation='NOCASE'),
                              nullable=False,
                              server_default='')

        # Define the relationship to Role via UserRoles
        roles = db.relationship('Role', secondary='user_roles')

    # Define the Role data-model
    class Role(db.Model):
        __tablename__ = 'roles'
        id = db.Column(db.Integer(), primary_key=True)
        name = db.Column(db.String(50), unique=True)

    # Define the UserRoles association table
    class UserRoles(db.Model):
        __tablename__ = 'user_roles'
        id = db.Column(db.Integer(), primary_key=True)
        user_id = db.Column(db.Integer(),
                            db.ForeignKey('users.id', ondelete='CASCADE'))
        role_id = db.Column(db.Integer(),
                            db.ForeignKey('roles.id', ondelete='CASCADE'))

    # Setup Flask-User and specify the User data-model
    user_manager = UserManager(app, db, User)

    # Create all database tables
    db.create_all()

    # Create '*****@*****.**' user with no roles
    if not User.query.filter(User.email == '*****@*****.**').first():
        user = User(
            email='*****@*****.**',
            email_confirmed_at=datetime.datetime.utcnow(),
            password=user_manager.hash_password('Password1'),
        )
        db.session.add(user)
        db.session.commit()

    # Create '*****@*****.**' user with 'Admin' and 'Agent' roles
    if not User.query.filter(User.email == '*****@*****.**').first():
        user = User(
            email='*****@*****.**',
            email_confirmed_at=datetime.datetime.utcnow(),
            password=user_manager.hash_password('Password1'),
        )
        user.roles.append(Role(name='Admin'))
        user.roles.append(Role(name='Agent'))
        db.session.add(user)
        db.session.commit()
Example #26
0
def base_app(request):
    """Flask application fixture without OAuthClient initialized."""
    # allow HTTP for keycloak tests, and create the KEYCLOAK_REMOTE_APP
    os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
    base_url, realm = "http://localhost:8080", "test"
    helper = KeycloakSettingsHelper(title="Keycloak",
                                    description="",
                                    base_url=base_url,
                                    realm=realm)
    KEYCLOAK_REMOTE_APP = helper.remote_app

    instance_path = tempfile.mkdtemp()
    base_app = Flask('testapp')
    base_app.config.update(
        ACCOUNTS_LOCAL_LOGIN_ENABLED=True,
        TESTING=True,
        WTF_CSRF_ENABLED=False,
        LOGIN_DISABLED=False,
        CACHE_TYPE='simple',
        OAUTHCLIENT_SIGNUP_FORM=_create_registrationform,
        OAUTHCLIENT_REMOTE_APPS=dict(
            cern=CERN_REMOTE_APP,
            cern_openid=CERN_OPENID_REMOTE_APP,
            orcid=ORCID_REMOTE_APP,
            github=GITHUB_REMOTE_APP,
            globus=GLOBUS_REMOTE_APP,
            keycloak=KEYCLOAK_REMOTE_APP,
        ),
        OAUTHCLIENT_REST_REMOTE_APPS=dict(
            cern=CERN_REMOTE_REST_APP,
            cern_openid=CERN_OPENID_REMOTE_REST_APP,
            orcid=ORCID_REMOTE_REST_APP,
            github=GITHUB_REMOTE_REST_APP,
            globus=GLOBUS_REMOTE_REST_APP,
        ),
        OAUTHCLIENT_STATE_EXPIRES=300,
        GITHUB_APP_CREDENTIALS=dict(
            consumer_key='github_key_changeme',
            consumer_secret='github_secret_changeme',
        ),
        ORCID_APP_CREDENTIALS=dict(
            consumer_key='orcid_key_changeme',
            consumer_secret='orcid_secret_changeme',
        ),
        CERN_APP_CREDENTIALS=dict(
            consumer_key='cern_key_changeme',
            consumer_secret='cern_secret_changeme',
        ),
        CERN_APP_OPENID_CREDENTIALS=dict(
            consumer_key='cern_key_changeme',
            consumer_secret='cern_secret_changeme',
        ),
        GLOBUS_APP_CREDENTIALS=dict(
            consumer_key='globus_key_changeme',
            consumer_secret='globus_secret_changeme',
        ),
        TEST_APP_CREDENTIALS=dict(
            consumer_key='test_key_changeme',
            consumer_secret='test_secret_changeme',
        ),
        OAUTHCLIENT_KEYCLOAK_USER_INFO_URL=helper.user_info_url,
        OAUTHCLIENT_KEYCLOAK_REALM_URL=helper.realm_url,
        OAUTHCLIENT_KEYCLOAK_VERIFY_AUD=True,
        OAUTHCLIENT_KEYCLOAK_VERIFY_EXP=False,
        OAUTHCLIENT_KEYCLOAK_AUD="invenio",
        KEYCLOAK_APP_CREDENTIALS=dict(
            consumer_key="keycloak_key_changeme",
            consumer_secret="keycloak_secret_changeme",
        ),
        # use local memory mailbox
        EMAIL_BACKEND='flask_email.backends.locmem.Mail',
        SQLALCHEMY_DATABASE_URI=os.getenv('SQLALCHEMY_DATABASE_URI',
                                          'sqlite://'),
        # Alembic runs all migrations in a single transaction, and in
        # oauthclient the useridentity table can be in state where it's created
        # and then deleted in the same transaction. On PostgreSQL which
        # supports transactional DDL therefore fails if we don't run each
        # migration in its own migration.
        ALEMBIC_CONTEXT={
            'transaction_per_migration': True,
        },
        SERVER_NAME='localhost',
        DEBUG=False,
        SECRET_KEY='TEST',
        SECURITY_DEPRECATED_PASSWORD_SCHEMES=[],
        SQLALCHEMY_TRACK_MODIFICATIONS=False,
        SECURITY_PASSWORD_HASH='plaintext',
        SECURITY_PASSWORD_SCHEMES=['plaintext'],
        APP_ALLOWED_HOSTS=['localhost'],
        APP_THEME=['semantic-ui'],
        THEME_ICONS={'semantic-ui': dict(link='linkify icon')})
    FlaskMenu(base_app)
    Babel(base_app)
    Mail(base_app)
    InvenioDB(base_app)
    InvenioAccounts(base_app)

    with base_app.app_context():
        if str(db.engine.url) != 'sqlite://' and \
           not database_exists(str(db.engine.url)):
            create_database(str(db.engine.url))
        db.create_all()

    def teardown():
        with base_app.app_context():
            db.session.close()
            if str(db.engine.url) != 'sqlite://':
                drop_database(str(db.engine.url))
            shutil.rmtree(instance_path)
            db.engine.dispose()

    request.addfinalizer(teardown)

    base_app.test_request_context().push()

    return base_app
def create_app(test_config=None):  # For automated tests
    # Setup Flask and read config from ConfigClass defined above
    app = Flask(__name__)
    app.config.from_object(__name__ + '.ConfigClass')

    # Load local_settings.py if file exists         # For automated tests
    try:
        app.config.from_object('local_settings')
    except ImportError:
        pass

    # Load optional test_config                     # For automated tests
    if test_config:
        app.config.update(test_config)

    # Initialize Flask extensions
    db = SQLAlchemy(app)  # Initialize Flask-SQLAlchemy
    babel = Babel(app)  # Initialize Flask-BabelEx

    @babel.localeselector
    def get_locale():
        translations = [
            str(translation) for translation in babel.list_translations()
        ]
        language = request.accept_languages.best_match(translations)
        return language

    # Define the User data-model. Make sure to add flask_user UserMixin !!!
    class User(db.Model, UserMixin):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)

        # User authentication information. The collation='NOCASE' is required
        # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'.
        username = db.Column(db.String(50), nullable=True, unique=True)
        password = db.Column(db.String(255), nullable=False, server_default='')

        # User email information. The collation='NOCASE' is required
        # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'.
        email = db.Column(db.String(255, collation='NOCASE'),
                          nullable=False,
                          unique=True)
        email_confirmed_at = db.Column(db.DateTime(), nullable=True)

        # User information
        is_enabled = db.Column(db.Boolean(),
                               nullable=False,
                               server_default='0')
        first_name = db.Column(db.String(100, collation='NOCASE'),
                               nullable=False,
                               server_default='')
        last_name = db.Column(db.String(100, collation='NOCASE'),
                              nullable=False,
                              server_default='')

    class UserInvitation(db.Model):
        __tablename__ = 'user_invitations'
        id = db.Column(db.Integer, primary_key=True)
        # UserInvitation email information. The collation='NOCASE' is required
        # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'.
        email = db.Column(db.String(255, collation='NOCASE'), nullable=False)
        # save the user of the invitee
        invited_by_user_id = db.Column(db.Integer, db.ForeignKey('users.id'))

    # Create all database tables
    db.create_all()

    # Setup Flask-User
    db_adapter = SQLAlchemyAdapter(
        db, User,
        UserInvitationClass=UserInvitation)  # Select database adapter
    user_manager = UserManager(db_adapter,
                               app)  # Init Flask-User and bind to app

    @user_registered.connect_via(app)
    def after_registered_hook(sender, user, user_invitation):
        sender.logger.info("USER REGISTERED")

    @user_sent_invitation.connect_via(app)
    def after_invitation_hook(sender, **extra):
        sender.logger.info("USER SENT INVITATION")

    # The Home page is accessible to anyone
    @app.route('/')
    def home_page():
        return render_template_string("""
            {% extends "flask_user_layout.html" %}
            {% block content %}
                <h2>{%trans%}Home Pages{%endtrans%}</h2>
                {% if call_or_get(current_user.is_authenticated) %}
                <p> <a href="{{ url_for('user_profile_page') }}">
                    {%trans%}Profile Page{%endtrans%}</a></p>
                <p> <a href="{{ url_for('user.logout') }}">
                    {%trans%}Sign out{%endtrans%}</a></p>
                {% else %}
                <p> <a href="{{ url_for('user.login') }}">
                    {%trans%}Sign in or Register{%endtrans%}</a></p>
                {% endif %}
            {% endblock %}
            """)
        user_manager = current_app.user_manager
        if user_manager.call_or_get(current_user.is_authenticated):
            return redirect(url_for('user_profile_page'))
        else:
            return redirect(url_for('user.login'))

    # The Profile page requires a logged-in user
    @app.route('/user/profiles')
    @login_required  # Use of @login_required decorator
    @confirmed_email_required
    def user_profile_page():
        return render_template_string("""
            {% extends "flask_user_layout.html" %}
            {% block content %}
                <h2>{%trans%}Profile Page{%endtrans%}</h2>
                <p> {%trans%}Hello{%endtrans%}
                    {{ current_user.username or current_user.email }},</p>
                <p> <a href="{{ url_for('home_page') }}">
                    {%trans%}Home Page{%endtrans%}</a></p>
                <p> <a href="{{ url_for('user.change_username') }}">
                    {%trans%}Change username{%endtrans%}</a></p>
                <p> <a href="{{ url_for('user.change_password') }}">
                    {%trans%}Change password{%endtrans%}</a></p>
                <p> <a href="{{ url_for('user.invite_user') }}">
                    {%trans%}Invite User{%endtrans%}</a></p>
                <p> <a href="{{ url_for('user.logout') }}">
                    {%trans%}Sign out{%endtrans%}</a></p>
            {% endblock %}
            """)

    return app
 def factory(**config):
     app = Flask('testapp', instance_path=instance_path)
     app.config.update(**config)
     Babel(app)
     invenioconfigtugraz(app)
     return app
Example #29
0
   $ export FLASK_APP=app.py FLASK_DEBUG=1
   $ flask run

and open the example application in your browser:

.. code-block:: console

    $ open http://127.0.0.1:5000/

To reset the example application run:

.. code-block:: console

    $ ./app-teardown.sh

SPHINX-END
"""

from __future__ import absolute_import, print_function

from flask import Flask
from flask_babelex import Babel

from reroils_data import REROILSDATA

# Create Flask application
app = Flask(__name__)
Babel(app)
REROILSDATA(app)
Example #30
0
def app(request):
    app = Flask(__name__)
    app.response_class = Response
    app.debug = True
    app.config['SECRET_KEY'] = 'secret'
    app.config['TESTING'] = True
    app.config['LOGIN_DISABLED'] = False
    app.config['WTF_CSRF_ENABLED'] = False
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    app.config['SECURITY_PASSWORD_SALT'] = 'salty'

    for opt in [
            'changeable', 'recoverable', 'registerable', 'trackable',
            'passwordless', 'confirmable'
    ]:
        app.config['SECURITY_' + opt.upper()] = opt in request.keywords

    if 'settings' in request.keywords:
        for key, value in request.keywords['settings'].kwargs.items():
            app.config['SECURITY_' + key.upper()] = value

    mail = Mail(app)
    if 'babel' not in request.keywords or \
            request.keywords['babel'].args[0]:
        babel = Babel(app)
        app.babel = babel
    app.json_encoder = JSONEncoder
    app.mail = mail

    @app.route('/')
    def index():
        return render_template('index.html', content='Home Page')

    @app.route('/profile')
    @login_required
    def profile():
        return render_template('index.html', content='Profile Page')

    @app.route('/post_login')
    @login_required
    def post_login():
        return render_template('index.html', content='Post Login')

    @app.route('/http')
    @http_auth_required
    def http():
        return 'HTTP Authentication'

    @app.route('/http_custom_realm')
    @http_auth_required('My Realm')
    def http_custom_realm():
        return render_template('index.html', content='HTTP Authentication')

    @app.route('/token', methods=['GET', 'POST'])
    @auth_token_required
    def token():
        return render_template('index.html', content='Token Authentication')

    @app.route('/multi_auth')
    @auth_required('session', 'token', 'basic')
    def multi_auth():
        return render_template('index.html',
                               content='Session, Token, Basic auth')

    @app.route('/post_logout')
    def post_logout():
        return render_template('index.html', content='Post Logout')

    @app.route('/post_register')
    def post_register():
        return render_template('index.html', content='Post Register')

    @app.route('/admin')
    @roles_required('admin')
    def admin():
        return render_template('index.html', content='Admin Page')

    @app.route('/admin_and_editor')
    @roles_required('admin', 'editor')
    def admin_and_editor():
        return render_template('index.html', content='Admin and Editor Page')

    @app.route('/admin_or_editor')
    @roles_accepted('admin', 'editor')
    def admin_or_editor():
        return render_template('index.html', content='Admin or Editor Page')

    @app.route('/unauthorized')
    def unauthorized():
        return render_template('unauthorized.html')

    @app.route('/page1')
    def page_1():
        return 'Page 1'

    return app
Example #31
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
    ##########################################################################

    # 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(logging.INFO)

    # 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

    # 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 not os.path.exists(SQLITE_PATH):
            db_upgrade(app)
        else:
            version = Version.query.filter_by(name='ConfigDB').first()
            schema_version = version.value

            # 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:
                version = Version.query.filter_by(name='ConfigDB').first()
                version.value = CURRENT_SCHEMA_VERSION
                db.session.commit()

    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
    }))

    security.init_app(app, user_datastore)

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

    app.session_interface = create_session_interface(app)

    # Make the Session more secure against XSS & CSRF when running in web mode
    if config.SERVER_MODE:
        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')
                    svr_port = registry.getint(section, 'Port')
                    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

    ##########################################################################
    # Load plugin modules
    ##########################################################################
    for module in app.find_submodules('pgadmin'):
        app.logger.info('Registering blueprint module: %s' % module)
        app.register_blueprint(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)

    @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)

        return response

    ##########################################################################
    # Minify output
    ##########################################################################
    # HTMLMIN doesn't work with Python 2.6.
    if not config.DEBUG and sys.version_info >= (2, 7):
        from flask_htmlmin import HTMLMIN
        HTMLMIN(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
        }

    ##########################################################################
    # All done!
    ##########################################################################

    return app
Example #32
0
def base_app(request):
    """Flask application fixture without OAuthClient initialized."""
    instance_path = tempfile.mkdtemp()
    base_app = Flask('testapp')
    base_app.config.update(
        TESTING=True,
        WTF_CSRF_ENABLED=False,
        LOGIN_DISABLED=False,
        CACHE_TYPE='simple',
        OAUTHCLIENT_REMOTE_APPS=dict(
            cern=CERN_REMOTE_APP,
            orcid=ORCID_REMOTE_APP,
            github=GITHUB_REMOTE_APP,
        ),
        GITHUB_APP_CREDENTIALS=dict(
            consumer_key='github_key_changeme',
            consumer_secret='github_secret_changeme',
        ),
        ORCID_APP_CREDENTIALS=dict(
            consumer_key='orcid_key_changeme',
            consumer_secret='orcid_secret_changeme',
        ),
        CERN_APP_CREDENTIALS=dict(
            consumer_key='cern_key_changeme',
            consumer_secret='cern_secret_changeme',
        ),
        # use local memory mailbox
        EMAIL_BACKEND='flask_email.backends.locmem.Mail',
        SQLALCHEMY_DATABASE_URI=os.getenv('SQLALCHEMY_DATABASE_URI',
                                          'sqlite://'),
        SERVER_NAME='localhost',
        DEBUG=False,
        SECRET_KEY='TEST',
        SECURITY_DEPRECATED_PASSWORD_SCHEMES=[],
        SECURITY_PASSWORD_HASH='plaintext',
        SECURITY_PASSWORD_SCHEMES=['plaintext'],
    )
    FlaskMenu(base_app)
    Babel(base_app)
    Mail(base_app)
    InvenioDB(base_app)
    InvenioAccounts(base_app)

    with base_app.app_context():
        if str(db.engine.url) != 'sqlite://' and \
           not database_exists(str(db.engine.url)):
            create_database(str(db.engine.url))
        db.create_all()

    def teardown():
        with base_app.app_context():
            db.session.close()
            if str(db.engine.url) != 'sqlite://':
                drop_database(str(db.engine.url))
            shutil.rmtree(instance_path)

    request.addfinalizer(teardown)

    base_app.test_request_context().push()

    return base_app
Example #33
0
# Initialize Flask and set some config values
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'
#debug_toolbar=DebugToolbarExtension()
#debug_toolbar.init_app(app)
#app.config['DEBUG_TB_INTERCEPT_REDIRECTS']=False
app.config[
    'SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:@127.0.0.1:3306/zsky'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_POOL_SIZE'] = 5000
db = SQLAlchemy(app)
manager = Manager(app)
migrate = Migrate(app, db)
moment = Moment(app)
babel = Babel(app)
app.config['BABEL_DEFAULT_LOCALE'] = 'zh_CN'
loginmanager = LoginManager()
loginmanager.init_app(app)
loginmanager.session_protection = 'strong'
loginmanager.login_view = 'login'
loginmanager.login_message = "请先登录!"
cache = Cache(app,
              config={
                  'CACHE_TYPE': 'redis',
                  'CACHE_REDIS_HOST': '127.0.0.1',
                  'CACHE_REDIS_PORT': 6379,
                  'CACHE_REDIS_DB': '',
                  'CACHE_REDIS_PASSWORD': ''
              })
cache.init_app(app)
Example #34
0
class InvenioI18N(object):
    """Invenio I18N extension."""
    def __init__(self,
                 app=None,
                 date_formats=None,
                 localeselector=None,
                 timezoneselector=None,
                 entry_point_group='invenio_i18n.translations'):
        """Initialize extension.

        :param app: Flask application.
        :param data_formats: Override default date/time formatting.
        :param localeselector: Callback function used for locale selection.
            (Default: :func:`invenio_i18n.selectors.get_locale()`)
        :param timezoneselector: Callback function used for timezone selection.
            (Default: ``BABEL_DEFAULT_TIMEZONE``)
        :param entry_point_group: Entrypoint used to load translations from.
            Set to ``None`` to not load translations from entry points.
        """
        self.domain = MultidirDomain()
        self.babel = Babel(
            date_formats=date_formats,
            configure_jinja=True,
            default_domain=self.domain,
        )
        self.localeselector = localeselector
        self.timezoneselector = timezoneselector
        self.entry_point_group = entry_point_group
        self._locales_cache = None
        self._languages_cache = None

        if app:
            self.init_app(app)

    def init_app(self, app):
        """Flask application initialization.

        The initialization will:

         * Set default values for the configuration variables.
         * Load translations from paths specified in
           ``I18N_TRANSLATIONS_PATHS``.
         * Load translations from ``app.root_path>/translations`` if it exists.
         * Load translations from a specified entry point.
         * Add ``toutc`` and ``tousertimezone`` template filters.
         * Install a custom JSON encoder on app.
        """
        self.init_config(app)

        # Initialize Flask-BabelEx
        self.babel.init_app(app)
        self.babel.localeselector(self.localeselector or get_locale)
        self.babel.timezoneselector(self.timezoneselector or get_timezone)

        # 1. Paths listed in I18N_TRANSLATIONS_PATHS
        for p in app.config.get('I18N_TRANSLATIONS_PATHS', []):
            self.domain.add_path(p)
        # 2. <app.root_path>/translations
        app_translations = os.path.join(app.root_path, 'translations')
        if os.path.exists(app_translations):
            self.domain.add_path(app_translations)
        # 3. Entrypoints
        if self.entry_point_group:
            self.domain.add_entrypoint(self.entry_point_group)

        # Register default routes if URL is set.
        register_default_routes = app.config['I18N_SET_LANGUAGE_URL'] \
            and app.config['I18N_LANGUAGES']
        app.register_blueprint(
            create_blueprint(register_default_routes=register_default_routes),
            url_prefix=app.config['I18N_SET_LANGUAGE_URL'])

        # Register Jinja2 template filters for date formatting (Flask-Babel
        # already installs other filters).
        app.add_template_filter(filter_to_utc, name='toutc')
        app.add_template_filter(filter_to_user_timezone, name='tousertimezone')
        app.add_template_filter(filter_language_name, name='language_name')
        app.add_template_filter(filter_language_name_local,
                                name='language_name_local')
        app.add_template_global(current_i18n, name='current_i18n')

        # Lazy string aware JSON encoder.
        app.json_encoder = get_lazystring_encoder(app)

        app.extensions['invenio-i18n'] = self

    def init_config(self, app):
        """Initialize configuration."""
        for k in dir(config):
            if k.startswith('I18N_'):
                app.config.setdefault(k, getattr(config, k))

    def iter_languages(self):
        """Iterate over list of languages."""
        default_lang = self.babel.default_locale.language
        default_title = self.babel.default_locale.get_display_name(
            default_lang)

        yield (default_lang, default_title)

        for l, title in current_app.config.get('I18N_LANGUAGES', []):
            yield l, title

    def get_languages(self):
        """Get list of languages."""
        if self._languages_cache is None:
            self._languages_cache = list(self.iter_languages())
        return self._languages_cache

    def get_locales(self):
        """Get a list of supported locales.

        Computes the list using ``I18N_LANGUAGES`` configuration variable.
        """
        if self._locales_cache is None:
            langs = [self.babel.default_locale]
            for l, dummy_title in current_app.config.get('I18N_LANGUAGES', []):
                langs.append(self.babel.load_locale(l))
            self._locales_cache = langs
        return self._locales_cache

    @property
    def locale(self):
        """Get current locale."""
        return get_current_locale()

    @property
    def language(self):
        """Get current language code."""
        return get_current_locale().language

    @property
    def timezone(self):
        """Get current timezone."""
        return get_current_timezone()
Example #35
0
app = Flask(__name__, template_folder='app/templates', static_folder='app/static')

import app.config as config

app.config.from_object(config)

app.jinja_env.filters['substring'] = jinja2_filter_substring
app.jinja_env.filters['startswith'] = jinja2_filter_startswith
app.jinja_env.filters['datedelta'] = jinja2_filter_date_with_delta
app.jinja_env.filters['heatmap'] = jinja2_filter_photo_collection_heat_map
app.jinja_env.filters['averagerating'] = jinja2_filter_get_average_rating
app.jinja_env.filters['numberoforder'] = jinja2_filter_get_number_of_order

from flask_babelex import Babel

babel = Babel(default_locale='zh_Hans_CN')
babel.init_app(app)

from flask.ext.sqlalchemy import SQLAlchemy

db = SQLAlchemy(app)
from app.app_provider import AppInfo

AppInfo.set_app(app)
AppInfo.set_db(db)

# 初始化云端的图片存储服务
image_store = ImageStore(app)
# 初始化Gallery存储的服务,用于存储所有的用户上传的头像
AppInfo.set_galleries_store_service(image_store)
# 初始化Image存储的服务,用于存储所有摄影师上传的作品图像
Example #36
0
def create_app():
    """ Flask application factory """

    # Create Flask app load app.config
    app = Flask(__name__)
    app.config.from_object(__name__ + '.ConfigClass')

    # Initialize Flask-BabelEx
    babel = Babel(app)

    # Initialize Flask-SQLAlchemy
    db = SQLAlchemy(app)

    # Define the User data-model.
    # NB: Make sure to add flask_user UserMixin !!!
    class User(db.Model, UserMixin):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        active = db.Column('is_active',
                           db.Boolean(),
                           nullable=False,
                           server_default='1')

        # User authentication information. The collation='NOCASE' is required
        # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'.
        email = db.Column(db.String(255, collation='NOCASE'),
                          nullable=False,
                          unique=True)
        email_confirmed_at = db.Column(db.DateTime())
        password = db.Column(db.String(255), nullable=False, server_default='')

        # User information
        first_name = db.Column(db.String(100, collation='NOCASE'),
                               nullable=False,
                               server_default='')
        last_name = db.Column(db.String(100, collation='NOCASE'),
                              nullable=False,
                              server_default='')

        # Define the relationship to Role via UserRoles
        roles = db.relationship('Role', secondary='user_roles')

    # Define the Role data-model
    class Role(db.Model):
        __tablename__ = 'roles'
        id = db.Column(db.Integer(), primary_key=True)
        name = db.Column(db.String(50), unique=True)

    # Define the UserRoles association table
    class UserRoles(db.Model):
        __tablename__ = 'user_roles'
        id = db.Column(db.Integer(), primary_key=True)
        user_id = db.Column(db.Integer(),
                            db.ForeignKey('users.id', ondelete='CASCADE'))
        role_id = db.Column(db.Integer(),
                            db.ForeignKey('roles.id', ondelete='CASCADE'))

    # Setup Flask-User and specify the User data-model
    user_manager = UserManager(app, db, User)

    # Create all database tables
    db.create_all()

    # Create '*****@*****.**' user with no roles
    if not User.query.filter(User.email == '*****@*****.**').first():
        user = User(
            email='*****@*****.**',
            email_confirmed_at=datetime.datetime.utcnow(),
            password=user_manager.hash_password('Password1'),
        )
        db.session.add(user)
        db.session.commit()

    # Create '*****@*****.**' user with 'Admin' and 'Agent' roles
    if not User.query.filter(User.email == '*****@*****.**').first():
        user = User(
            email='*****@*****.**',
            email_confirmed_at=datetime.datetime.utcnow(),
            password=user_manager.hash_password('Password1'),
        )
        user.roles.append(Role(name='Admin'))
        user.roles.append(Role(name='Agent'))
        db.session.add(user)
        db.session.commit()

    # The Home page is accessible to anyone
    @app.route('/')
    def home_page():
        return render_template_string("""
                {% extends "flask_user_layout.html" %}
                {% block content %}
                    <h2>{%trans%}Home page{%endtrans%}</h2>
                    <p><a href={{ url_for('user.register') }}>{%trans%}Register{%endtrans%}</a></p>
                    <p><a href={{ url_for('user.login') }}>{%trans%}Sign in{%endtrans%}</a></p>
                    <p><a href={{ url_for('home_page') }}>{%trans%}Home Page{%endtrans%}</a> (accessible to anyone)</p>
                    <p><a href={{ url_for('member_page') }}>{%trans%}Member Page{%endtrans%}</a> (login_required: [email protected] / Password1)</p>
                    <p><a href={{ url_for('admin_page') }}>{%trans%}Admin Page{%endtrans%}</a> (role_required: [email protected] / Password1')</p>
                    <p><a href={{ url_for('user.logout') }}>{%trans%}Sign out{%endtrans%}</a></p>
                {% endblock %}
                """)

    # The Members page is only accessible to authenticated users
    @app.route('/members')
    @login_required  # Use of @login_required decorator
    def member_page():
        return render_template_string("""
                {% extends "flask_user_layout.html" %}
                {% block content %}
                    <h2>{%trans%}Members page{%endtrans%}</h2>
                    <p><a href={{ url_for('user.register') }}>{%trans%}Register{%endtrans%}</a></p>
                    <p><a href={{ url_for('user.login') }}>{%trans%}Sign in{%endtrans%}</a></p>
                    <p><a href={{ url_for('home_page') }}>{%trans%}Home Page{%endtrans%}</a> (accessible to anyone)</p>
                    <p><a href={{ url_for('member_page') }}>{%trans%}Member Page{%endtrans%}</a> (login_required: [email protected] / Password1)</p>
                    <p><a href={{ url_for('admin_page') }}>{%trans%}Admin Page{%endtrans%}</a> (role_required: [email protected] / Password1')</p>
                    <p><a href={{ url_for('user.logout') }}>{%trans%}Sign out{%endtrans%}</a></p>
                {% endblock %}
                """)

    # The Admin page requires an 'Admin' role.
    @app.route('/admin')
    @roles_required('Admin')  # Use of @roles_required decorator
    def admin_page():
        return render_template_string("""
                {% extends "flask_user_layout.html" %}
                {% block content %}
                    <h2>{%trans%}Admin Page{%endtrans%}</h2>
                    <p><a href={{ url_for('user.register') }}>{%trans%}Register{%endtrans%}</a></p>
                    <p><a href={{ url_for('user.login') }}>{%trans%}Sign in{%endtrans%}</a></p>
                    <p><a href={{ url_for('home_page') }}>{%trans%}Home Page{%endtrans%}</a> (accessible to anyone)</p>
                    <p><a href={{ url_for('member_page') }}>{%trans%}Member Page{%endtrans%}</a> (login_required: [email protected] / Password1)</p>
                    <p><a href={{ url_for('admin_page') }}>{%trans%}Admin Page{%endtrans%}</a> (role_required: [email protected] / Password1')</p>
                    <p><a href={{ url_for('user.logout') }}>{%trans%}Sign out{%endtrans%}</a></p>
                {% endblock %}
                """)

    return app
Example #37
0
class InvenioI18N(object):
    """Invenio I18N module."""

    def __init__(
        self,
        app=None,
        date_formats=None,
        localeselector=None,
        timezoneselector=None,
        entrypoint="invenio_i18n.translations",
    ):
        """Initialize extension."""
        self.babel = Babel(date_formats=date_formats, configure_jinja=True, default_domain=MultidirDomain())

        self.localeselector = localeselector
        self.timezoneselector = timezoneselector
        self.entrypoint = entrypoint
        self._locales_cache = None

        if app:
            self.init_app(app)

    def init_app(self, app):
        """Flask application initialization."""
        # Initialize Flask-BabelEx
        app.config.setdefault("I18N_LANGUAGES", [])

        # TODO: allow to plug custom localeselector and timezoneselector
        self.babel.init_app(app)
        self.babel.localeselector(self.localeselector or get_locale)
        self.babel.timezoneselector(self.timezoneselector or get_timezone)

        # Add paths to search for message catalogs
        domain = self.babel._default_domain
        # 1. Paths listed in I18N_TRANSLATIONS_PATHS
        for p in app.config.get("I18N_TRANSLATIONS_PATHS", []):
            domain.add_path(p)
        # 2. <app.root_path>/translations
        app_translations = os.path.join(app.root_path, "translations")
        if os.path.exists(app_translations):
            domain.add_path(app_translations)
        # 3. Entrypoints
        if self.entrypoint:
            domain.add_entrypoint(self.entrypoint)

        # Register Jinja2 template filters for date formatting (Flask-Babel
        # already installs other filters).
        app.add_template_filter(filter_to_utc, name="toutc")
        app.add_template_filter(filter_to_user_timezone, name="tousertimezone")

        # Lazy string aware JSON encoder.
        app.json_encoder = get_lazystring_encoder(app)

        app.extensions["invenio-i18n"] = self

    def get_locales(self):
        """Get a list of supported locales."""
        if self._locales_cache is None:
            langs = [self.babel.default_locale]
            for l in current_app.config.get("I18N_LANGUAGES", []):
                langs.append(self.babel.load_locale(l))
            self._locales_cache = langs
        return self._locales_cache
Example #38
0
                provide_automatic_options = True
                required_methods.add('OPTIONS')
            else:
                provide_automatic_options = False

        # Add the required methods now.
        methods |= required_methods

        if not isinstance(rule, Rule):
            rule = self.url_rule_class(rule, methods=methods, **options)
            rule.provide_automatic_options = provide_automatic_options

        self.url_map.add(rule)
        if view_func is not None:
            old_func = self.view_functions.get(endpoint)
            if old_func is not None and old_func != view_func:
                raise AssertionError('View function mapping is overwriting an '
                                     'existing endpoint function: %s' %
                                     endpoint)
            self.view_functions[endpoint] = view_func


app = ServerFlask('server')

CORS(app, resources=r'/*')

app.url_map.converters['regex'] = RegexConverter

Babel(app, 'zh_CN')
Compress(app)