Esempio n. 1
0
def init_dbsessions(settings: dict, config: Configurator, health_check: HealthCheck=None) -> None:
    # define the srid, schema as global variables to be usable in the model
    global schema
    global srid
    srid = settings['srid']
    schema = settings['schema']

    db_chooser = settings.get('db_chooser', {})
    master_paths = [re.compile(i.replace('//', '/')) for i in db_chooser.get('master', [])]
    slave_paths = [re.compile(i.replace('//', '/')) for i in db_chooser.get('slave', [])]

    slave_prefix = 'sqlalchemy_slave' if 'sqlalchemy_slave.url' in settings else None

    c2cgeoportal_commons.models.DBSession, rw_bind, _ = c2cwsgiutils.db.setup_session(
        config, 'sqlalchemy', slave_prefix, force_master=master_paths, force_slave=slave_paths)
    c2cgeoportal_commons.models.Base.metadata.bind = rw_bind
    c2cgeoportal_commons.models.DBSessions['dbsession'] = c2cgeoportal_commons.models.DBSession

    for dbsession_name, dbsession_config in settings.get('dbsessions', {}).items():  # pragma: nocover
        c2cgeoportal_commons.models.DBSessions[dbsession_name] = \
            c2cwsgiutils.db.create_session(config, dbsession_name, **dbsession_config)

    Base.metadata.clear()
    from c2cgeoportal_commons.models import main

    if health_check is not None:
        for name, session in c2cgeoportal_commons.models.DBSessions.items():
            if name == 'dbsession':
                health_check.add_db_session_check(session, at_least_one_model=main.Theme)
            else:  # pragma: no cover
                def check(session: Session) -> None:
                    session.execute('SELECT 1')
                health_check.add_db_session_check(session, query_cb=check)
Esempio n. 2
0
def init_dbsessions(settings: dict,
                    config: Configurator,
                    health_check: HealthCheck = None) -> None:
    db_chooser = settings.get('db_chooser', {})
    master_paths = [
        re.compile(i.replace('//', '/')) for i in db_chooser.get('master', [])
    ]
    slave_paths = [
        re.compile(i.replace('//', '/')) for i in db_chooser.get('slave', [])
    ]

    slave_prefix = 'sqlalchemy_slave' if 'sqlalchemy_slave.url' in settings else None

    c2cgeoportal_commons.models.DBSession, rw_bind, _ = c2cwsgiutils.db.setup_session(
        config,
        'sqlalchemy',
        slave_prefix,
        force_master=master_paths,
        force_slave=slave_paths)
    c2cgeoportal_commons.models.Base.metadata.bind = rw_bind
    c2cgeoportal_commons.models.DBSessions[
        'dbsession'] = c2cgeoportal_commons.models.DBSession

    for dbsession_name, dbsession_config in settings.get(
            'dbsessions', {}).items():  # pragma: nocover
        c2cgeoportal_commons.models.DBSessions[dbsession_name] = \
            c2cwsgiutils.db.create_session(config, dbsession_name, **dbsession_config)

    c2cgeoportal_commons.models.Base.metadata.clear()
    from c2cgeoportal_commons.models import main

    if health_check is not None:
        for name, session in c2cgeoportal_commons.models.DBSessions.items():
            if name == 'dbsession':
                health_check.add_db_session_check(
                    session, at_least_one_model=main.Theme, level=1)
                alembic_ini = os.path.join(os.path.abspath(os.path.curdir),
                                           'alembic.ini')
                if os.path.exists(alembic_ini):
                    health_check.add_alembic_check(
                        session,
                        alembic_ini_path=alembic_ini,
                        name='main',
                        version_schema=settings['schema'],
                        level=1)
                    health_check.add_alembic_check(
                        session,
                        alembic_ini_path=alembic_ini,
                        name='static',
                        version_schema=settings['schema_static'],
                        level=1)
            else:  # pragma: no cover

                def check(session_: Session) -> None:
                    session_.execute('SELECT 1')

                health_check.add_db_session_check(session,
                                                  query_cb=check,
                                                  level=2)
Esempio n. 3
0
def main(_, **settings):
    config = Configurator(settings=settings,
                          route_prefix=os.environ.get("ROUTE_PREFIX", "/scm"))

    config.include(c2cwsgiutils.pyramid.includeme)
    config.scan("shared_config_manager.services")
    HealthCheck(config)
    sources.init(slave=False)
    return config.make_wsgi_app()
Esempio n. 4
0
def main(_, **settings):
    """
    This function returns a Pyramid WSGI application.
    """
    configuration.init(settings.get('app.cfg'))
    settings.update(configuration.get_config())

    config = Configurator(settings=settings)
    config.include('c2cwsgiutils.pyramid.includeme')

    config.include('c2cgeoportal_admin')

    from c2cgeoportal_commons.testing import (
        generate_mappers,
        get_engine,
        get_session_factory,
        get_tm_session,
    )

    # Initialize the dev dbsession
    settings = config.get_settings()
    settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'

    session_factory = get_session_factory(get_engine(settings))
    config.registry['dbsession_factory'] = session_factory

    # Make request.dbsession available for use in Pyramid
    config.add_request_method(
        # request.tm is the transaction manager used by pyramid_tm
        lambda request: get_tm_session(session_factory, request.tm),
        'dbsession',
        reify=True
    )

    config.add_subscriber(add_renderer_globals, BeforeRender)
    config.add_subscriber(add_localizer, NewRequest)

    generate_mappers()

    health_check = HealthCheck(config)
    health_check.add_url_check('http://{}/'.format(settings['healthcheck_host']))

    return config.make_wsgi_app()
Esempio n. 5
0
def main(_, **settings):
    """
    This function returns a Pyramid WSGI application.
    """
    settings.update(c2c.template.get_config(settings.get('app.cfg')))

    config = Configurator(settings=settings)
    config.include('c2cwsgiutils.pyramid.includeme')
    config.include('pyramid_jinja2')
    config.include('c2cgeoform')
    config.include('c2cgeoportal_commons')
    config.include(c2cgeoportal_admin.routes)
    config.scan()

    health_check = HealthCheck(config)
    health_check.add_url_check('http://{}/'.format(settings['healthcheck_host']))
    # health_check.add_alembic_check(models.DBSession, '/app/alembic.ini', 1)

    return config.make_wsgi_app()
Esempio n. 6
0
def init_dbsessions(settings: dict,
                    config: Configurator,
                    health_check: HealthCheck = None) -> None:
    db_chooser = settings.get('db_chooser', {})
    master_paths = [
        re.compile(i.replace('//', '/')) for i in db_chooser.get('master', [])
    ]
    slave_paths = [
        re.compile(i.replace('//', '/')) for i in db_chooser.get('slave', [])
    ]

    slave_prefix = 'sqlalchemy_slave' if 'sqlalchemy_slave.url' in settings else None

    c2cgeoportal_commons.models.DBSession, rw_bind, _ = c2cwsgiutils.db.setup_session(
        config,
        'sqlalchemy',
        slave_prefix,
        force_master=master_paths,
        force_slave=slave_paths)
    c2cgeoportal_commons.models.Base.metadata.bind = rw_bind
    c2cgeoportal_commons.models.DBSessions[
        'dbsession'] = c2cgeoportal_commons.models.DBSession

    for dbsession_name, dbsession_config in settings.get(
            'dbsessions', {}).items():  # pragma: nocover
        c2cgeoportal_commons.models.DBSessions[dbsession_name] = \
            c2cwsgiutils.db.create_session(config, dbsession_name, **dbsession_config)

    c2cgeoportal_commons.models.Base.metadata.clear()
    from c2cgeoportal_commons.models import main

    if health_check is not None:
        for name, session in c2cgeoportal_commons.models.DBSessions.items():
            if name == 'dbsession':
                health_check.add_db_session_check(
                    session, at_least_one_model=main.Theme)
            else:  # pragma: no cover

                def check(session: Session) -> None:
                    session.execute('SELECT 1')

                health_check.add_db_session_check(session, query_cb=check)
Esempio n. 7
0
def main(_, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(settings=settings,
                          route_prefix=os.environ.get('ROUTE_PREFIX', '/'))
    config.include(c2cwsgiutils.pyramid.includeme)
    config.add_route('ping', '/ping')
    config.add_route('upload', '/upload')
    config.add_route('publish', '/publish')
    config.add_route('recrop', '/recrop')
    config.add_route('delete', '/delete')
    config.add_static_view(name='active', path=os.environ['ACTIVE_FOLDER'])
    config.add_subscriber(add_cors_headers_response_callback, NewRequest)

    HealthCheck(config)

    config.scan("c2corg_images")

    return config.make_wsgi_app()
Esempio n. 8
0
def main(_, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(settings=settings, route_prefix="/api")

    # Initialise the broadcast view before c2cwsgiutils is initialised. This allows to test the
    # reconfiguration on the fly of the broadcast framework
    config.add_route("broadcast", r"/broadcast", request_method="GET")
    config.add_view(
        lambda request: broadcast_view(), route_name="broadcast", renderer="fast_json", http_cache=0
    )

    config.include(c2cwsgiutils.pyramid.includeme)
    models.init(config)
    config.scan("c2cwsgiutils_app.services")
    health_check = HealthCheck(config)
    health_check.add_db_session_check(models.DBSession, at_least_one_model=models.Hello)
    health_check.add_url_check("http://localhost:8080/api/hello")
    health_check.add_url_check(name="fun_url", url=lambda _request: "http://localhost:8080/api/hello")
    health_check.add_custom_check("fail", _failure, 2)
    health_check.add_custom_check("fail_json", _failure_json, 2)
    health_check.add_alembic_check(models.DBSession, "/app/alembic.ini", 1)

    return config.make_wsgi_app()
Esempio n. 9
0
def includeme(config: pyramid.config.Configurator):
    """
    This function returns a Pyramid WSGI application.
    """

    settings = config.get_settings()

    config.include("c2cgeoportal_commons")

    call_hook(settings, "after_settings", settings)

    get_user_from_request = create_get_user_from_request(settings)
    config.add_request_method(get_user_from_request,
                              name="user",
                              property=True)
    config.add_request_method(get_user_from_request, name="get_user")

    # Configure 'locale' dir as the translation dir for c2cgeoportal app
    config.add_translation_dirs("c2cgeoportal_geoportal:locale/")

    config.include('c2cwsgiutils.pyramid.includeme')
    health_check = HealthCheck(config)

    # Initialise DBSessions
    init_dbsessions(settings, config, health_check)

    # Initialize the dbreflection module
    dbreflection.init()

    checker.init(config, health_check)
    check_collector.init(config, health_check)

    # dogpile.cache configuration
    if 'cache' in settings:
        caching.init_region(settings['cache'])
        from c2cgeoportal_commons.models.main import InvalidateCacheEvent

        @zope.event.classhandler.handler(InvalidateCacheEvent)
        def handle(event: InvalidateCacheEvent):  # pylint: disable=unused-variable
            del event
            caching.invalidate_region()

    # Register a tween to get back the cache buster path.
    if 'cache_path' not in config.get_settings():
        config.get_settings()['cache_path'] = ['static']
    config.add_tween(
        "c2cgeoportal_geoportal.lib.cacheversion.CachebusterTween")
    config.add_tween("c2cgeoportal_geoportal.lib.headers.HeadersTween")

    # Bind the mako renderer to other file extensions
    add_mako_renderer(config, ".html")
    add_mako_renderer(config, ".js")

    # Add the "geojson" renderer
    config.add_renderer("geojson", GeoJSON())

    # Add decimal json renderer
    config.add_renderer("decimaljson", DecimalJSON())

    # Add the "xsd" renderer
    config.add_renderer("xsd", XSD(include_foreign_keys=True))

    # Add the set_user_validator directive, and set a default user validator
    config.add_directive("set_user_validator", set_user_validator)
    config.set_user_validator(default_user_validator)

    config.add_route('dynamic', '/dynamic.json', request_method="GET")

    # Add routes to the mapserver proxy
    config.add_route_predicate("mapserverproxy", MapserverproxyRoutePredicate)
    config.add_route("mapserverproxy",
                     "/mapserv_proxy",
                     mapserverproxy=True,
                     pregenerator=C2CPregenerator(role=True),
                     request_method="GET")
    config.add_route("mapserverproxy_post",
                     "/mapserv_proxy",
                     mapserverproxy=True,
                     pregenerator=C2CPregenerator(role=True),
                     request_method="POST")
    add_cors_route(config, "/mapserv_proxy", "mapserver")

    # Add route to the tinyows proxy
    config.add_route(
        "tinyowsproxy",
        "/tinyows_proxy",
        pregenerator=C2CPregenerator(role=True),
    )

    # Add routes to the entry view class
    config.add_route("base", "/", static=True)
    config.add_route("loginform", "/login.html", request_method="GET")
    add_cors_route(config, "/login", "login")
    config.add_route("login", "/login", request_method="POST")
    add_cors_route(config, "/logout", "login")
    config.add_route("logout", "/logout", request_method="GET")
    add_cors_route(config, "/loginchange", "login")
    config.add_route("loginchange", "/loginchange", request_method="POST")
    add_cors_route(config, "/loginresetpassword", "login")
    config.add_route("loginresetpassword",
                     "/loginresetpassword",
                     request_method="POST")
    add_cors_route(config, "/loginuser", "login")
    config.add_route("loginuser", "/loginuser", request_method="GET")
    config.add_route("testi18n", "/testi18n.html", request_method="GET")

    config.add_renderer(".map", AssetRendererFactory)
    config.add_renderer(".css", AssetRendererFactory)
    config.add_renderer(".ico", AssetRendererFactory)
    config.add_route("localejson", "/locale.json", request_method="GET")

    # Cannot be at the header to do not load the model too early
    from c2cgeoportal_geoportal.views.entry import Entry

    def add_api_route(name: str, attr: str, path: str, renderer: str):
        config.add_route(name, path, request_method="GET")
        config.add_view(Entry, attr=attr, route_name=name, renderer=renderer)

    add_api_route('favicon', 'favicon', '/favicon.ico',
                  '/etc/geomapfish/static/images/favicon.ico')
    add_api_route('apijs', 'apijs', '/api.js', "/etc/static-ngeo/api.js")
    add_api_route('apijsmap', 'apijsmap', '/api.js.map',
                  "/etc/static-ngeo/api.js.map")
    add_api_route('apicss', 'apicss', '/api.css', "/etc/static-ngeo/api.css")
    add_api_route('apihelp', 'apihelp', '/apihelp/index.html',
                  "/etc/geomapfish/static/apihelp/index.html")
    c2cgeoportal_geoportal.views.add_redirect(config, 'apihelp_redirect',
                                              '/apihelp.html',
                                              '/apihelp/index.html')

    config.add_route(
        "themes",
        "/themes",
        request_method="GET",
        pregenerator=C2CPregenerator(role=True),
    )

    config.add_route("invalidate", "/invalidate", request_method="GET")

    # Print proxy routes
    config.add_route("printproxy", "/printproxy", request_method="HEAD")
    add_cors_route(config, "/printproxy/*all", "print")
    config.add_route(
        "printproxy_capabilities",
        "/printproxy/capabilities.json",
        request_method="GET",
        pregenerator=C2CPregenerator(role=True),
    )
    config.add_route("printproxy_report_create",
                     "/printproxy/report.{format}",
                     request_method="POST",
                     header=JSON_CONTENT_TYPE)
    config.add_route("printproxy_status",
                     "/printproxy/status/{ref}.json",
                     request_method="GET")
    config.add_route("printproxy_cancel",
                     "/printproxy/cancel/{ref}",
                     request_method="DELETE")
    config.add_route("printproxy_report_get",
                     "/printproxy/report/{ref}",
                     request_method="GET")

    # Full-text search routes
    add_cors_route(config, "/search", "fulltextsearch")
    config.add_route("fulltextsearch", "/search", request_method="GET")

    # Access to raster data
    add_cors_route(config, "/raster", "raster")
    config.add_route("raster", "/raster", request_method="GET")

    add_cors_route(config, "/profile.json", "profile")
    config.add_route("profile.json", "/profile.json", request_method="POST")

    # Shortener
    add_cors_route(config, "/short/create", "shortener")
    config.add_route("shortener_create",
                     "/short/create",
                     request_method="POST")
    config.add_route("shortener_get", "/s/{ref}", request_method="GET")

    # Geometry processing
    config.add_route("difference", "/difference", request_method="POST")

    # PDF report tool
    config.add_route("pdfreport",
                     "/pdfreport/{layername}/{ids}",
                     request_method="GET")

    # Add routes for the "layers" web service
    add_cors_route(config, "/layers/*all", "layers")
    config.add_route("layers_count",
                     "/layers/{layer_id:\\d+}/count",
                     request_method="GET")
    config.add_route(
        "layers_metadata",
        "/layers/{layer_id:\\d+}/md.xsd",
        request_method="GET",
        pregenerator=C2CPregenerator(role=True),
    )
    config.add_route("layers_read_many",
                     "/layers/{layer_id:\\d+,?(\\d+,)*\\d*$}",
                     request_method="GET")  # supports URLs like /layers/1,2,3
    config.add_route("layers_read_one",
                     "/layers/{layer_id:\\d+}/{feature_id}",
                     request_method="GET")
    config.add_route("layers_create",
                     "/layers/{layer_id:\\d+}",
                     request_method="POST",
                     header=GEOJSON_CONTENT_TYPE)
    config.add_route("layers_update",
                     "/layers/{layer_id:\\d+}/{feature_id}",
                     request_method="PUT",
                     header=GEOJSON_CONTENT_TYPE)
    config.add_route("layers_delete",
                     "/layers/{layer_id:\\d+}/{feature_id}",
                     request_method="DELETE")
    config.add_route(
        "layers_enumerate_attribute_values",
        "/layers/{layer_name}/values/{field_name}",
        request_method="GET",
        pregenerator=C2CPregenerator(),
    )
    # There is no view corresponding to that route, it is to be used from
    # mako templates to get the root of the "layers" web service
    config.add_route("layers_root", "/layers", request_method="HEAD")

    # Resource proxy (load external url, useful when loading non https content)
    config.add_route("resourceproxy", "/resourceproxy", request_method="GET")

    # Dev
    config.add_route("dev", "/dev/*path", request_method="GET")

    # Used memory in caches
    config.add_route("memory", "/memory", request_method="GET")

    # Scan view decorator for adding routes
    config.scan(ignore=[
        "c2cgeoportal_geoportal.lib", "c2cgeoportal_geoportal.scaffolds",
        "c2cgeoportal_geoportal.scripts"
    ])

    add_admin_interface(config)

    # Add the project static view with cache buster
    from c2cgeoportal_geoportal.lib.cacheversion import version_cache_buster
    config.add_static_view(
        name="static",
        path="/etc/geomapfish/static",
        cache_max_age=int(config.get_settings()["default_max_age"]),
    )
    config.add_cache_buster("/etc/geomapfish/static", version_cache_buster)

    # Add the project static view without cache buster
    config.add_static_view(
        name="static-ngeo",
        path="/etc/static-ngeo",
        cache_max_age=int(config.get_settings()["default_max_age"]),
    )

    # Handles the other HTTP errors raised by the views. Without that,
    # the client receives a status=200 without content.
    config.add_view(error_handler, context=HTTPException)

    c2cwsgiutils.index.additional_title = '<div class="row"><div class="col-lg-3"><h2>GeoMapFish</h2>' \
        '</div><div class="col-lg">'
    c2cwsgiutils.index.additional_auth.extend([
        '<a href="../tiles/admin/">TileCloud chain admin</a><br>',
        '<a href="../tiles/c2c/">TileCloud chain c2c tools</a><br>',
        '<a href="../invalidate">Invalidate the cache</a><br>',
        '<a href="../memory">Memory status</a><br>',
    ])
    if config.get_settings().get('enable_admin_interface', False):
        c2cwsgiutils.index.additional_noauth.append(
            '<a href="../admin/">Admin</a><br>')

    c2cwsgiutils.index.additional_noauth.append(
        '</div></div><div class="row"><div class="col-lg-3"><h3>Interfaces</h3></div><div class="col-lg">'
    )
    c2cwsgiutils.index.additional_noauth.append(
        '<a href="../">Default</a><br>')
    for interface in config.get_settings().get("interfaces", []):
        if not interface.get('default', False):
            c2cwsgiutils.index.additional_noauth.append(
                '<a href="../{interface}">{interface}</a><br>'.format(
                    interface=interface['name']))
    c2cwsgiutils.index.additional_noauth.append(
        '<a href="../apihelp/index.html">API help</a><br>')
    c2cwsgiutils.index.additional_noauth.append('</div></div><hr>')
Esempio n. 10
0
def includeme(config):
    """
    This function returns a Pyramid WSGI application.
    """

    settings = config.get_settings()

    config.include("c2cgeoportal_commons")

    call_hook(settings, "after_settings", settings)

    get_user_from_request = create_get_user_from_request(settings)
    config.add_request_method(get_user_from_request,
                              name="user",
                              property=True)
    config.add_request_method(get_user_from_request, name="get_user")

    # Configure 'locale' dir as the translation dir for c2cgeoportal app
    config.add_translation_dirs("c2cgeoportal_geoportal:locale/")

    config.include('c2cwsgiutils.pyramid.includeme')
    health_check = HealthCheck(config)

    # Initialise DBSessions
    init_dbsessions(settings, config, health_check)

    # Initialize the dbreflection module
    dbreflection.init()

    checker.init(config, health_check)
    check_collector.init(config, health_check)

    config.include("pyramid_closure")

    # dogpile.cache configuration
    if 'cache' in settings:
        caching.init_region(settings['cache'])
        from c2cgeoportal_commons.models.main import InvalidateCacheEvent

        @zope.event.classhandler.handler(InvalidateCacheEvent)
        def handle(event: InvalidateCacheEvent):
            del event
            caching.invalidate_region()

    # Register a tween to get back the cache buster path.
    config.add_tween(
        "c2cgeoportal_geoportal.lib.cacheversion.CachebusterTween")

    # Bind the mako renderer to other file extensions
    add_mako_renderer(config, ".html")
    add_mako_renderer(config, ".js")

    # Add the "geojson" renderer
    config.add_renderer("geojson", GeoJSON())

    # Add decimal json renderer
    config.add_renderer("decimaljson", DecimalJSON())

    # Add the "xsd" renderer
    config.add_renderer(
        "xsd", XSD(sequence_callback=dbreflection.xsd_sequence_callback))

    # Add the set_user_validator directive, and set a default user validator
    config.add_directive("set_user_validator", set_user_validator)
    config.set_user_validator(default_user_validator)

    if settings.get("ogcproxy_enable", False):  # pragma: no cover
        # Add an OGCProxy view
        config.add_route_predicate("ogc_server", OgcproxyRoutePredicate)
        config.add_route("ogcproxy", "/ogcproxy", ogc_server=True)
        config.add_view("papyrus_ogcproxy.views:ogcproxy",
                        route_name="ogcproxy")

    # Add routes to the mapserver proxy
    config.add_route_predicate("mapserverproxy", MapserverproxyRoutePredicate)
    config.add_route(
        "mapserverproxy",
        "/mapserv_proxy",
        mapserverproxy=True,
        pregenerator=C2CPregenerator(role=True),
    )

    # Add route to the tinyows proxy
    config.add_route(
        "tinyowsproxy",
        "/tinyows_proxy",
        pregenerator=C2CPregenerator(role=True),
    )

    # Add routes to csv view
    config.add_route("csvecho", "/csv", request_method="POST")

    # Add route to the export GPX/KML view
    config.add_route("exportgpxkml", "/exportgpxkml")

    # Add routes to the echo service
    config.add_route("echo", "/echo", request_method="POST")

    # Add routes to the entry view class
    config.add_route("base", "/", static=True)
    config.add_route("loginform", "/login.html", request_method="GET")
    add_cors_route(config, "/login", "login")
    config.add_route("login", "/login", request_method="POST")
    add_cors_route(config, "/logout", "login")
    config.add_route("logout", "/logout", request_method="GET")
    add_cors_route(config, "/loginchange", "login")
    config.add_route("loginchange", "/loginchange", request_method="POST")
    add_cors_route(config, "/loginresetpassword", "login")
    config.add_route("loginresetpassword",
                     "/loginresetpassword",
                     request_method="POST")
    add_cors_route(config, "/loginuser", "login")
    config.add_route("loginuser", "/loginuser", request_method="GET")
    config.add_route("testi18n", "/testi18n.html", request_method="GET")
    config.add_route("apijs", "/api.js", request_method="GET")
    config.add_route("xapijs", "/xapi.js", request_method="GET")
    config.add_route("apihelp", "/apihelp.html", request_method="GET")
    config.add_route("xapihelp", "/xapihelp.html", request_method="GET")
    config.add_route(
        "themes",
        "/themes",
        request_method="GET",
        pregenerator=C2CPregenerator(role=True),
    )
    config.add_route("invalidate", "/invalidate", request_method="GET")

    # Print proxy routes
    config.add_route("printproxy", "/printproxy", request_method="HEAD")
    add_cors_route(config, "/printproxy/*all", "print")
    config.add_route(
        "printproxy_capabilities",
        "/printproxy/capabilities.json",
        request_method="GET",
        pregenerator=C2CPregenerator(role=True),
    )
    config.add_route("printproxy_report_create",
                     "/printproxy/report.{format}",
                     request_method="POST",
                     header=JSON_CONTENT_TYPE)
    config.add_route("printproxy_status",
                     "/printproxy/status/{ref}.json",
                     request_method="GET")
    config.add_route("printproxy_cancel",
                     "/printproxy/cancel/{ref}",
                     request_method="DELETE")
    config.add_route("printproxy_report_get",
                     "/printproxy/report/{ref}",
                     request_method="GET")
    # For v2
    config.add_route(
        "printproxy_info",
        "/printproxy/info.json",
        request_method="GET",
        pregenerator=C2CPregenerator(role=True),
    )
    config.add_route(
        "printproxy_create",
        "/printproxy/create.json",
        request_method="POST",
    )
    config.add_route(
        "printproxy_get",
        "/printproxy/{file}.printout",
        request_method="GET",
    )

    # Full-text search routes
    add_cors_route(config, "/fulltextsearch", "fulltextsearch")
    config.add_route("fulltextsearch", "/fulltextsearch")

    # Access to raster data
    add_cors_route(config, "/raster", "raster")
    config.add_route("raster", "/raster", request_method="GET")

    add_cors_route(config, "/profile.{ext}", "profile")
    config.add_route("profile.csv", "/profile.csv", request_method="POST")
    config.add_route("profile.json", "/profile.json", request_method="POST")

    # Shortener
    add_cors_route(config, "/short/create", "shortener")
    config.add_route("shortener_create",
                     "/short/create",
                     request_method="POST")
    config.add_route("shortener_get", "/short/{ref}", request_method="GET")

    # Geometry processing
    config.add_route("difference", "/difference", request_method="POST")

    # PDF report tool
    config.add_route("pdfreport",
                     "/pdfreport/{layername}/{ids}",
                     request_method="GET")

    # Add routes for the "layers" web service
    add_cors_route(config, "/layers/*all", "layers")
    config.add_route("layers_count",
                     "/layers/{layer_id:\\d+}/count",
                     request_method="GET")
    config.add_route(
        "layers_metadata",
        "/layers/{layer_id:\\d+}/md.xsd",
        request_method="GET",
        pregenerator=C2CPregenerator(role=True),
    )
    config.add_route("layers_read_many",
                     "/layers/{layer_id:\\d+,?(\\d+,)*\\d*$}",
                     request_method="GET")  # supports URLs like /layers/1,2,3
    config.add_route("layers_read_one",
                     "/layers/{layer_id:\\d+}/{feature_id}",
                     request_method="GET")
    config.add_route("layers_create",
                     "/layers/{layer_id:\\d+}",
                     request_method="POST",
                     header=JSON_CONTENT_TYPE)
    config.add_route("layers_update",
                     "/layers/{layer_id:\\d+}/{feature_id}",
                     request_method="PUT",
                     header=JSON_CONTENT_TYPE)
    config.add_route("layers_delete",
                     "/layers/{layer_id:\\d+}/{feature_id}",
                     request_method="DELETE")
    config.add_route(
        "layers_enumerate_attribute_values",
        "/layers/{layer_name}/values/{field_name}",
        request_method="GET",
        pregenerator=C2CPregenerator(),
    )
    # There is no view corresponding to that route, it is to be used from
    # mako templates to get the root of the "layers" web service
    config.add_route("layers_root", "/layers/", request_method="HEAD")

    # Resource proxy (load external url, useful when loading non https content)
    config.add_route("resourceproxy", "/resourceproxy", request_method="GET")

    # Scan view decorator for adding routes
    config.scan(ignore=[
        "c2cgeoportal_geoportal.scripts", "c2cgeoportal_geoportal.wsgi_app"
    ])

    if "subdomains" in settings:  # pragma: no cover
        config.registry.registerUtility(MultiDomainStaticURLInfo(),
                                        IStaticURLInfo)

    # Add the static view (for static resources)
    _add_static_view(config, "static", "c2cgeoportal_geoportal:static")
    _add_static_view(config, "project", "c2cgeoportal_geoportal:project")

    add_admin_interface(config)
    add_static_view(config)

    # Handles the other HTTP errors raised by the views. Without that,
    # the client receives a status=200 without content.
    config.add_view(error_handler, context=HTTPException)
Esempio n. 11
0
def init_dbsessions(settings: dict,
                    config: Configurator,
                    health_check: HealthCheck = None) -> None:
    db_chooser = settings.get("db_chooser", {})
    master_paths = [
        re.compile(i.replace("//", "/")) for i in db_chooser.get("master", [])
    ]
    slave_paths = [
        re.compile(i.replace("//", "/")) for i in db_chooser.get("slave", [])
    ]

    slave_prefix = "sqlalchemy_slave" if "sqlalchemy_slave.url" in settings else None

    c2cgeoportal_commons.models.DBSession, rw_bind, _ = c2cwsgiutils.db.setup_session(
        config,
        "sqlalchemy",
        slave_prefix,
        force_master=master_paths,
        force_slave=slave_paths)
    c2cgeoportal_commons.models.Base.metadata.bind = rw_bind
    c2cgeoportal_commons.models.DBSessions[
        "dbsession"] = c2cgeoportal_commons.models.DBSession

    for dbsession_name, dbsession_config in settings.get(
            "dbsessions", {}).items():  # pragma: nocover
        c2cgeoportal_commons.models.DBSessions[
            dbsession_name] = c2cwsgiutils.db.create_session(
                config, dbsession_name, **dbsession_config)

    c2cgeoportal_commons.models.Base.metadata.clear()
    from c2cgeoportal_commons.models import main  # pylint: disable=import-outside-toplevel

    if health_check is not None:
        for name, session in c2cgeoportal_commons.models.DBSessions.items():
            if name == "dbsession":
                health_check.add_db_session_check(
                    session, at_least_one_model=main.Theme, level=1)
                alembic_ini = os.path.join(os.path.abspath(os.path.curdir),
                                           "alembic.ini")
                if os.path.exists(alembic_ini):
                    health_check.add_alembic_check(
                        session,
                        alembic_ini_path=alembic_ini,
                        name="main",
                        version_schema=settings["schema"],
                        level=1,
                    )
                    health_check.add_alembic_check(
                        session,
                        alembic_ini_path=alembic_ini,
                        name="static",
                        version_schema=settings["schema_static"],
                        level=1,
                    )
            else:  # pragma: no cover

                def check(session_: Session) -> None:
                    session_.execute("SELECT 1")

                health_check.add_db_session_check(session,
                                                  query_cb=check,
                                                  level=2)
Esempio n. 12
0
def includeme(config: pyramid.config.Configurator) -> None:
    """Get the Pyramid WSGI application."""
    settings = config.get_settings()

    if "available_locale_names" not in settings:
        settings["available_locale_names"] = available_locale_names()

    call_hook(settings, "after_settings", settings)

    get_user_from_request = create_get_user_from_request(settings)
    config.add_request_method(get_user_from_request,
                              name="user",
                              property=True)
    config.add_request_method(get_user_from_request, name="get_user")
    # Be able for an organization to override the method to use alternate:
    # - Organization roles name for the standard roles 'anonymous', 'registered' and 'intranet'.
    config.add_request_method(lambda request, role_type: role_type,
                              name="get_organization_role")
    # - Organization print URL
    config.add_request_method(
        lambda request: request.registry.settings["print_url"],
        name="get_organization_print_url")
    # - Organization interface name (in the config and in the admin interface)
    config.add_request_method(lambda request, interface: interface,
                              name="get_organization_interface")

    # Configure 'locale' dir as the translation dir for c2cgeoportal app
    config.add_translation_dirs("c2cgeoportal_geoportal:locale/")

    config.include("pyramid_mako")
    config.include("c2cwsgiutils.pyramid.includeme")
    health_check = HealthCheck(config)
    config.registry["health_check"] = health_check

    metrics_config = config.registry.settings["metrics"]
    if metrics_config["memory_maps_rss"]:
        add_provider(MemoryMapProvider("rss"))
    if metrics_config["memory_maps_size"]:
        add_provider(MemoryMapProvider("size"))
    if metrics_config["memory_cache"]:
        add_provider(
            MemoryCacheSizeProvider(
                metrics_config.get("memory_cache_all", False)))
    if metrics_config["raster_data"]:
        add_provider(RasterDataSizeProvider())
    if metrics_config["total_python_object_memory"]:
        add_provider(TotalPythonObjectMemoryProvider())

    # Initialise DBSessions
    init_db_sessions(settings, config, health_check)

    checker.init(config, health_check)
    check_collector.init(config, health_check)

    # dogpile.cache configuration
    if "cache" in settings:
        register_backend("c2cgeoportal.hybrid",
                         "c2cgeoportal_geoportal.lib.caching",
                         "HybridRedisBackend")
        register_backend("c2cgeoportal.hybridsentinel",
                         "c2cgeoportal_geoportal.lib.caching",
                         "HybridRedisSentinelBackend")
        for name, cache_config in settings["cache"].items():
            caching.init_region(cache_config, name)

            @zope.event.classhandler.handler(InvalidateCacheEvent
                                             )  # type: ignore
            def handle(event: InvalidateCacheEvent) -> None:
                del event
                caching.invalidate_region()
                if caching.MEMORY_CACHE_DICT:
                    caching.get_region("std").delete_multi(
                        list(caching.MEMORY_CACHE_DICT.keys()))
                caching.MEMORY_CACHE_DICT.clear()

    # Register a tween to get back the cache buster path.
    if "cache_path" not in config.get_settings():
        config.get_settings()["cache_path"] = ["static", "static-geomapfish"]
    config.add_tween(
        "c2cgeoportal_geoportal.lib.cacheversion.CachebusterTween")
    config.add_tween("c2cgeoportal_geoportal.lib.headers.HeadersTween")

    # Bind the mako renderer to other file extensions
    add_mako_renderer(config, ".html")
    add_mako_renderer(config, ".js")

    # Add the "geojson" renderer
    config.add_renderer("geojson", GeoJSON())

    # Add the "xsd" renderer
    config.add_renderer("xsd", XSD(include_foreign_keys=True))

    # Add the set_user_validator directive, and set a default user validator
    config.add_directive("set_user_validator", set_user_validator)
    config.set_user_validator(default_user_validator)

    config.add_route("oauth2token", "/oauth/token", request_method="POST")
    config.add_route("oauth2loginform", "/oauth/login", request_method="GET")
    config.add_route("notlogin", "/notlogin", request_method="GET")

    config.add_route("dynamic", "/dynamic.json", request_method="GET")

    # Add routes to the mapserver proxy
    config.add_route_predicate("mapserverproxy", MapserverproxyRoutePredicate)
    config.add_route(
        "mapserverproxy",
        "/mapserv_proxy",
        mapserverproxy=True,
        pregenerator=C2CPregenerator(role=True),
        request_method="GET",
    )
    config.add_route(
        "mapserverproxy_post",
        "/mapserv_proxy",
        mapserverproxy=True,
        pregenerator=C2CPregenerator(role=True),
        request_method="POST",
    )
    # The tow next views are used to serve the application on the URL /mapserv_proxy/<ogc server name>
    # instead of /mapserv_proxy?ogcserver=<ogc server name>, required for QGIS server landing page
    config.add_route(
        "mapserverproxy_get_path",
        "/mapserv_proxy/{ogcserver}/*path",
        mapserverproxy=True,
        pregenerator=C2CPregenerator(role=True),
        request_method="GET",
    )
    config.add_route(
        "mapserverproxy_post_path",
        "/mapserv_proxy/{ogcserver}/*path",
        mapserverproxy=True,
        pregenerator=C2CPregenerator(role=True),
        request_method="POST",
    )
    add_cors_route(config, "/mapserv_proxy", "mapserver")

    # Add route to the tinyows proxy
    config.add_route("tinyowsproxy",
                     "/tinyows_proxy",
                     pregenerator=C2CPregenerator(role=True))

    # Add routes to the entry view class
    config.add_route("base", "/", static=True)
    config.add_route("loginform", "/login.html", request_method="GET")
    add_cors_route(config, "/login", "login")
    config.add_route("login", "/login", request_method="POST")
    add_cors_route(config, "/logout", "login")
    config.add_route("logout", "/logout", request_method="GET")
    add_cors_route(config, "/loginchangepassword", "login")
    config.add_route("change_password",
                     "/loginchangepassword",
                     request_method="POST")
    add_cors_route(config, "/loginresetpassword", "login")
    config.add_route("loginresetpassword",
                     "/loginresetpassword",
                     request_method="POST")
    add_cors_route(config, "/loginuser", "login")
    config.add_route("loginuser", "/loginuser", request_method="GET")
    config.add_route("testi18n", "/testi18n.html", request_method="GET")

    config.add_renderer(".map", AssetRendererFactory)
    config.add_renderer(".css", AssetRendererFactory)
    config.add_renderer(".ico", AssetRendererFactory)
    config.add_route("localejson", "/locale.json", request_method="GET")
    config.add_route("localepot", "/locale.pot", request_method="GET")

    def add_static_route(name: str, attr: str, path: str,
                         renderer: str) -> None:
        config.add_route(name, path, request_method="GET")
        config.add_view(Entry, attr=attr, route_name=name, renderer=renderer)

    add_static_route("favicon", "favicon", "/favicon.ico",
                     "/etc/geomapfish/static/images/favicon.ico")
    add_static_route("robot.txt", "robot_txt", "/robot.txt",
                     "/etc/geomapfish/static/robot.txt")
    config.add_route("apijs", "/api.js", request_method="GET")
    add_static_route("apijsmap", "apijsmap", "/api.js.map",
                     "/etc/static-ngeo/api.js.map")
    add_static_route("apicss", "apicss", "/api.css",
                     "/etc/static-ngeo/api.css")
    add_static_route("apihelp", "apihelp", "/apihelp/index.html",
                     "/etc/geomapfish/static/apihelp/index.html")
    c2cgeoportal_geoportal.views.add_redirect(config, "apihelp_redirect",
                                              "/apihelp.html", "apihelp")

    config.add_route("themes",
                     "/themes",
                     request_method="GET",
                     pregenerator=C2CPregenerator(role=True))

    config.add_route("invalidate", "/invalidate", request_method="GET")

    # Print proxy routes
    config.add_route("printproxy", "/printproxy", request_method="HEAD")
    add_cors_route(config, "/printproxy/*all", "print")
    config.add_route(
        "printproxy_capabilities",
        "/printproxy/capabilities.json",
        request_method="GET",
        pregenerator=C2CPregenerator(role=True),
    )
    config.add_route(
        "printproxy_report_create",
        "/printproxy/report.{format}",
        request_method="POST",
        header=JSON_CONTENT_TYPE,
    )
    config.add_route("printproxy_status",
                     "/printproxy/status/{ref}.json",
                     request_method="GET")
    config.add_route("printproxy_cancel",
                     "/printproxy/cancel/{ref}",
                     request_method="DELETE")
    config.add_route("printproxy_report_get",
                     "/printproxy/report/{ref}",
                     request_method="GET")

    # Full-text search routes
    add_cors_route(config, "/search", "fulltextsearch")
    config.add_route("fulltextsearch", "/search", request_method="GET")

    # Access to raster data
    add_cors_route(config, "/raster", "raster")
    config.add_route("raster", "/raster", request_method="GET")

    add_cors_route(config, "/profile.json", "profile")
    config.add_route("profile.json", "/profile.json", request_method="POST")

    # Access to vector tiles
    add_cors_route(config, "/vector_tiles", "vector_tiles")
    config.add_route("vector_tiles",
                     "/vector_tiles/{layer_name}/{z}/{x}/{y}.pbf",
                     request_method="GET")
    # There is no view corresponding to that route, it is to be used from
    # mako templates to get the root of the "vector_tiles" web service
    config.add_route("vector_tiles_root",
                     "/vector_tiles",
                     request_method="HEAD")

    # Shortener
    add_cors_route(config, "/short/create", "shortener")
    config.add_route("shortener_create",
                     "/short/create",
                     request_method="POST")
    config.add_route("shortener_get", "/s/{ref}", request_method="GET")

    # Geometry processing
    config.add_route("difference", "/difference", request_method="POST")

    # PDF report tool
    config.add_route("pdfreport",
                     "/pdfreport/{layername}/{ids}",
                     request_method="GET")

    # Add routes for the "layers" web service
    add_cors_route(config, "/layers/*all", "layers")
    config.add_route("layers_count",
                     "/layers/{layer_id:\\d+}/count",
                     request_method="GET")
    config.add_route(
        "layers_metadata",
        "/layers/{layer_id:\\d+}/md.xsd",
        request_method="GET",
        pregenerator=C2CPregenerator(role=True),
    )
    config.add_route("layers_read_many",
                     "/layers/{layer_id:\\d+,?(\\d+,)*\\d*$}",
                     request_method="GET")  # supports URLs like /layers/1,2,3
    config.add_route("layers_read_one",
                     "/layers/{layer_id:\\d+}/{feature_id}",
                     request_method="GET")
    config.add_route("layers_create",
                     "/layers/{layer_id:\\d+}",
                     request_method="POST",
                     header=GEOJSON_CONTENT_TYPE)
    config.add_route(
        "layers_update",
        "/layers/{layer_id:\\d+}/{feature_id}",
        request_method="PUT",
        header=GEOJSON_CONTENT_TYPE,
    )
    config.add_route("layers_delete",
                     "/layers/{layer_id:\\d+}/{feature_id}",
                     request_method="DELETE")
    config.add_route(
        "layers_enumerate_attribute_values",
        "/layers/{layer_name}/values/{field_name}",
        request_method="GET",
        pregenerator=C2CPregenerator(),
    )
    # There is no view corresponding to that route, it is to be used from
    # mako templates to get the root of the "layers" web service
    config.add_route("layers_root", "/layers", request_method="HEAD")

    # Resource proxy (load external url, useful when loading non https content)
    config.add_route("resourceproxy", "/resourceproxy", request_method="GET")

    # Dev
    config.add_route("dev", "/dev/*path", request_method="GET")

    # Used memory in caches
    config.add_route("memory", "/memory", request_method="GET")

    # Scan view decorator for adding routes
    config.scan(ignore=[
        "c2cgeoportal_geoportal.lib",
        "c2cgeoportal_geoportal.scaffolds",
        "c2cgeoportal_geoportal.scripts",
    ])

    add_admin_interface(config)
    add_getitfixed(config)

    # Add the project static view with cache buster
    config.add_static_view(
        name="static",
        path="/etc/geomapfish/static",
        cache_max_age=int(config.get_settings()["default_max_age"]),
    )
    config.add_cache_buster("/etc/geomapfish/static", version_cache_buster)

    # Add the project static view without cache buster
    config.add_static_view(
        name="static-ngeo",
        path="/etc/static-ngeo",
        cache_max_age=int(config.get_settings()["default_max_age"]),
    )

    # Add the c2cgeoportal static view with cache buster
    config.add_static_view(
        name="static-geomapfish",
        path="c2cgeoportal_geoportal:static",
        cache_max_age=int(config.get_settings()["default_max_age"]),
    )
    config.add_cache_buster("c2cgeoportal_geoportal:static",
                            version_cache_buster)

    # Add the project static view without cache buster
    config.add_static_view(
        name="static-ngeo-dist",
        path="/opt/c2cgeoportal/geoportal/node_modules/ngeo/dist",
        cache_max_age=int(config.get_settings()["default_max_age"]),
    )

    # Handles the other HTTP errors raised by the views. Without that,
    # the client receives a status=200 without content.
    config.add_view(error_handler, context=HTTPException)

    c2cwsgiutils.index.additional_title = (
        '<div class="row"><div class="col-lg-3"><h2>GeoMapFish</h2></div><div class="col-lg">'
    )

    c2cwsgiutils.index.additional_auth.extend([
        '<a href="../tiles/admin/">TileCloud chain admin</a><br>',
        '<a href="../tiles/c2c/">TileCloud chain c2c tools</a><br>',
        '<a href="../invalidate">Invalidate the cache</a><br>',
        '<a href="../memory">Memory status</a><br>',
    ])
    if config.get_settings().get("enable_admin_interface", False):
        c2cwsgiutils.index.additional_noauth.append(
            '<a href="../admin/">Admin</a><br>')

    c2cwsgiutils.index.additional_noauth.append(
        '</div></div><div class="row"><div class="col-lg-3"><h3>Interfaces</h3></div><div class="col-lg">'
    )
    c2cwsgiutils.index.additional_noauth.append(
        '<a href="../">Default</a><br>')
    for interface in config.get_settings().get("interfaces", []):
        if not interface.get("default", False):
            c2cwsgiutils.index.additional_noauth.append(
                '<a href="../{interface}">{interface}</a><br>'.format(
                    interface=interface["name"]))
    c2cwsgiutils.index.additional_noauth.append(
        '<a href="../apihelp/index.html">API help</a><br>')
    c2cwsgiutils.index.additional_noauth.append("</div></div><hr>")