Beispiel #1
0
def test_menu_links():
    app = Flask(__name__)
    admin = base.Admin(app)
    admin.add_link(base.MenuLink('TestMenuLink1', endpoint='.index'))
    admin.add_link(base.MenuLink('TestMenuLink2', url='http://python.org/'))

    client = app.test_client()
    rv = client.get('/admin/')

    data = rv.data.decode('utf-8')
    ok_('TestMenuLink1' in data)
    ok_('TestMenuLink2' in data)
Beispiel #2
0
def test_menu_links():
    app = Flask(__name__)
    admin = base.Admin(app)
    admin.add_link(base.MenuLink("TestMenuLink1", endpoint=".index"))
    admin.add_link(base.MenuLink("TestMenuLink2", url="http://python.org/"))

    client = app.test_client()
    rv = client.get("/admin/")

    data = rv.data.decode("utf-8")
    ok_("TestMenuLink1" in data)
    ok_("TestMenuLink2" in data)
Beispiel #3
0
def add_default_views(admin_app_):
    from admin.views import UserAdmin, RoleAdmin
    from flask_security_ndb import User, Role
    # Add Flask-Admin views for Users and Roles
    admin_app_.add_view(UserAdmin(User, category='Entities'))
    admin_app_.add_view(RoleAdmin(Role, category='Entities'))
    admin_app_.add_link(base.MenuLink(name='Site Home', url='/'))
Beispiel #4
0
def test_menu_order():
    app = Flask(__name__)
    admin = base.Admin(app)

    view_no_order = MockView(endpoint='test_no_order')
    admin.add_view(view_no_order)
    eq_(admin._menu[-1].sort_order, 0)
    eq_(admin._menu[0].sort_order, 99999)

    view1 = MockView(endpoint='test1', menu_order=20)
    view2 = MockView(endpoint='test2', menu_order=30)
    view3 = MockView(endpoint='test3', menu_order=40)
    admin.add_views(view3, view1, view2)
    ok_(admin._menu[1]._view is view3)
    eq_(admin._menu[2].sort_order, view2.menu_order)
    ok_(admin._menu[0]._view is admin.index_view)

    catname = "test_category"
    admin.category_menu_orders[catname] = 50
    view_with_cat = MockView(endpoint="test_with_category", category=catname)
    admin.add_view(view_with_cat)
    eq_(admin._menu[1].name, catname)

    admin.add_link(base.MenuLink('Link1', endpoint='.link1', sort_order=100))
    admin.add_link(base.MenuLink('Link2', endpoint='.link2', sort_order=110))
    eq_(admin._menu_links[0].name, "Link2")

    admin.add_link(
        base.MenuLink('LinkWithCategory1',
                      endpoint='.linkcat1',
                      category=catname,
                      sort_order=200))
    admin.add_link(
        base.MenuLink('LinkWithCategory2',
                      endpoint='.linkcat2',
                      category=catname,
                      sort_order=220))
    children = admin._menu[1].get_children()
    eq_(children[0].name, "LinkWithCategory2")
Beispiel #5
0
def create_app(config=None, testing=False):
    app = Flask(__name__)
    if configuration.conf.getboolean('webserver', 'ENABLE_PROXY_FIX'):
        app.wsgi_app = ProxyFix(app.wsgi_app,
                                num_proxies=None,
                                x_for=1,
                                x_proto=1,
                                x_host=1,
                                x_port=1,
                                x_prefix=1)
    app.secret_key = configuration.conf.get('webserver', 'SECRET_KEY')
    app.config['LOGIN_DISABLED'] = not configuration.conf.getboolean(
        'webserver', 'AUTHENTICATE')

    app.config['SESSION_COOKIE_HTTPONLY'] = True
    app.config['SESSION_COOKIE_SECURE'] = conf.getboolean(
        'webserver', 'COOKIE_SECURE')
    app.config['SESSION_COOKIE_SAMESITE'] = conf.get('webserver',
                                                     'COOKIE_SAMESITE')

    if config:
        app.config.from_mapping(config)

    csrf.init_app(app)

    app.config['TESTING'] = testing

    airflow.load_login()
    airflow.login.LOGIN_MANAGER.init_app(app)

    from airflow import api
    api.load_auth()
    api.API_AUTH.api_auth.init_app(app)

    # flake8: noqa: F841
    cache = Cache(app=app,
                  config={
                      'CACHE_TYPE': 'filesystem',
                      'CACHE_DIR': '/tmp'
                  })

    app.register_blueprint(routes)

    configure_logging()

    with app.app_context():
        from airflow.www import views

        admin = Admin(
            app,
            name='Airflow',
            static_url_path='/admin',
            index_view=views.HomeView(endpoint='', url='/admin', name="DAGs"),
            template_mode='bootstrap3',
        )
        av = admin.add_view
        vs = views
        av(vs.Airflow(name='DAGs', category='DAGs'))

        if not conf.getboolean('core', 'secure_mode'):
            av(vs.QueryView(name='Ad Hoc Query', category="Data Profiling"))
            av(
                vs.ChartModelView(models.Chart,
                                  Session,
                                  name="Charts",
                                  category="Data Profiling"))
        av(
            vs.KnownEventView(models.KnownEvent,
                              Session,
                              name="Known Events",
                              category="Data Profiling"))
        av(
            vs.SlaMissModelView(models.SlaMiss,
                                Session,
                                name="SLA Misses",
                                category="Browse"))
        av(
            vs.TaskInstanceModelView(models.TaskInstance,
                                     Session,
                                     name="Task Instances",
                                     category="Browse"))
        av(vs.LogModelView(models.Log, Session, name="Logs",
                           category="Browse"))
        av(
            vs.JobModelView(jobs.BaseJob,
                            Session,
                            name="Jobs",
                            category="Browse"))
        av(
            vs.PoolModelView(models.Pool,
                             Session,
                             name="Pools",
                             category="Admin"))
        av(vs.ConfigurationView(name='Configuration', category="Admin"))
        av(
            vs.UserModelView(models.User,
                             Session,
                             name="Users",
                             category="Admin"))
        av(
            vs.ConnectionModelView(Connection,
                                   Session,
                                   name="Connections",
                                   category="Admin"))
        av(
            vs.VariableView(models.Variable,
                            Session,
                            name="Variables",
                            category="Admin"))
        av(vs.XComView(models.XCom, Session, name="XComs", category="Admin"))

        admin.add_link(
            base.MenuLink(category='Docs',
                          name='Documentation',
                          url='https://airflow.apache.org/'))
        admin.add_link(
            base.MenuLink(category='Docs',
                          name='GitHub',
                          url='https://github.com/apache/airflow'))

        av(vs.VersionView(name='Version', category="About"))

        av(
            vs.DagRunModelView(models.DagRun,
                               Session,
                               name="DAG Runs",
                               category="Browse"))
        av(vs.DagModelView(models.DagModel, Session, name=None))
        # Hack to not add this view to the menu
        admin._menu = admin._menu[:-1]

        def integrate_plugins():
            """Integrate plugins to the context"""
            log = LoggingMixin().log
            from airflow.plugins_manager import (admin_views, flask_blueprints,
                                                 menu_links)
            for v in admin_views:
                log.debug('Adding view %s', v.name)
                admin.add_view(v)
            for bp in flask_blueprints:
                log.debug("Adding blueprint %s:%s", bp["name"],
                          bp["blueprint"].import_name)
                app.register_blueprint(bp["blueprint"])
            for ml in sorted(menu_links, key=lambda x: x.name):
                log.debug('Adding menu link %s', ml.name)
                admin.add_link(ml)

        integrate_plugins()

        import airflow.www.api.experimental.endpoints as e
        # required for testing purposes otherwise the module retains
        # a link to the default_auth
        if app.config['TESTING']:
            six.moves.reload_module(e)

        app.register_blueprint(e.api_experimental,
                               url_prefix='/api/experimental')

        @app.context_processor
        def jinja_globals():
            return {
                'hostname': get_hostname(),
                'navbar_color': configuration.get('webserver', 'NAVBAR_COLOR'),
            }

        @app.teardown_appcontext
        def shutdown_session(exception=None):
            settings.Session.remove()

        return app
Beispiel #6
0
def create_app(config=None, testing=False):
    app = Flask(__name__)
    app.secret_key = configuration.get('webserver', 'SECRET_KEY')
    app.config['LOGIN_DISABLED'] = not configuration.getboolean(
        'webserver', 'AUTHENTICATE')

    csrf.init_app(app)

    app.config['TESTING'] = testing

    airflow.load_login()
    airflow.login.login_manager.init_app(app)

    from airflow import api
    api.load_auth()
    api.api_auth.init_app(app)

    cache = Cache(app=app,
                  config={
                      'CACHE_TYPE': 'filesystem',
                      'CACHE_DIR': '/tmp'
                  })

    app.register_blueprint(routes)

    log_format = airflow.settings.LOG_FORMAT_WITH_PID
    airflow.settings.configure_logging(log_format=log_format)

    with app.app_context():
        from airflow.www import views

        admin = Admin(
            app,
            name='Airflow',
            static_url_path='/admin',
            index_view=views.HomeView(endpoint='', url='/admin', name="DAGs"),
            template_mode='bootstrap3',
        )
        av = admin.add_view
        vs = views
        av(vs.Airflow(name='DAGs', category='DAGs'))

        av(vs.QueryView(name='Ad Hoc Query', category="Data Profiling"))
        av(
            vs.ChartModelView(models.Chart,
                              Session,
                              name="Charts",
                              category="Data Profiling"))
        av(
            vs.KnownEventView(models.KnownEvent,
                              Session,
                              name="Known Events",
                              category="Data Profiling"))
        av(
            vs.SlaMissModelView(models.SlaMiss,
                                Session,
                                name="SLA Misses",
                                category="Browse"))
        av(
            vs.TaskInstanceModelView(models.TaskInstance,
                                     Session,
                                     name="Task Instances",
                                     category="Browse"))
        av(vs.LogModelView(models.Log, Session, name="Logs",
                           category="Browse"))
        av(
            vs.JobModelView(jobs.BaseJob,
                            Session,
                            name="Jobs",
                            category="Browse"))
        av(
            vs.PoolModelView(models.Pool,
                             Session,
                             name="Pools",
                             category="Admin"))
        av(vs.ConfigurationView(name='Configuration', category="Admin"))
        av(
            vs.UserModelView(models.User,
                             Session,
                             name="Users",
                             category="Admin"))
        av(
            vs.ConnectionModelView(models.Connection,
                                   Session,
                                   name="Connections",
                                   category="Admin"))
        av(
            vs.VariableView(models.Variable,
                            Session,
                            name="Variables",
                            category="Admin"))
        av(vs.XComView(models.XCom, Session, name="XComs", category="Admin"))

        admin.add_link(
            base.MenuLink(category='Docs',
                          name='Documentation',
                          url='http://pythonhosted.org/airflow/'))
        admin.add_link(
            base.MenuLink(category='Docs',
                          name='Github',
                          url='https://github.com/apache/incubator-airflow'))

        av(vs.VersionView(name='Version', category="About"))

        av(
            vs.DagRunModelView(models.DagRun,
                               Session,
                               name="DAG Runs",
                               category="Browse"))
        av(vs.DagModelView(models.DagModel, Session, name=None))
        # Hack to not add this view to the menu
        admin._menu = admin._menu[:-1]

        def integrate_plugins():
            """Integrate plugins to the context"""
            from airflow.plugins_manager import (admin_views, flask_blueprints,
                                                 menu_links)
            for v in admin_views:
                logging.debug('Adding view ' + v.name)
                admin.add_view(v)
            for bp in flask_blueprints:
                logging.debug('Adding blueprint ' + bp.name)
                app.register_blueprint(bp)
            for ml in sorted(menu_links, key=lambda x: x.name):
                logging.debug('Adding menu link ' + ml.name)
                admin.add_link(ml)

        integrate_plugins()

        import airflow.www.api.experimental.endpoints as e
        # required for testing purposes otherwise the module retains
        # a link to the default_auth
        if app.config['TESTING']:
            if six.PY2:
                reload(e)
            else:
                import importlib
                importlib.reload(e)

        app.register_blueprint(e.api_experimental,
                               url_prefix='/api/experimental')

        @app.context_processor
        def jinja_globals():
            return {
                'hostname': get_hostname(),
            }

        @app.teardown_appcontext
        def shutdown_session(exception=None):
            settings.Session.remove()

        return app
Beispiel #7
0
def create_app(config=None):
    app = Flask(__name__)
    app.secret_key = configuration.get('webserver', 'SECRET_KEY')
    app.config['LOGIN_DISABLED'] = not configuration.getboolean('webserver', 'AUTHENTICATE')

    csrf.init_app(app)

    #app.config = config
    airflow.load_login()
    airflow.login.login_manager.init_app(app)

    cache = Cache(
        app=app, config={'CACHE_TYPE': 'filesystem', 'CACHE_DIR': '/tmp'})

    app.register_blueprint(ck, url_prefix='/ck')
    app.register_blueprint(routes)
    app.jinja_env.add_extension("chartkick.ext.charts")

    with app.app_context():
        from airflow.www import views

        admin = Admin(
            app, name='Airflow',
            static_url_path='/admin',
            index_view=views.HomeView(endpoint='', url='/admin', name="DAGs"),
            template_mode='bootstrap3',
        )
        av = admin.add_view
        vs = views
        av(vs.Airflow(name='DAGs', category='DAGs'))

        av(vs.QueryView(name='Ad Hoc Query', category="Data Profiling"))
        av(vs.ChartModelView(
            models.Chart, Session, name="Charts", category="Data Profiling"))
        av(vs.KnowEventView(
            models.KnownEvent,
            Session, name="Known Events", category="Data Profiling"))
        av(vs.SlaMissModelView(
            models.SlaMiss,
            Session, name="SLA Misses", category="Browse"))
        av(vs.TaskInstanceModelView(models.TaskInstance,
            Session, name="Task Instances", category="Browse"))
        av(vs.LogModelView(
            models.Log, Session, name="Logs", category="Browse"))
        av(vs.JobModelView(
            jobs.BaseJob, Session, name="Jobs", category="Browse"))
        av(vs.PoolModelView(
            models.Pool, Session, name="Pools", category="Admin"))
        av(vs.ConfigurationView(
            name='Configuration', category="Admin"))
        av(vs.UserModelView(
            models.User, Session, name="Users", category="Admin"))
        av(vs.ConnectionModelView(
            models.Connection, Session, name="Connections", category="Admin"))
        av(vs.VariableView(
            models.Variable, Session, name="Variables", category="Admin"))

        admin.add_link(base.MenuLink(
            category='Docs', name='Documentation',
            url='http://pythonhosted.org/airflow/'))
        admin.add_link(
            base.MenuLink(category='Docs',
                name='Github',url='https://github.com/airbnb/airflow'))

        av(vs.DagRunModelView(
            models.DagRun, Session, name="DAG Runs", category="Browse"))
        av(vs.DagModelView(models.DagModel, Session, name=None))
        # Hack to not add this view to the menu
        admin._menu = admin._menu[:-1]

        def integrate_plugins():
            """Integrate plugins to the context"""
            from airflow.plugins_manager import (
                admin_views, flask_blueprints, menu_links)
            for v in admin_views:
                admin.add_view(v)
            for bp in flask_blueprints:
                app.register_blueprint(bp)
            for ml in menu_links:
                admin.add_link(ml)

        integrate_plugins()

        @app.context_processor
        def jinja_globals():
            return {
                'hostname': socket.gethostname(),
            }

        @app.teardown_appcontext
        def shutdown_session(exception=None):
            settings.Session.remove()

        return app
def create_app(config=None, testing=False):
    app = Flask(__name__)
    if conf.getboolean('webserver', 'ENABLE_PROXY_FIX'):
        app.wsgi_app = ProxyFix(app.wsgi_app,
                                num_proxies=conf.get("webserver",
                                                     "PROXY_FIX_NUM_PROXIES",
                                                     fallback=None),
                                x_for=conf.getint("webserver",
                                                  "PROXY_FIX_X_FOR",
                                                  fallback=1),
                                x_proto=conf.getint("webserver",
                                                    "PROXY_FIX_X_PROTO",
                                                    fallback=1),
                                x_host=conf.getint("webserver",
                                                   "PROXY_FIX_X_HOST",
                                                   fallback=1),
                                x_port=conf.getint("webserver",
                                                   "PROXY_FIX_X_PORT",
                                                   fallback=1),
                                x_prefix=conf.getint("webserver",
                                                     "PROXY_FIX_X_PREFIX",
                                                     fallback=1))
    app.secret_key = conf.get('webserver', 'SECRET_KEY')
    app.config['LOGIN_DISABLED'] = not conf.getboolean('webserver',
                                                       'AUTHENTICATE')

    app.config['SESSION_COOKIE_HTTPONLY'] = True
    app.config['SESSION_COOKIE_SECURE'] = conf.getboolean(
        'webserver', 'COOKIE_SECURE')
    app.config['SESSION_COOKIE_SAMESITE'] = conf.get('webserver',
                                                     'COOKIE_SAMESITE')

    if config:
        app.config.from_mapping(config)

    csrf.init_app(app)

    app.config['TESTING'] = testing

    airflow.load_login()
    airflow.login.LOGIN_MANAGER.init_app(app)

    from airflow import api
    api.load_auth()
    api.API_AUTH.api_auth.init_app(app)

    # flake8: noqa: F841
    cache = Cache(app=app,
                  config={
                      'CACHE_TYPE': 'filesystem',
                      'CACHE_DIR': '/tmp'
                  })

    app.register_blueprint(routes)

    configure_logging()

    with app.app_context():
        from airflow.www import views

        admin = Admin(
            app,
            name='Airflow',
            static_url_path='/admin',
            index_view=views.HomeView(endpoint='', url='/admin', name="DAGs"),
            template_mode='bootstrap3',
        )
        av = admin.add_view
        vs = views
        av(vs.Airflow(name='DAGs', category='DAGs'))

        if not conf.getboolean('core', 'secure_mode'):
            av(vs.QueryView(name='Ad Hoc Query', category="Data Profiling"))
            av(
                vs.ChartModelView(models.Chart,
                                  Session,
                                  name="Charts",
                                  category="Data Profiling"))
        av(
            vs.KnownEventView(models.KnownEvent,
                              Session,
                              name="Known Events",
                              category="Data Profiling"))
        av(
            vs.SlaMissModelView(models.SlaMiss,
                                Session,
                                name="SLA Misses",
                                category="Browse"))
        av(
            vs.TaskInstanceModelView(models.TaskInstance,
                                     Session,
                                     name="Task Instances",
                                     category="Browse"))
        av(vs.LogModelView(models.Log, Session, name="Logs",
                           category="Browse"))
        av(
            vs.JobModelView(jobs.BaseJob,
                            Session,
                            name="Jobs",
                            category="Browse"))
        av(
            vs.PoolModelView(models.Pool,
                             Session,
                             name="Pools",
                             category="Admin"))
        av(vs.ConfigurationView(name='Configuration', category="Admin"))
        av(
            vs.UserModelView(models.User,
                             Session,
                             name="Users",
                             category="Admin"))
        av(
            vs.ConnectionModelView(Connection,
                                   Session,
                                   name="Connections",
                                   category="Admin"))
        av(
            vs.VariableView(models.Variable,
                            Session,
                            name="Variables",
                            category="Admin"))
        av(vs.XComView(models.XCom, Session, name="XComs", category="Admin"))

        if "dev" in version.version:
            airflow_doc_site = "https://airflow.readthedocs.io/en/latest"
        else:
            airflow_doc_site = 'https://airflow.apache.org/docs/{}'.format(
                version.version)

        admin.add_link(
            base.MenuLink(name="Website",
                          url='https://airflow.apache.org',
                          category="Docs"))
        admin.add_link(
            base.MenuLink(category='Docs',
                          name='Documentation',
                          url=airflow_doc_site))
        admin.add_link(
            base.MenuLink(category='Docs',
                          name='GitHub',
                          url='https://github.com/apache/airflow'))

        av(vs.VersionView(name='Version', category="About"))

        av(
            vs.DagRunModelView(models.DagRun,
                               Session,
                               name="DAG Runs",
                               category="Browse"))
        av(vs.DagModelView(models.DagModel, Session, name=None))
        # Hack to not add this view to the menu
        admin._menu = admin._menu[:-1]

        def integrate_plugins():
            """Integrate plugins to the context"""
            log = LoggingMixin().log
            from airflow.plugins_manager import (admin_views, flask_blueprints,
                                                 menu_links)
            for v in admin_views:
                log.debug('Adding view %s', v.name)
                admin.add_view(v)
            for bp in flask_blueprints:
                log.debug("Adding blueprint %s:%s", bp["name"],
                          bp["blueprint"].import_name)
                app.register_blueprint(bp["blueprint"])
            for ml in sorted(menu_links, key=lambda x: x.name):
                log.debug('Adding menu link %s', ml.name)
                admin.add_link(ml)

        integrate_plugins()

        import airflow.www.api.experimental.endpoints as e
        # required for testing purposes otherwise the module retains
        # a link to the default_auth
        if app.config['TESTING']:
            six.moves.reload_module(e)

        app.register_blueprint(e.api_experimental,
                               url_prefix='/api/experimental')

        @app.context_processor
        def jinja_globals():
            return {
                'hostname':
                get_hostname() if conf.getboolean('webserver',
                                                  'EXPOSE_HOSTNAME',
                                                  fallback=True) else 'redact',
                'navbar_color':
                conf.get('webserver', 'NAVBAR_COLOR'),
                'log_fetch_delay_sec':
                conf.getint('webserver', 'log_fetch_delay_sec', fallback=2),
                'log_auto_tailing_offset':
                conf.getint('webserver',
                            'log_auto_tailing_offset',
                            fallback=30),
                'log_animation_speed':
                conf.getint('webserver', 'log_animation_speed', fallback=1000)
            }

        @app.before_request
        def before_request():
            _force_log_out_after = conf.getint('webserver',
                                               'FORCE_LOG_OUT_AFTER',
                                               fallback=0)
            if _force_log_out_after > 0:
                flask.session.permanent = True
                app.permanent_session_lifetime = datetime.timedelta(
                    minutes=_force_log_out_after)
                flask.session.modified = True
                flask.g.user = flask_login.current_user

        @app.after_request
        def apply_caching(response):
            _x_frame_enabled = conf.getboolean('webserver',
                                               'X_FRAME_ENABLED',
                                               fallback=True)
            if not _x_frame_enabled:
                response.headers["X-Frame-Options"] = "DENY"
            return response

        @app.teardown_appcontext
        def shutdown_session(exception=None):
            settings.Session.remove()

        return app
Beispiel #9
0

class UserAdminView(MyModelView):
    column_exclude_list = ('password')

    def is_accessible(self):
        return current_user.has_role('admin')

    def __init__(self, session, **kwargs):
        super(UserAdminView, self).__init__(User, session, **kwargs)


class RoleView(MyModelView):
    def is_accessible(self):
        return current_user.has_role('admin')

    def __init__(self, session, **kwargs):
        super(RoleView, self).__init__(Role, session, **kwargs)


admin = Admin(app,
              name='Hive Admin',
              index_view=MyAdminIndexView(),
              template_mode='bootstrap3')
admin.add_view(ExpenseAdminView(db.session))
admin.add_view(UserAdminView(db.session))
admin.add_view(RoleView(db.session))
admin.add_link(base.MenuLink('Web Home', endpoint="index"))
admin.add_link(base.MenuLink('Logout', endpoint="logout"))

# --------------------------  END ADMIN PART ---------------------------------
Beispiel #10
0

# Create admin
adminApp = flask_admin.Admin(app,
                             name='EcotaxoServer Administration',
                             url='/admin')

# Add views
adminApp.add_view(UsersView(db.session, name="Users"))

adminApp.add_view(
    TaxonomyView(db.session, category='Taxonomy', name="Edit Taxonomy"))

adminApp.add_link(
    base.MenuLink('Import Taxonomy (admin only)',
                  category='Taxonomy',
                  url='/Task/Create/TaskTaxoImport'))
adminApp.add_link(
    base.MenuLink('Taxonomy errors (admin only)',
                  category='Taxonomy',
                  url='/dbadmin/viewtaxoerror'))
adminApp.add_link(base.MenuLink('EcoTaxoServer Home', url='/'))
adminApp.add_link(
    base.MenuLink('View DB Size (admin only)',
                  category='Database',
                  url='/dbadmin/viewsizes'))
adminApp.add_link(
    base.MenuLink('View DB Bloat (admin only)',
                  category='Database',
                  url='/dbadmin/viewbloat'))
Beispiel #11
0
    ProjectsViewLight(db.session, endpoint="projectlight",
                      category='Projects'))
adminApp.add_view(
    ProjectsView(db.session, name="Projects (Full)", category='Projects'))
adminApp.add_view(ObjectsView(db.session, category='Objects'))
adminApp.add_view(ObjectsFieldsView(db.session, category='Objects'))
adminApp.add_view(SamplesView(db.session, category='Objects'))
adminApp.add_view(ProcessView(db.session, category='Objects'))
adminApp.add_view(AcquisitionsView(db.session, category='Objects'))
adminApp.add_view(
    TaxonomyView(db.session, category='Taxonomy', name="Edit Taxonomy"))

# adminApp.add_link(base.MenuLink('Import Taxonomy (admin only)', category='Taxonomy', url='/Task/Create/TaskTaxoImport'))
adminApp.add_link(
    base.MenuLink('Merge 2 categories (admin only)',
                  category='Taxonomy',
                  url='/dbadmin/merge2taxon'))
adminApp.add_link(
    base.MenuLink('Taxonomy errors (admin only)',
                  category='Taxonomy',
                  url='/dbadmin/viewtaxoerror'))
adminApp.add_link(base.MenuLink('Ecotaxa Home', url='/'))
adminApp.add_link(
    base.MenuLink('View DB Size (admin only)',
                  category='Database',
                  url='/dbadmin/viewsizes'))
adminApp.add_link(
    base.MenuLink('View DB Bloat (admin only)',
                  category='Database',
                  url='/dbadmin/viewbloat'))