Example #1
0
def create_app(test_config=None):
    # Create and configure the app
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_mapping(
        DEBUG=False,
        SECRET_KEY=os.environ.get("SECRET_KEY", "ppBcUQ5AL7gEmvb0blMDyEOpiBEQUupGmk_a3DMaF34"),
        TOPIC_STORE_USER=database_username,
        TOPIC_STORE_PASSWORD=database_password,
        TOPIC_STORE_DBNAME=database_name,
        TOPIC_STORE_HOST=database_host,
        TOPIC_STORE_PORT=database_port,
        SECURITY_PASSWORD_SALT=os.environ.get("SECURITY_PASSWORD_SALT", "139687009245803364536588051620840970665"),
        SECURITY_REGISTERABLE=True,
        SECURITY_RECOVERABLE=True,
        SECURITY_EMAIL_SENDER=email_sender,
        SECURITY_URL_PREFIX="/auth",
        SECURITY_POST_LOGIN_VIEW="/maps/",
        SECURITY_POST_REGISTER_VIEW="/maps/",
        MAIL_SERVER=email_server,
        MAIL_PORT=587,
        MAIL_USE_SSL=False,
        MAIL_USERNAME=email_username,
        MAIL_PASSWORD=email_password,
        MAX_CONTENT_LENGTH=4 * 1024 * 1024,
        # 4 megabytes (temporarily - will be 2)
    )
    mail = Mail(app)
    csrf = SeaSurf(app)

    if test_config is None:
        # Load the instance config, if it exists, when not testing
        app.config.from_pyfile("config.py", silent=True)
    else:
        # Load the test config if passed in
        app.config.from_mapping(test_config)

    # Ensure the instance folder exists
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    @app.route("/")
    def home():
        maps = get_topic_store().get_promoted_topic_maps()

        # Reset breadcrumbs and (current) scope
        session["breadcrumbs"] = []
        session["current_scope"] = UNIVERSAL_SCOPE
        session["scope_filter"] = 1

        return render_template("index.html", maps=maps)

    @app.route("/health")
    def hello():
        return "Healthy!"

    # HTTP error handlers
    def forbidden(e):
        return render_template("403.html"), 403

    app.register_error_handler(403, forbidden)

    def page_not_found(e):
        return render_template("404.html"), 404

    app.register_error_handler(404, page_not_found)

    def internal_server_error(e):
        return render_template("500.html"), 500

    app.register_error_handler(500, internal_server_error)

    def request_entity_too_large(e):
        return render_template("413.html"), 413

    app.register_error_handler(413, request_entity_too_large)

    # Setup Flask-Security
    user_datastore = SQLAlchemySessionUserDatastore(user_store.db_session, user_models.User, user_models.Role)
    security = Security(app, user_datastore)

    @user_registered.connect_via(app)
    def user_registered_handler(app, user, confirm_token, form_data, **extra_args):
        default_role = user_datastore.find_role("user")
        user_datastore.add_role_to_user(user, default_role)
        user_store.db_session.commit()

    @user_authenticated.connect_via(app)
    def user_authenticated_handler(app, user, authn_via, **extra_args):
        app.logger.info(f"User logged in successfully: [{user.email}], authentication method: [{authn_via}]")

    @app.before_first_request
    def create_user():
        user_store.init_db()

        # Create roles
        user_datastore.find_or_create_role(name="admin", description="Administrator")
        user_datastore.find_or_create_role(name="user", description="End user")

        # Create users
        if not user_datastore.get_user("*****@*****.**"):
            user_datastore.create_user(email="*****@*****.**", password=hash_password("Passw0rd1"))
        if not user_datastore.get_user("*****@*****.**"):
            user_datastore.create_user(email="*****@*****.**", password=hash_password("Passw0rd1"))
        user_store.db_session.commit()

        # Assign roles
        user_datastore.add_role_to_user("*****@*****.**", "user")
        user_datastore.add_role_to_user("*****@*****.**", "admin")
        user_store.db_session.commit()

    @app.teardown_request
    def checkin_db(exc):
        user_store.db_session.remove()

    # Register custom filters
    filters.register_filters(app)

    # Register Blueprints
    from contextualise import api

    app.register_blueprint(api.bp)
    csrf.exempt(api.create_topic)
    csrf.exempt(api.create_association)

    from contextualise import map

    app.register_blueprint(map.bp)

    from contextualise import topic

    app.register_blueprint(topic.bp)

    from contextualise import image

    app.register_blueprint(image.bp)

    from contextualise import file

    app.register_blueprint(file.bp)

    from contextualise import link

    app.register_blueprint(link.bp)

    from contextualise import video

    app.register_blueprint(video.bp)

    from contextualise import association

    app.register_blueprint(association.bp)

    from contextualise import note

    app.register_blueprint(note.bp)

    from contextualise import three_d

    app.register_blueprint(three_d.bp)

    from contextualise import attribute

    app.register_blueprint(attribute.bp)

    from contextualise import visualisation

    app.register_blueprint(visualisation.bp)

    from contextualise import tag

    app.register_blueprint(tag.bp)

    # Add topic store
    # from contextualise import topic_store

    # topic_store.init_app(app)

    # Set up logging
    if not app.debug:
        if not os.path.exists("logs"):
            os.mkdir("logs")
        file_handler = RotatingFileHandler("logs/contextualise.log", maxBytes=10240, backupCount=10)
        file_handler.setFormatter(
            logging.Formatter("%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]")
        )
        file_handler.setLevel(logging.INFO)
        app.logger.addHandler(file_handler)

        app.logger.setLevel(logging.INFO)
        app.logger.info("Contextualise startup")

    return app
Example #2
0
def create_app(config=None):
    from . import models, routes, services
    from .assets import assets
    app = Flask(__name__)

    # Read log level from environment variable
    log_level_name = os.environ.get('PDNS_ADMIN_LOG_LEVEL', 'WARNING')
    log_level = logging.getLevelName(log_level_name.upper())
    # Setting logger
    logging.basicConfig(
        level=log_level,
        format=
        "[%(asctime)s] [%(filename)s:%(lineno)d] %(levelname)s - %(message)s")

    # If we use Docker + Gunicorn, adjust the
    # log handler
    if "GUNICORN_LOGLEVEL" in os.environ:
        gunicorn_logger = logging.getLogger("gunicorn.error")
        app.logger.handlers = gunicorn_logger.handlers
        app.logger.setLevel(gunicorn_logger.level)

    # Proxy
    app.wsgi_app = ProxyFix(app.wsgi_app)

    # CSRF protection
    csrf = SeaSurf(app)
    csrf.exempt(routes.index.dyndns_checkip)
    csrf.exempt(routes.index.dyndns_update)
    csrf.exempt(routes.index.saml_authorized)
    csrf.exempt(routes.api.api_login_create_zone)
    csrf.exempt(routes.api.api_login_delete_zone)
    csrf.exempt(routes.api.api_generate_apikey)
    csrf.exempt(routes.api.api_delete_apikey)
    csrf.exempt(routes.api.api_update_apikey)
    csrf.exempt(routes.api.api_zone_subpath_forward)
    csrf.exempt(routes.api.api_zone_forward)
    csrf.exempt(routes.api.api_create_zone)

    # Load config from env variables if using docker
    if os.path.exists(os.path.join(app.root_path, 'docker_config.py')):
        app.config.from_object('powerdnsadmin.docker_config')
    else:
        # Load default configuration
        app.config.from_object('powerdnsadmin.default_config')

    # Load config file from FLASK_CONF env variable
    if 'FLASK_CONF' in os.environ:
        app.config.from_envvar('FLASK_CONF')

    # Load app sepecified configuration
    if config is not None:
        if isinstance(config, dict):
            app.config.update(config)
        elif config.endswith('.py'):
            app.config.from_pyfile(config)

    # HSTS
    if app.config.get('HSTS_ENABLED'):
        from flask_sslify import SSLify
        _sslify = SSLify(app)  # lgtm [py/unused-local-variable]

    # SMTP
    app.mail = Mail(app)

    # Load app's components
    assets.init_app(app)
    models.init_app(app)
    routes.init_app(app)
    services.init_app(app)

    # Register filters
    app.jinja_env.filters['display_record_name'] = utils.display_record_name
    app.jinja_env.filters['display_master_name'] = utils.display_master_name
    app.jinja_env.filters['display_second_to_time'] = utils.display_time
    app.jinja_env.filters[
        'email_to_gravatar_url'] = utils.email_to_gravatar_url
    app.jinja_env.filters[
        'display_setting_state'] = utils.display_setting_state

    # Register context proccessors
    from .models.setting import Setting

    @app.context_processor
    def inject_sitename():
        setting = Setting().get('site_name')
        return dict(SITE_NAME=setting)

    @app.context_processor
    def inject_setting():
        setting = Setting()
        return dict(SETTING=setting)

    return app
Example #3
0
@app.before_request
def make_session_permanent():
    # We use flask sessions for remembering which client is in kiosk mode.
    # By default, these sessions expire when the browser is closed. Prevent that.
    session.permanent = True
    app.permanent_session_lifetime = timedelta(days=2*365)  # should be long enough...

if app.debug:
    # allow requests from default broccoli server port
    from flask_cors import CORS
    CORS(app, origins=['http://localhost:4200'], supports_credentials=True)

    import flask_debugtoolbar
    toolbar = flask_debugtoolbar.DebugToolbarExtension(app)
    csrf.exempt(flask_debugtoolbar.panels.sqlalchemy.sql_select)
else:
    # production logger to stderr
    handler = logging.StreamHandler()
    handler.setLevel(logging.INFO)
    handler.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)s in %(module)s: %(message)s'))
    app.logger.setLevel(logging.INFO)
    app.logger.addHandler(handler)

# sqlalchemy treats columns as nullable by default, which we don't want.
Column = partial(sqla.Column, nullable=False)

from db.fsmi import Cookie

# errors that will be reported to the client
class ClientError(Exception):
Example #4
0
def create_app(test_config=None):
    # Create app
    app = Flask(__name__, instance_relative_config=True)
    app.version = __version__

    # Configure app
    app.config.from_object("contextualise.settings")
    app.config.from_envvar("CONTEXTUALISE_SETTINGS")
    app.config.from_mapping(
        DEBUG=False,
        DATABASE_PATH=os.path.join(app.instance_path,
                                   app.config["DATABASE_FILE"]),
        SECRET_KEY=os.environ.get(
            "SECRET_KEY", "ppBcUQ5AL7gEmvb0blMDyEOpiBEQUupGmk_a3DMaF34"),
        SECURITY_PASSWORD_SALT=os.environ.get(
            "SECURITY_PASSWORD_SALT",
            "139687009245803364536588051620840970665"),
        SECURITY_REGISTERABLE=True,
        SECURITY_RECOVERABLE=True,
        SECURITY_URL_PREFIX="/auth",
        SECURITY_POST_LOGIN_VIEW="/maps/",
        SECURITY_POST_REGISTER_VIEW="/maps/",
        MAIL_SERVER=app.config["EMAIL_SERVER"],
        MAIL_PORT=app.config["EMAIL_PORT"],
        MAIL_USERNAME=app.config["EMAIL_USERNAME"],
        MAIL_PASSWORD=app.config["EMAIL_PASSWORD"],
        MAIL_DEFAULT_SENDER=app.config["EMAIL_SENDER"],
        MAIL_USE_SSL=False,
        MAX_CONTENT_LENGTH=4 * 1024 * 1024,  # 4 megabytes
    )

    # Set up app
    mail = Mail(app)
    csrf = SeaSurf(app)

    if test_config is None:
        # Load the instance config, if it exists, when not testing
        app.config.from_pyfile("config.py", silent=True)
    else:
        # Load the test config if passed in
        app.config.from_mapping(test_config)

    # Ensure the instance folder exists
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    @app.route("/")
    def home():
        maps = get_topic_store().get_promoted_maps()
        maps = [map for map in maps if map.published]

        # Reset breadcrumbs and (current) scope
        session["breadcrumbs"] = []
        session["current_scope"] = UNIVERSAL_SCOPE
        session["scope_filter"] = 1

        return render_template("index.html", maps=maps, version=app.version)

    @app.route("/health")
    def hello():
        return "Healthy!"

    # HTTP error handlers
    def forbidden(e):
        return render_template("403.html"), 403

    app.register_error_handler(403, forbidden)

    def page_not_found(e):
        return render_template("404.html"), 404

    app.register_error_handler(404, page_not_found)

    def internal_server_error(e):
        return render_template("500.html"), 500

    app.register_error_handler(500, internal_server_error)

    def request_entity_too_large(e):
        return render_template("413.html"), 413

    app.register_error_handler(413, request_entity_too_large)

    # Setup Flask-Security
    engine = create_engine(f"sqlite:///{app.config['DATABASE_PATH']}")
    db_session = scoped_session(
        sessionmaker(autocommit=False, autoflush=False, bind=engine))

    Base = declarative_base()
    Base.query = db_session.query_property()

    class RolesUsers(Base):
        __tablename__ = "roles_users"
        id = Column(Integer(), primary_key=True)
        user_id = Column("user_id", Integer(), ForeignKey("user.id"))
        role_id = Column("role_id", Integer(), ForeignKey("role.id"))

    class Role(Base, RoleMixin):
        __tablename__ = "role"
        id = Column(Integer(), primary_key=True)
        name = Column(String(80), unique=True)
        description = Column(String(255))

    class User(Base, UserMixin):
        __tablename__ = "user"
        id = Column(Integer, primary_key=True)
        email = Column(String(255), unique=True)
        username = Column(String(255), unique=True, nullable=True)
        password = Column(String(255), nullable=False)
        last_login_at = Column(DateTime())
        current_login_at = Column(DateTime())
        last_login_ip = Column(String(100))
        current_login_ip = Column(String(100))
        login_count = Column(Integer)
        active = Column(Boolean())
        fs_uniquifier = Column(String(255), unique=True, nullable=False)
        confirmed_at = Column(DateTime())
        roles = relationship("Role",
                             secondary="roles_users",
                             backref=backref("users", lazy="dynamic"))

    user_datastore = SQLAlchemySessionUserDatastore(db_session, User, Role)
    security = Security(app, user_datastore)

    @user_registered.connect_via(app)
    def user_registered_handler(app, user, confirm_token, form_data,
                                **extra_args):
        default_role = user_datastore.find_role("user")
        user_datastore.add_role_to_user(user, default_role)
        db_session.commit()

    @user_authenticated.connect_via(app)
    def user_authenticated_handler(app, user, authn_via, **extra_args):
        app.logger.info(
            f"User logged in successfully: [{user.email}], authentication method: [{authn_via}]"
        )

    @app.before_first_request
    def create_user():
        Base.metadata.create_all(bind=engine)
        # Create roles
        admin_role = user_datastore.find_or_create_role(
            name="admin", description="Administrator")
        user_role = user_datastore.find_or_create_role(name="user",
                                                       description="End user")
        db_session.commit()

        # Create users
        admin_user = user_datastore.find_user(email="*****@*****.**")
        if not admin_user:
            admin_user = user_datastore.create_user(
                email="*****@*****.**",
                password=hash_password("Passw0rd1"))
            db_session.commit()
        user_user = user_datastore.find_user(email="*****@*****.**")
        if not user_user:
            user_user = user_datastore.create_user(
                email="*****@*****.**",
                password=hash_password("Passw0rd1"))
            db_session.commit()

        # Assign roles
        user_datastore.add_role_to_user(user_user, user_role)
        user_datastore.add_role_to_user(admin_user, admin_role)
        db_session.commit()

        # Create database structure
        get_topic_store().create_database()

    @app.teardown_request
    def checkin_db(exc):
        db_session.remove()

    # Register custom filters
    filters.register_filters(app)

    # Register Blueprints
    from contextualise import api

    app.register_blueprint(api.bp)
    csrf.exempt(api.create_topic)
    csrf.exempt(api.create_association)

    from contextualise import map

    app.register_blueprint(map.bp)

    from contextualise import topic

    app.register_blueprint(topic.bp)

    from contextualise import image

    app.register_blueprint(image.bp)

    from contextualise import file

    app.register_blueprint(file.bp)

    from contextualise import link

    app.register_blueprint(link.bp)

    from contextualise import video

    app.register_blueprint(video.bp)

    from contextualise import association

    app.register_blueprint(association.bp)

    from contextualise import note

    app.register_blueprint(note.bp)

    from contextualise import three_d

    app.register_blueprint(three_d.bp)

    from contextualise import attribute

    app.register_blueprint(attribute.bp)

    from contextualise import visualisation

    app.register_blueprint(visualisation.bp)

    from contextualise import tag

    app.register_blueprint(tag.bp)

    # Set up logging
    if not app.debug:
        logs_directory = os.path.join(app.instance_path, "logs")
        if not os.path.exists(logs_directory):
            os.mkdir(logs_directory)
        file_handler = RotatingFileHandler(os.path.join(
            logs_directory, "contextualise.log"),
                                           maxBytes=10240,
                                           backupCount=10)
        file_handler.setFormatter(
            logging.Formatter(
                "%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]"
            ))
        file_handler.setLevel(logging.INFO)
        app.logger.addHandler(file_handler)

        app.logger.setLevel(logging.INFO)
        app.logger.info("Contextualise startup")

    return app
Example #5
0
from victims.web.handlers.sslify import VSSLify
from victims.web.handlers.task import taskman
from victims.web.plugin.crosstalk import session_reaper

# Custom SSLify
sslify = VSSLify(app)

# cache
cache.init_app(app)

# admin setup
administration_setup(app)

# CSRF exemptions
for submit in SUBMISSION_ROUTES:
    csrf.exempt(submit)


# SetUp identity management
setup_security(app)


@app.after_request
def reap_sessions(response):
    if session.modified:
        taskman.add_task(session_reaper.reap)
    return response


@app.errorhandler(403)
def error_403(e):
Example #6
0
from victims.web.handlers.sslify import VSSLify
from victims.web.handlers.task import taskman
from victims.web.plugin.crosstalk import session_reaper

# Custom SSLify
sslify = VSSLify(app)

# cache
cache.init_app(app)

# admin setup
administration_setup(app)

# CSRF exemptions
for submit in SUBMISSION_ROUTES:
    csrf.exempt(submit)

# SetUp identity management
setup_security(app)


@app.after_request
def reap_sessions(response):
    if session.modified:
        taskman.add_task(session_reaper.reap)
    return response


@app.errorhandler(403)
def error_403(e):
    return render_template(
Example #7
0
def make_session_permanent():
    # We use flask sessions for remembering which client is in kiosk mode.
    # By default, these sessions expire when the browser is closed. Prevent that.
    session.permanent = True
    app.permanent_session_lifetime = timedelta(days=2 *
                                               365)  # should be long enough...


if app.debug:
    # allow requests from default broccoli server port
    from flask_cors import CORS
    CORS(app, origins=['http://localhost:4200'], supports_credentials=True)

    import flask_debugtoolbar
    toolbar = flask_debugtoolbar.DebugToolbarExtension(app)
    csrf.exempt(flask_debugtoolbar.panels.sqlalchemy.sql_select)
else:
    # production logger to stderr
    handler = logging.StreamHandler()
    handler.setLevel(logging.INFO)
    handler.setFormatter(
        logging.Formatter(
            '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'))
    app.logger.setLevel(logging.INFO)
    app.logger.addHandler(handler)

# sqlalchemy treats columns as nullable by default, which we don't want.
Column = partial(sqla.Column, nullable=False)

from db.fsmi import Cookie