def add_static_url(self, url_path, directory, endpoint=None, roles=None): """Add a new url rule for static files. :param endpoint: flask endpoint name for this url rule. :param url: subpath from application static url path. No heading or trailing slash. :param directory: directory to serve content from. Example:: app.add_static_url('myplugin', '/path/to/myplugin/resources', endpoint='myplugin_static') With default setup it will serve content from directory `/path/to/myplugin/resources` from url `http://.../static/myplugin` """ url_path = self.static_url_path + '/' + url_path + '/<path:filename>' self.add_url_rule(url_path, endpoint=endpoint, view_func=partial(send_file_from_directory, directory=directory), roles=roles) self.add_access_controller(endpoint, allow_access_for_roles(Anonymous), endpoint=True)
def add_static_url(self, url_path, directory, endpoint=None, roles=None): """ Adds a new url rule for static files. :param endpoint: flask endpoint name for this url rule. :param url: subpath from application static url path. No heading or trailing slash. :param directory: directory to serve content from. Example:: app.add_static_url('myplugin', '/path/to/myplugin/resources', endpoint='myplugin_static') With default setup it will serve content from directory `/path/to/myplugin/resources` from url `http://.../static/myplugin` """ url_path = self.static_url_path + '/' + url_path + '/<path:filename>' self.add_url_rule(url_path, endpoint=endpoint, view_func=partial(send_file_from_directory, directory=directory), roles=roles) self.add_access_controller(endpoint, allow_access_for_roles(Anonymous), endpoint=True)
def add_url_rule(self, rule, endpoint=None, view_func=None, roles=None, **options): """See :meth:`Flask.add_url_rule`. If `roles` parameter is present, it must be a :class:`abilian.service.security.models.Role` instance, or a list of Role instances. """ super().add_url_rule(rule, endpoint, view_func, **options) if roles: self.add_access_controller( endpoint, allow_access_for_roles(roles), endpoint=True )
def add_url_rule(self, rule, endpoint=None, view_func=None, **options): """ See :meth:`Flask.add_url_rule`. If `roles` parameter is present, it must be a :class:`abilian.service.security.models.Role` instance, or a list of Role instances. """ roles = options.pop('roles', None) super(Application, self).add_url_rule(rule, endpoint, view_func, **options) if roles: self.add_access_controller(endpoint, allow_access_for_roles(roles), endpoint=True)
def add_url_rule_with_role( self, rule: str, endpoint: str, view_func: Callable, roles: Collection[Role] = (), **options: Any, ) -> None: """See :meth:`Flask.add_url_rule`. If `roles` parameter is present, it must be a :class:`abilian.service.security.models.Role` instance, or a list of Role instances. """ self.add_url_rule(rule, endpoint, view_func, **options) if roles: self.add_access_controller(endpoint, allow_access_for_roles(roles), endpoint=True)
def __init__(self, name=None, config=None, *args, **kwargs): kwargs.setdefault('instance_relative_config', True) name = name or __name__ # used by make_config to determine if we try to load config from instance / # environment variable /... self._ABILIAN_INIT_TESTING_FLAG = (getattr(config, 'TESTING', False) if config else False) Flask.__init__(self, name, *args, **kwargs) del self._ABILIAN_INIT_TESTING_FLAG self._setup_script_manager() appcontext_pushed.connect(self._install_id_generator) ServiceManager.__init__(self) PluginManager.__init__(self) self.default_view = ViewRegistry() self.js_api = dict() if config: self.config.from_object(config) # at this point we have loaded all external config files: # SQLALCHEMY_DATABASE_URI is definitively fixed (it cannot be defined in # database AFAICT), and LOGGING_FILE cannot be set in DB settings. self.setup_logging() configured = bool(self.config.get('SQLALCHEMY_DATABASE_URI')) self.config['CONFIGURED'] = configured if not self.testing: self.init_sentry() if not configured: # set fixed secret_key so that any unconfigured worker will use, so that # session can be used during setup even if multiple processes are # processing requests. self.config['SECRET_KEY'] = 'abilian_setup_key' # time to load config bits from database: 'settings' # First init required stuff: db to make queries, and settings service extensions.db.init_app(self) settings_service.init_app(self) if configured: with self.app_context(): try: settings = self.services['settings'].namespace( 'config').as_dict() except sa.exc.DatabaseError as exc: # we may get here if DB is not initialized and "settings" table is # missing. Command "initdb" must be run to initialize db, but first we # must pass app init if not self.testing: # durint tests this message will show up on every test, since db is # always recreated logging.error(exc.message) self.db.session.rollback() else: self.config.update(settings) if not self.config.get('FAVICO_URL'): self.config['FAVICO_URL'] = self.config.get('LOGO_URL') languages = self.config.get('BABEL_ACCEPT_LANGUAGES') if languages is None: languages = abilian.i18n.VALID_LANGUAGES_CODE else: languages = tuple(lang for lang in languages if lang in abilian.i18n.VALID_LANGUAGES_CODE) self.config['BABEL_ACCEPT_LANGUAGES'] = languages self._jinja_loaders = list() self.register_jinja_loaders( jinja2.PackageLoader('abilian.web', 'templates')) js_filters = (('closure_js', ) if self.config.get('PRODUCTION', False) else None) self._assets_bundles = { 'css': { 'options': dict(filters=('less', 'cssmin'), output='style-%(version)s.min.css') }, 'js-top': { 'options': dict(output='top-%(version)s.min.js', filters=js_filters) }, 'js': { 'options': dict(output='app-%(version)s.min.js', filters=js_filters) }, } # bundles for JS translations for lang in languages: code = 'js-i18n-' + lang filename = 'lang-' + lang + '-%(version)s.min.js' self._assets_bundles[code] = { 'options': dict(output=filename, filters=js_filters), } for http_error_code in (403, 404, 500): self.install_default_handler(http_error_code) with self.app_context(): self.init_extensions() self.register_plugins() self.add_access_controller('static', allow_access_for_roles(Anonymous), endpoint=True) # debugtoolbar: this is needed to have it when not authenticated on a # private site. We cannot do this in init_debug_toolbar, since auth # service is not yet installed self.add_access_controller('debugtoolbar', allow_access_for_roles(Anonymous)) self.add_access_controller('_debug_toolbar.static', allow_access_for_roles(Anonymous), endpoint=True) self.maybe_register_setup_wizard() self._finalize_assets_setup() # At this point all models should have been imported: time to configure # mappers. Normally Sqlalchemy does it when needed but mappers may be # configured inside sa.orm.class_mapper() which hides a misconfiguration: if # a mapper is misconfigured its exception is swallowed by # class_mapper(model) results in this laconic (and misleading) message: # "model is not mapped" sa.orm.configure_mappers() signals.components_registered.send(self) self.before_first_request(self._set_current_celery_app) self.before_first_request(lambda: signals.register_js_api.send(self)) request_started.connect(self._setup_nav_and_breadcrumbs) # Initialize Abilian core services. # Must come after all entity classes have been declared. # Inherited from ServiceManager. Will need some configuration love later. if not self.config.get('TESTING', False): with self.app_context(): self.start_services()
def __init__(self, name=None, config=None, *args, **kwargs): name = name or __name__ instance_path = os.environ.get("FLASK_INSTANCE_PATH") if instance_path: kwargs["instance_path"] = instance_path else: kwargs.setdefault("instance_relative_config", True) # used by make_config to determine if we try to load config from # instance / environment variable /... self._ABILIAN_INIT_TESTING_FLAG = (getattr(config, "TESTING", False) if config else False) Flask.__init__(self, name, *args, **kwargs) del self._ABILIAN_INIT_TESTING_FLAG self._setup_script_manager() appcontext_pushed.connect(self._install_id_generator) ServiceManager.__init__(self) PluginManager.__init__(self) JinjaManagerMixin.__init__(self) self.default_view = ViewRegistry() self.js_api = dict() self.configure(config) # At this point we have loaded all external config files: # SQLALCHEMY_DATABASE_URI is definitively fixed (it cannot be defined in # database AFAICT), and LOGGING_FILE cannot be set in DB settings. self.setup_logging() configured = bool(self.config.get("SQLALCHEMY_DATABASE_URI")) self.config["CONFIGURED"] = configured if not self.testing: self.init_sentry() if not configured: # set fixed secret_key so that any unconfigured worker will use, # so that session can be used during setup even if # multiple processes are processing requests. self.config["SECRET_KEY"] = "abilian_setup_key" # time to load config bits from database: 'settings' # First init required stuff: db to make queries, and settings service extensions.db.init_app(self) settings_service.init_app(self) if configured: with self.app_context(): try: settings = self.services["settings"] config = settings.namespace("config").as_dict() except sa.exc.DatabaseError as exc: # We may get here if DB is not initialized and "settings" # table is missing. Command "initdb" must be run to # initialize db, but first we must pass app init. if not self.testing: # durint tests this message will show up on every test, # since db is always recreated logging.error(exc) db.session.rollback() else: self.config.update(config) if not self.config.get("FAVICO_URL"): self.config["FAVICO_URL"] = self.config.get("LOGO_URL") self.register_jinja_loaders(jinja2.PackageLoader("abilian.web")) self.init_assets() self.install_default_handlers() with self.app_context(): self.init_extensions() self.register_plugins() self.add_access_controller("static", allow_access_for_roles(Anonymous), endpoint=True) # debugtoolbar: this is needed to have it when not authenticated # on a private site. We cannot do this in init_debug_toolbar, # since auth service is not yet installed. self.add_access_controller("debugtoolbar", allow_access_for_roles(Anonymous)) self.add_access_controller( "_debug_toolbar.static", allow_access_for_roles(Anonymous), endpoint=True, ) self.maybe_register_setup_wizard() self._finalize_assets_setup() # At this point all models should have been imported: time to configure # mappers. Normally Sqlalchemy does it when needed but mappers may be # configured inside sa.orm.class_mapper() which hides a # misconfiguration: if a mapper is misconfigured its exception is # swallowed by class_mapper(model) results in this laconic # (and misleading) message: "model is not mapped" sa.orm.configure_mappers() signals.components_registered.send(self) self.before_first_request(self._set_current_celery_app) self.before_first_request(lambda: signals.register_js_api.send(self)) request_started.connect(self._setup_nav_and_breadcrumbs) # Initialize Abilian core services. # Must come after all entity classes have been declared. # Inherited from ServiceManager. Will need some configuration love # later. if not self.config.get("TESTING", False): with self.app_context(): self.start_services() if os.environ.get("FLASK_VALIDATE_HTML"): # Workaround circular import from abilian.testing.validation import validate_response self.after_request(validate_response)
def __init__(self, name=None, config=None, *args, **kwargs): kwargs.setdefault('instance_relative_config', True) name = name or __name__ # used by make_config to determine if we try to load config from instance / # environment variable /... self._ABILIAN_INIT_TESTING_FLAG = (getattr(config, 'TESTING', False) if config else False) Flask.__init__(self, name, *args, **kwargs) del self._ABILIAN_INIT_TESTING_FLAG self._setup_script_manager() appcontext_pushed.connect(self._install_id_generator) ServiceManager.__init__(self) PluginManager.__init__(self) self.default_view = ViewRegistry() self.js_api = dict() if config: self.config.from_object(config) # at this point we have loaded all external config files: # SQLALCHEMY_DATABASE_URI is definitively fixed (it cannot be defined in # database AFAICT), and LOGGING_FILE cannot be set in DB settings. self.setup_logging() configured = bool(self.config.get('SQLALCHEMY_DATABASE_URI')) self.config['CONFIGURED'] = configured if not self.testing: self.init_sentry() if not configured: # set fixed secret_key so that any unconfigured worker will use, so that # session can be used during setup even if multiple processes are # processing requests. self.config['SECRET_KEY'] = 'abilian_setup_key' # time to load config bits from database: 'settings' # First init required stuff: db to make queries, and settings service extensions.db.init_app(self) settings_service.init_app(self) if configured: with self.app_context(): try: settings = self.services['settings'].namespace('config').as_dict() except sa.exc.DatabaseError as exc: # we may get here if DB is not initialized and "settings" table is # missing. Command "initdb" must be run to initialize db, but first we # must pass app init if not self.testing: # durint tests this message will show up on every test, since db is # always recreated logging.error(exc.message) self.db.session.rollback() else: self.config.update(settings) if not self.config.get('FAVICO_URL'): self.config['FAVICO_URL'] = self.config.get('LOGO_URL') languages = self.config.get('BABEL_ACCEPT_LANGUAGES') if languages is None: languages = abilian.i18n.VALID_LANGUAGES_CODE else: languages = tuple(lang for lang in languages if lang in abilian.i18n.VALID_LANGUAGES_CODE) self.config['BABEL_ACCEPT_LANGUAGES'] = languages self._jinja_loaders = list() self.register_jinja_loaders( jinja2.PackageLoader('abilian.web', 'templates')) js_filters = (('closure_js',) if self.config.get('PRODUCTION', False) else None) self._assets_bundles = { 'css': {'options': dict(filters=('less', 'cssmin'), output='style-%(version)s.min.css',)}, 'js-top': {'options': dict(output='top-%(version)s.min.js', filters=js_filters,)}, 'js': {'options': dict(output='app-%(version)s.min.js', filters=js_filters)}, } # bundles for JS translations for lang in languages: code = 'js-i18n-' + lang filename = 'lang-' + lang + '-%(version)s.min.js' self._assets_bundles[code] = { 'options': dict(output=filename, filters=js_filters), } for http_error_code in (403, 404, 500): self.install_default_handler(http_error_code) with self.app_context(): self.init_extensions() self.register_plugins() self.add_access_controller('static', allow_access_for_roles(Anonymous), endpoint=True) # debugtoolbar: this is needed to have it when not authenticated on a # private site. We cannot do this in init_debug_toolbar, since auth # service is not yet installed self.add_access_controller('debugtoolbar', allow_access_for_roles(Anonymous),) self.add_access_controller('_debug_toolbar.static', allow_access_for_roles(Anonymous), endpoint=True) self.maybe_register_setup_wizard() self._finalize_assets_setup() # At this point all models should have been imported: time to configure # mappers. Normally Sqlalchemy does it when needed but mappers may be # configured inside sa.orm.class_mapper() which hides a misconfiguration: if # a mapper is misconfigured its exception is swallowed by # class_mapper(model) results in this laconic (and misleading) message: # "model is not mapped" sa.orm.configure_mappers() signals.components_registered.send(self) self.before_first_request(self._set_current_celery_app) self.before_first_request( lambda: signals.register_js_api.send(self) ) request_started.connect(self._setup_nav_and_breadcrumbs) # Initialize Abilian core services. # Must come after all entity classes have been declared. # Inherited from ServiceManager. Will need some configuration love later. if not self.config.get('TESTING', False): with self.app_context(): self.start_services()
def setup(self, config): self.configure(config) # At this point we have loaded all external config files: # SQLALCHEMY_DATABASE_URI is definitively fixed (it cannot be defined in # database AFAICT), and LOGGING_FILE cannot be set in DB settings. self.setup_logging() appcontext_pushed.connect(self.install_id_generator) if not self.testing: self.init_sentry() # time to load config bits from database: 'settings' # First init required stuff: db to make queries, and settings service extensions.db.init_app(self) settings_service.init_app(self) self.register_jinja_loaders(jinja2.PackageLoader("abilian.web")) self.init_assets() self.install_default_handlers() with self.app_context(): self.init_extensions() self.register_plugins() self.add_access_controller( "static", allow_access_for_roles(Anonymous), endpoint=True ) # debugtoolbar: this is needed to have it when not authenticated # on a private site. We cannot do this in init_debug_toolbar, # since auth service is not yet installed. self.add_access_controller( "debugtoolbar", allow_access_for_roles(Anonymous) ) self.add_access_controller( "_debug_toolbar.static", allow_access_for_roles(Anonymous), endpoint=True, ) # TODO: maybe reenable later # self.maybe_register_setup_wizard() self._finalize_assets_setup() # At this point all models should have been imported: time to configure # mappers. Normally Sqlalchemy does it when needed but mappers may be # configured inside sa.orm.class_mapper() which hides a # misconfiguration: if a mapper is misconfigured its exception is # swallowed by class_mapper(model) results in this laconic # (and misleading) message: "model is not mapped" sa.orm.configure_mappers() signals.components_registered.send(self) request_started.connect(self.setup_nav_and_breadcrumbs) init_hooks(self) # Initialize Abilian core services. # Must come after all entity classes have been declared. # Inherited from ServiceManager. Will need some configuration love # later. if not self.testing: with self.app_context(): self.start_services() setup(self)
def setup(self, config: Optional[type]) -> None: self.configure(config) # At this point we have loaded all external config files: # SQLALCHEMY_DATABASE_URI is definitively fixed (it cannot be defined in # database AFAICT), and LOGGING_FILE cannot be set in DB settings. self.setup_logging() appcontext_pushed.connect(self.install_id_generator) if not self.testing: self.init_sentry() # time to load config bits from database: 'settings' # First init required stuff: db to make queries, and settings service extensions.db.init_app(self) settings_service.init_app(self) self.register_jinja_loaders(jinja2.PackageLoader("abilian.web")) self.init_assets() self.install_default_handlers() with self.app_context(): self.init_extensions() self.register_plugins() self.add_access_controller("static", allow_access_for_roles(Anonymous), endpoint=True) # debugtoolbar: this is needed to have it when not authenticated # on a private site. We cannot do this in init_debug_toolbar, # since auth service is not yet installed. self.add_access_controller("debugtoolbar", allow_access_for_roles(Anonymous)) self.add_access_controller( "_debug_toolbar.static", allow_access_for_roles(Anonymous), endpoint=True, ) # TODO: maybe reenable later # self.maybe_register_setup_wizard() self._finalize_assets_setup() # At this point all models should have been imported: time to configure # mappers. Normally Sqlalchemy does it when needed but mappers may be # configured inside sa.orm.class_mapper() which hides a # misconfiguration: if a mapper is misconfigured its exception is # swallowed by class_mapper(model) results in this laconic # (and misleading) message: "model is not mapped" sa.orm.configure_mappers() signals.components_registered.send(self) request_started.connect(self.setup_nav_and_breadcrumbs) init_hooks(self) # Initialize Abilian core services. # Must come after all entity classes have been declared. # Inherited from ServiceManager. Will need some configuration love # later. if not self.testing: with self.app_context(): self.start_services() setup(self)