예제 #1
0
def test_large_json_request(sentry_init, capture_events, route, get_client):
    sentry_init(integrations=[PyramidIntegration()])

    data = {"foo": {"bar": "a" * 2000}}

    @route("/")
    def index(request):
        assert request.json == data
        assert request.text == json.dumps(data)
        assert not request.POST
        capture_message("hi")
        return Response("ok")

    events = capture_events()

    client = get_client()
    client.post("/", content_type="application/json", data=json.dumps(data))

    event, = events
    assert event["_meta"]["request"]["data"]["foo"]["bar"] == {
        "": {
            "len": 2000,
            "rem": [["!limit", "x", 509, 512]]
        }
    }
    assert len(event["request"]["data"]["foo"]["bar"]) == 512
예제 #2
0
def test_files_and_form(sentry_init, capture_events, route, get_client):
    sentry_init(integrations=[PyramidIntegration()], request_bodies="always")

    data = {"foo": "a" * 2000, "file": (BytesIO(b"hello"), "hello.txt")}

    @route("/")
    def index(request):
        capture_message("hi")
        return Response("ok")

    events = capture_events()

    client = get_client()
    client.post("/", data=data)

    event, = events
    assert event["_meta"]["request"]["data"]["foo"] == {
        "": {"len": 2000, "rem": [["!limit", "x", 509, 512]]}
    }
    assert len(event["request"]["data"]["foo"]) == 512

    assert event["_meta"]["request"]["data"]["file"] == {
        "": {"len": 0, "rem": [["!raw", "x", 0, 0]]}
    }
    assert not event["request"]["data"]["file"]
예제 #3
0
def test_has_context(route, get_client, sentry_init, capture_events):
    sentry_init(integrations=[PyramidIntegration()])
    events = capture_events()

    @route("/message/{msg}")
    def hi2(request):
        capture_message(request.matchdict["msg"])
        return Response("hi")

    client = get_client()
    client.get("/message/yoo")

    event, = events
    assert event["message"] == "yoo"
    assert event["request"] == {
        "env": {
            "SERVER_NAME": "localhost",
            "SERVER_PORT": "80"
        },
        "headers": {
            "Content-Length": "0",
            "Content-Type": "",
            "Host": "localhost"
        },
        "method": "GET",
        "query_string": "",
        "url": "http://localhost/message/yoo",
    }
    assert event["transaction"] == "hi2"
예제 #4
0
def test_view_exceptions(
    get_client, route, sentry_init, capture_events, capture_exceptions
):
    sentry_init(integrations=[PyramidIntegration()])
    events = capture_events()
    exceptions = capture_exceptions()

    add_breadcrumb({"message": "hi"})

    @route("/errors")
    def errors(request):
        add_breadcrumb({"message": "hi2"})
        1 / 0

    client = get_client()
    with pytest.raises(ZeroDivisionError):
        client.get("/errors")

    error, = exceptions
    assert isinstance(error, ZeroDivisionError)

    event, = events
    breadcrumb, = event["breadcrumbs"]
    assert breadcrumb["message"] == "hi2"
    assert event["exception"]["values"][0]["mechanism"]["type"] == "pyramid"
예제 #5
0
def test_error_in_errorhandler(
    sentry_init, pyramid_config, capture_events, route, get_client
):
    sentry_init(integrations=[PyramidIntegration()])

    @route("/")
    def index(request):
        raise ValueError()

    def error_handler(err, request):
        1 / 0

    pyramid_config.add_view(error_handler, context=ValueError)

    events = capture_events()

    client = get_client()

    with pytest.raises(ZeroDivisionError):
        client.get("/")

    event1, event2 = events

    exception, = event1["exception"]["values"]
    assert exception["type"] == "ValueError"

    exception = event2["exception"]["values"][0]
    assert exception["type"] == "ZeroDivisionError"
예제 #6
0
def initialize_sentry_integration():  # pragma: no cover
    """\
    Used to optionally initialize the Sentry service with this app.
    See https://docs.sentry.io/platforms/python/pyramid/

    """
    # This function is not under coverage because it is boilerplate
    # from the Sentry documentation.
    try:
        import sentry_sdk
        from sentry_sdk.integrations.pyramid import PyramidIntegration
        from sentry_sdk.integrations.celery import CeleryIntegration
    except ImportError:
        # This is an optional feature to be used when the dependency
        # and configuration are available.
        return  # bail out early

    try:
        dsn = os.environ['SENTRY_DSN']
    except KeyError:
        warnings.warn(
            "Sentry is not configured because SENTRY_DSN "
            "was not supplied.",
            AppStartUpWarning,
        )
    else:
        sentry_sdk.init(
            dsn=dsn,
            integrations=[PyramidIntegration(),
                          CeleryIntegration()],
        )
예제 #7
0
def includeme(config):

    # Initialize sentry and stash it in the registry
    sentry_sdk.init(
        dsn=config.registry.settings.get("sentry.dsn"),
        release=config.registry.settings.get("warehouse.commit"),
        transport=config.registry.settings.get("sentry.transport"),
        before_send=before_send,
        attach_stacktrace=True,
        integrations=[
            # This allows us to not create a tween
            # and a tween handler as it automatically
            # integrates with pyramid
            PyramidIntegration(),
            CeleryIntegration(),
            SqlalchemyIntegration(),
            LoggingIntegration(),
        ],
    )
    config.registry["sentry"] = sentry_sdk

    # Create a request method that'll get us the Sentry SDK in each request.
    config.add_request_method(_sentry, name="sentry", reify=True)

    # Wrap the WSGI object with the middle to catch any exceptions we don't
    # catch elsewhere.
    config.add_wsgi_middleware(SentryWsgiMiddleware)
예제 #8
0
def test_error_in_authenticated_userid(
    sentry_init, pyramid_config, capture_events, route, get_client
):
    from sentry_sdk.integrations.logging import LoggingIntegration

    sentry_init(
        send_default_pii=True,
        integrations=[
            PyramidIntegration(),
            LoggingIntegration(event_level=logging.ERROR),
        ],
    )
    logger = logging.getLogger("test_pyramid")

    class AuthenticationPolicy(object):
        def authenticated_userid(self, request):
            logger.error("failed to identify user")

    pyramid_config.set_authorization_policy(ACLAuthorizationPolicy())
    pyramid_config.set_authentication_policy(AuthenticationPolicy())

    events = capture_events()

    client = get_client()
    client.get("/message")

    assert len(events) == 1
예제 #9
0
def test_transaction_style(
    sentry_init, get_client, capture_events, transaction_style, expected_transaction
):
    sentry_init(integrations=[PyramidIntegration(transaction_style=transaction_style)])

    events = capture_events()
    client = get_client()
    client.get("/message")

    event, = events
    assert event["transaction"] == expected_transaction
예제 #10
0
    def initialize_sentry_sdk(self):
        import sentry_sdk
        from sentry_sdk.integrations.pyramid import PyramidIntegration
        from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration

        # Patch MAX_STRING_LENGTH to prevent clipping of big error messages,
        # especially for mako template tracebacks.
        sentry_sdk.utils.MAX_STRING_LENGTH = 8192

        sentry_sdk.init(
            self.options['dsn'],
            integrations=[
                PyramidIntegration(),
                SqlalchemyIntegration(),
            ],
            ignore_errors=[KeyboardInterrupt],
            environment=self.options['environment'],
            shutdown_timeout=self.options['shutdown_timeout'],
        )

        ts = Setting.__table__
        qs = ts.select().where(sqlalchemy.and_(
            ts.c.component == 'core',
            ts.c.name == 'instance_id'))

        event_user = None

        def add_instance_id(event, hint):
            nonlocal event_user
            if event_user is None:
                try:
                    row = self.env.core.DBSession.connection() \
                        .execute(qs).fetchone()
                except sqlalchemy.exc.ProgrammingError:
                    logger.debug(
                        "Failed to get instance_id, the database may not "
                        "have been initialized yet")
                except Exception:
                    logger.error("Got an exception while getting instance_id")
                else:
                    if row is not None:
                        instance_id = json.loads(row.value)
                        event_user = dict(id=instance_id)
                    else:
                        logger.debug("Missing instance_id")

            if event_user is not None:
                event['user'] = event_user

            return event

        with sentry_sdk.configure_scope() as scope:
            scope.add_event_processor(add_instance_id)
예제 #11
0
    def __init__(self, env, settings):
        super(SentryComponent, self).__init__(env, settings)

        if 'dsn' in self.options:
            sentry_sdk.init(
                self.options['dsn'],
                integrations=[
                    PyramidIntegration(),
                    SqlalchemyIntegration(),
                ],
                environment=self.options['environment'],
                shutdown_timeout=self.options['shutdown_timeout'],
            )
예제 #12
0
def main(global_config, **settings):
    """ Connect to sentry
    """
    sentry_sdk.init(
        dsn="https://[email protected]/1845128",
        integrations=[PyramidIntegration()]
    )

    """ This function returns a Pyramid WSGI application.
    """
    with Configurator(settings=settings) as config:
        config.include('.models')
        config.include('pyramid_jinja2')
        config.include('.routes')
        config.scan()
    return config.make_wsgi_app()
예제 #13
0
    def configure(self):
        super(Portal, self).configure()
        self.configure_zca()

        mimetypes.add_type('application/font-woff', '.woff')
        mimetypes.add_type('application/x-font-ttf', '.ttf')

        registry = pyramid.registry.Registry(
            bases=(zope.component.getGlobalSiteManager(),))
        if self.settings.get('sentry.dsn', None):
            version = sw.allotmentclub.version.__version__
            sentry_sdk.init(
                release=f"sw-allotmentclub-backend@{version}",
                dsn=self.settings['sentry.dsn'],
                integrations=[PyramidIntegration(), SqlalchemyIntegration()])
        self.config = config = pyramid.config.Configurator(
            settings=self.settings,
            registry=registry)
        config.setup_registry(settings=self.settings)
        config.include('pyramid_beaker')
        config.include('pyramid_exclog')
        config.include('pyramid_tm')

        if self.testing:
            config.include('pyramid_mailer.testing')
        elif config.registry.settings.get('mail.enable') == 'false':
            config.include('sw.allotmentclub.printmailer')
        else:
            config.include('sw.allotmentclub.logmailer')

        # self.add_csrf_check()

        config.add_renderer(
            'json', risclog.sqlalchemy.serializer.json_renderer_factory(
                serializer=json_serializer))

        config.set_default_permission('view')
        config.set_authentication_policy(SessionAuthenticationPolicy())
        config.set_authorization_policy(ACLAuthorizationPolicy())
        config.set_root_factory(
            sw.allotmentclub.browser.auth.get_default_context)
        config.add_request_method(
            sw.allotmentclub.browser.auth.get_user, 'user', property=True)

        self.add_routes()
        config.scan(package=sw.allotmentclub.browser,
                    ignore=sw.allotmentclub.SCAN_IGNORE_TESTS)
예제 #14
0
def main(global_config: Dict[str, str], **settings: str) -> PrefixMiddleware:
    """Configure and return a Pyramid WSGI application."""
    settings["tildes.open_registration"] = asbool(
        settings.get("tildes.open_registration", "false"))

    config = Configurator(settings=settings)

    config.include("cornice")
    config.include("pyramid_session_redis")
    config.include("pyramid_webassets")

    # include database first so the session and querying are available
    config.include("tildes.database")
    config.include("tildes.auth")
    config.include("tildes.jinja")
    config.include("tildes.json")
    config.include("tildes.request_methods")
    config.include("tildes.routes")
    config.include("tildes.tweens")

    config.add_webasset("javascript", Bundle(output="js/tildes.js"))
    config.add_webasset("javascript-third-party",
                        Bundle(output="js/third_party.js"))
    config.add_webasset("css", Bundle(output="css/tildes.css"))
    config.add_webasset("site-icons-css", Bundle(output="css/site-icons.css"))

    config.scan("tildes.views")

    config.add_static_view("images", "/images")

    if settings.get("sentry_dsn"):
        sentry_sdk.init(
            dsn=settings["sentry_dsn"],
            integrations=[PyramidIntegration()],
            ignore_errors=[ValidationError],
        )

    app = config.make_wsgi_app()

    force_port = global_config.get("prefixmiddleware_force_port")
    if force_port:
        prefixed_app = PrefixMiddleware(app, force_port=force_port)
    else:
        prefixed_app = PrefixMiddleware(app)

    return prefixed_app
예제 #15
0
def test_tween_ok(sentry_init, pyramid_config, capture_exceptions, route, get_client):
    sentry_init(integrations=[PyramidIntegration()])
    errors = capture_exceptions()

    @route("/")
    def index(request):
        raise Exception()

    pyramid_config.add_tween(
        "tests.integrations.pyramid.test_pyramid.tween_factory",
        under=pyramid.tweens.INGRESS,
    )

    client = get_client()
    client.get("/")

    assert not errors
예제 #16
0
def main(global_config, **settings):
    settings.update(parse_settings(settings))
    config = Configurator(settings=settings)
    config.include("cornice")
    config.include("cornice_swagger")
    config.include("documentstore.pyramid_prometheus")
    config.scan()
    config.add_renderer("xml", XMLRenderer)
    config.add_renderer("text", PlainTextRenderer)

    mongo = adapters.MongoDB(
        settings["kernel.app.mongodb.dsn"],
        settings["kernel.app.mongodb.dbname"],
        options={
            "replicaSet": settings["kernel.app.mongodb.replicaset"],
            "readPreference": settings["kernel.app.mongodb.readpreference"],
            "w": settings["kernel.app.mongodb.writeto"],
        },
    )

    if settings["kernel.app.mongodb.transactions.enabled"]:
        Session = adapters.TransactionalSession.partial(mongo)
    else:
        Session = adapters.Session.partial(mongo)
        LOGGER.warning(
            "transactional support is disabled and it may cause data loss. "
            "If the app is running in production, this is a huge mistake"
        )

    config.add_request_method(
        lambda request: services.get_handlers(Session), "services", reify=True
    )

    if settings["kernel.app.sentry.enabled"]:
        if settings["kernel.app.sentry.dsn"]:
            sentry_sdk.init(
                dsn=settings["kernel.app.sentry.dsn"],
                integrations=[PyramidIntegration(transaction_style="route_pattern")],
                release=f"scielo-kernel@{VERSION}",
                environment=settings["kernel.app.sentry.environment"],
            )
        else:
            LOGGER.info("cannot setup Sentry: the dsn was not provided")

    return config.make_wsgi_app()
예제 #17
0
def test_errorhandler_ok(sentry_init, pyramid_config, capture_exceptions,
                         route, get_client):
    sentry_init(integrations=[PyramidIntegration()])
    errors = capture_exceptions()

    @route("/")
    def index(request):
        raise Exception()

    def errorhandler(exc, request):
        return Response("bad request")

    pyramid_config.add_view(errorhandler, context=Exception)

    client = get_client()
    client.get("/")

    assert not errors
예제 #18
0
    def __init__(self, env, settings):
        super(SentryComponent, self).__init__(env, settings)

        if 'dsn' in self.options:
            # Patch MAX_STRING_LENGTH to prevent clipping of big error messages,
            # especially for mako template tracebacks.
            sentry_sdk.utils.MAX_STRING_LENGTH = 8192

            sentry_sdk.init(
                self.options['dsn'],
                integrations=[
                    PyramidIntegration(),
                    SqlalchemyIntegration(),
                ],
                ignore_errors=[KeyboardInterrupt],
                environment=self.options['environment'],
                shutdown_timeout=self.options['shutdown_timeout'],
            )
예제 #19
0
def test_flask_empty_json_request(sentry_init, capture_events, route, get_client, data):
    sentry_init(integrations=[PyramidIntegration()])

    @route("/")
    def index(request):
        assert request.json == data
        assert request.text == json.dumps(data)
        assert not request.POST
        capture_message("hi")
        return Response("ok")

    events = capture_events()

    client = get_client()
    response = client.post("/", content_type="application/json", data=json.dumps(data))
    assert response[1] == "200 OK"

    event, = events
    assert event["request"]["data"] == data
예제 #20
0
def test_bad_request_not_captured(sentry_init, pyramid_config, capture_events,
                                  route, get_client):
    import pyramid.httpexceptions as exc

    sentry_init(integrations=[PyramidIntegration()])
    events = capture_events()

    @route("/")
    def index(request):
        raise exc.HTTPBadRequest()

    def errorhandler(exc, request):
        return Response("bad request")

    pyramid_config.add_view(errorhandler, context=exc.HTTPBadRequest)

    client = get_client()
    client.get("/")

    assert not events
예제 #21
0
def test_errorhandler_500(sentry_init, pyramid_config, capture_exceptions,
                          route, get_client):
    sentry_init(integrations=[PyramidIntegration()])
    errors = capture_exceptions()

    @route("/")
    def index(request):
        1 / 0

    def errorhandler(exc, request):
        return Response("bad request", status=500)

    pyramid_config.add_view(errorhandler, context=Exception)

    client = get_client()
    app_iter, status, headers = client.get("/")
    assert b"".join(app_iter) == b"bad request"
    assert status.lower() == "500 internal server error"

    (error, ) = errors

    assert isinstance(error, ZeroDivisionError)
예제 #22
0
def main(global_config, **settings):
    dsn = settings.get("sentry.dsn") or os.environ.get("SENTRY_DSN")
    if dsn:
        sentry_sdk.init(
            dsn=dsn,
            integrations=[
                LoggingIntegration(),
                PyramidIntegration(),
            ],
            send_default_pii=True,
            request_bodies="always",
            environment=settings.get("sentry.environment"),
        )

    config = Configurator(
        autocommit=True,
        settings=settings,
        authentication_policy=AuthenticationPolicy(settings['auth.file'], __name__),
        authorization_policy=AuthorizationPolicy(),
        route_prefix=ROUTE_PREFIX,
    )
    config.include('pyramid_exclog')
    config.include("cornice")
    config.add_forbidden_view(forbidden)
    config.add_request_method(request_params, 'params', reify=True)
    config.add_request_method(authenticated_role, reify=True)
    config.add_request_method(check_accreditation)
    config.add_renderer('json', JSON(serializer=simplejson.dumps))
    config.add_renderer('prettyjson', JSON(indent=4, serializer=simplejson.dumps))
    config.add_renderer('jsonp', JSONP(param_name='opt_jsonp', serializer=simplejson.dumps))
    config.add_renderer('prettyjsonp', JSONP(indent=4, param_name='opt_jsonp', serializer=simplejson.dumps))

    # search for plugins
    plugins = settings.get('plugins') and settings['plugins'].split(',')
    for entry_point in iter_entry_points('openprocurement.audit.api.plugins'):
        if not plugins or entry_point.name in plugins:
            plugin = entry_point.load()
            plugin(config)
            pass

    # CouchDB connection
    aserver, server, db = set_api_security(settings)
    config.registry.couchdb_server = server
    if aserver:
        config.registry.admin_couchdb_server = aserver
    config.registry.db = db
    # readjust couchdb json decoder
    couchdb_json_decode()

    # Document Service key
    config.registry.docservice_url = settings.get('docservice_url')
    config.registry.docservice_username = settings.get('docservice_username')
    config.registry.docservice_password = settings.get('docservice_password')
    config.registry.docservice_upload_url = settings.get('docservice_upload_url')
    # config.registry.docservice_key = dockey = Signer(settings.get('dockey', '').decode('hex'))
    # config.registry.keyring = keyring = {}
    # dockeys = settings.get('dockeys') if 'dockeys' in settings else dockey.hex_vk()
    # for key in dockeys.split('\0'):
    #     keyring[key[:8]] = Verifier(key)

    signing_key = settings.get('dockey', '')
    signer = SigningKey(signing_key, encoder=HexEncoder) if signing_key else SigningKey.generate()
    config.registry.docservice_key = signer
    verifier = signer.verify_key

    config.registry.keyring = {
        verifier.encode(encoder=HexEncoder)[:8].decode(): verifier
    }
    dockeys = settings.get('dockeys', '')
    for key in dockeys.split('\0'):
        if key:
            config.registry.keyring[key[:8]] = VerifyKey(key, encoder=HexEncoder)

    # migrate data
    if not os.environ.get('MIGRATION_SKIP'):
        for entry_point in iter_entry_points('openprocurement.audit.api.migrations'):
            plugin = entry_point.load()
            plugin(config.registry)

    config.registry.server_id = settings.get('id', '')

    # search subscribers
    subscribers_keys = [k for k in settings if k.startswith('subscribers.')]
    for k in subscribers_keys:
        subscribers = settings[k].split(',')
        for subscriber in subscribers:
            for entry_point in iter_entry_points('openprocurement.{}'.format(k), subscriber):
                if entry_point:
                    plugin = entry_point.load()
                    plugin(config)

    config.registry.health_threshold = float(settings.get('health_threshold', 512))
    config.registry.health_threshold_func = settings.get('health_threshold_func', 'all')
    config.registry.update_after = asbool(settings.get('update_after', True))
    config.registry.disable_opt_fields_filter = asbool(settings.get('disable_opt_fields_filter', False))
    return config.make_wsgi_app()
예제 #23
0
def init_sentry(dsn):
    """ Helper function that initializes sentry SDK if a dsn is specified. """
    if dsn:
        sentry_sdk.init(
            dsn, integrations=[PyramidIntegration(),
                               SqlalchemyIntegration()])
예제 #24
0
######### sentry.io logging


import sentry_sdk, os
from sentry_sdk.integrations.pyramid import PyramidIntegration

if 'SENTRY_DNS_MICHELANGLO' in os.environ:
    #this is not in the config file due to security as this github repo is public.
    sentry_sdk.init(
     dsn=os.environ['SENTRY_DNS_MICHELANGLO'],
     integrations=[PyramidIntegration()]
    )

from pyramid.config import Configurator
from pyramid.session import SignedCookieSessionFactory

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(settings=settings)
    my_session_factory = SignedCookieSessionFactory('TIM barrels') ##temporary data
    config.set_session_factory(my_session_factory)
    config.include('.models')
    config.include('pyramid_mako')
    config.include('.routes')
    config.include('.security')
    config.include('.scheduler')
    config.scan()
    return config.make_wsgi_app()
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

from sentry_sdk.integrations.pyramid import PyramidIntegration
import sentry_sdk


def hello_world(request):
    return 1 / 0
    return Response('<h1>Hello world!</h1>')


def test_func(request):
    return Response("<h1>Hi!, this is Paras Jain</h1>")


if __name__ == '__main__':
    with Configurator() as config:
        config.add_route('', '/')
        config.add_view(hello_world, route_name='')
        config.add_route('test', '/test')
        config.add_view(test_func, route_name='test')
        sentry_sdk.init(dsn="", integrations=[PyramidIntegration()])

    app = config.make_wsgi_app()

    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()
예제 #26
0
def main(global_config, **settings):
    """ Return a Pyramid WSGI application. """
    settings['config_uri'] = global_config['__file__']

    # here we create the engine and bind it to the (not really a) session
    # factory
    settings = set_config(settings)
    if not session_maker_is_initialized():
        configure_engine(settings)
    if settings.get('assembl_debug_signal', False):
        from assembl.lib import signals
        signals.listen()

    import os
    if 'UWSGI_ORIGINAL_PROC_NAME' in os.environ:
        # uwsgi does not load logging properly
        from pyramid.paster import setup_logging
        setup_logging(global_config['__file__'])

    # Sentry
    import sentry_sdk
    from sentry_sdk.integrations.pyramid import PyramidIntegration
    if settings.get('sentry_dsn', ''):
        sentry_sdk.init(dsn=settings['sentry_dsn'],
                        integrations=[PyramidIntegration()])

    from views.traversal import root_factory
    config = Configurator(registry=getGlobalSiteManager())
    config.setup_registry(settings=settings, root_factory=root_factory)
    config.add_translation_dirs('assembl:locale/')

    config.set_locale_negotiator(my_locale_negotiator)
    config.add_tween('assembl.tweens.logging.logging_tween_factory',
                     over="pyramid_tm.tm_tween_factory")

    config.include('.auth')
    config.include('.models')
    config.include('.indexing')
    config.include('.lib.logging')
    # Tasks first, because it includes ZCA registration (for now)
    config.include('.tasks')

    config.include('.lib.zmqlib')
    session_factory = session_factory_from_settings(settings)
    config.set_session_factory(session_factory)
    if not settings.get('nosecurity', False):
        # import after session to delay loading of BaseOps
        from auth.util import authentication_callback
        auth_policy_name = settings.get(
            "auth_policy_class",
            "assembl.auth.util.UpgradingSessionAuthenticationPolicy")
        auth_policy = resolver.resolve(auth_policy_name)(
            callback=authentication_callback)
        config.set_authentication_policy(auth_policy)
        config.set_authorization_policy(ACLAuthorizationPolicy())
    # ensure default roles and permissions at startup
    from models import get_session_maker
    if not settings.get('in_migration', False):
        with transaction.manager:
            session = get_session_maker()
            from .lib.migration import bootstrap_db_data
            bootstrap_db_data(session, settings['config_uri'] != "testing.ini")

    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_static_view('static2', 'static2', cache_max_age=3600)
    config.include('.graphql')  # This MUST be above views import

    config.include('cornice')  # REST services library.
    # config.include('.lib.alembic')
    # config.include('.lib.email')
    config.include('.lib')
    config.include('.views')

    # jinja2
    config.include('pyramid_jinja2')
    config.add_jinja2_extension('jinja2.ext.i18n')

    # Mailer
    config.include('pyramid_mailer')

    config.include('.view_def')

    wsgi_app = config.make_wsgi_app()
    if asbool(settings.get('sqltap', False)):
        import sqltap.wsgi
        wsgi_app = sqltap.wsgi.SQLTapMiddleware(wsgi_app)
    return wsgi_app
예제 #27
0
def main(global_config, **settings):
    del global_config  # Unused

    if len(os.environ.get('SENTRY_URL', '')) > 0:
        sentry_sdk.init(dsn=os.environ.get('SENTRY_URL', ''),
                        integrations=[PyramidIntegration()])
    """
    This function returns a Pyramid WSGI application.
    """
    config = Configurator(
        root_factory=Root,
        settings=settings,
        locale_negotiator=locale_negotiator,
        authentication_policy=create_authentication(settings))
    if os.environ.get('ALLOW_CORS', '0') == '1':
        config.add_subscriber(add_cors_headers_response_callback, NewRequest)

    if os.environ.get('DEBUG_TOOLBAR', '0') == '1':
        config.get_settings()['debugtoolbar.hosts'] = ['0.0.0.0/0']
        config.include('pyramid_debugtoolbar')

    # Workaround to not have the error: distutils.errors.DistutilsArgError: no commands supplied
    distutils.core._setup_stop_after = 'config'

    config.add_route("lux_get_thumbnail",
                     "/printproxy/thumbnail",
                     request_method="GET")
    # overwrite print routes
    config.add_route("lux_printproxy_report_create",
                     "/printproxy/report.{format}",
                     request_method="POST")
    config.add_route("lux_printproxy_status",
                     "/printproxy/status/{ref}.json",
                     request_method="GET")
    config.add_route("lux_printproxy_report_get",
                     "/printproxy/report/{ref}",
                     request_method="GET")
    config.add_route("lux_printproxy_report_cancel",
                     "/printproxy/cancel/{ref}",
                     request_method="DELETE")

    config.include('c2cgeoportal_geoportal')
    distutils.core._setup_stop_after = None

    add_mako_renderer(config, '.appcache')

    config.add_translation_dirs('geoportailv3_geoportal:locale/')

    add_interface(config, 'main', INTERFACE_TYPE_NGEO_CATALOGUE, default=True)

    # ping routes
    config.add_route("ping", "/ping")

    # mymaps routes
    config.add_route("mymaps", "/mymaps", request_method="HEAD")
    config.add_route("mymaps_image", "/", request_method="HEAD")
    config.add_route("mymaps_get_full_mymaps",
                     "mymaps/get_full_mymaps",
                     request_method="GET")
    config.add_route("mymaps_getcategories",
                     "mymaps/categories",
                     request_method="GET")
    config.add_route("mymaps_getallcategories",
                     "mymaps/allcategories",
                     request_method="GET")

    config.add_route("generate_symbol_file",
                     "/mymaps/generate_symbol_file",
                     request_method="GET")

    config.add_route("mymaps_getpublicmaps",
                     "/mymaps/public_maps",
                     request_method="GET")
    config.add_route("mymaps_getpublicategories",
                     "/mymaps/public_categories",
                     request_method="GET")
    config.add_route("mymaps_getmaps", "/mymaps/maps", request_method="GET")
    config.add_route("mymaps_features",
                     "/mymaps/features/{map_id}",
                     request_method="GET")
    config.add_route("mymaps_map_info",
                     "/mymaps/map_info/{map_id}",
                     request_method="GET")

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

    config.add_route("mymaps_create", "/mymaps/create", request_method="POST")
    config.add_route("mymaps_rate", "/mymaps/rate/{map_id}")
    config.add_route("mymaps_update",
                     "/mymaps/update/{map_id}",
                     request_method="PUT")
    config.add_route("get_gpx",
                     "/mymaps/get_gpx/{map_id}",
                     request_method="GET")
    config.add_route("mymaps_map",
                     "/mymaps/map/{map_id}",
                     request_method="GET")
    config.add_route("mymaps_comment",
                     "/mymaps/comment/{map_id}",
                     request_method="POST")
    config.add_route("mymaps_upload_image",
                     "/mymaps/upload_image",
                     request_method="POST")
    config.add_route("mymaps_upload_symbol",
                     "/mymaps/upload_symbol",
                     request_method="POST")
    config.add_route("mymaps_get_image",
                     "/mymaps/images/{filename}",
                     request_method="GET")
    config.add_route("mymaps_get_symbol",
                     "/mymaps/symbol/{symbol_id}",
                     request_method="GET")
    config.add_route("mymaps_users_categories",
                     "/mymaps/get_users_categories",
                     request_method="GET")
    config.add_route("mymaps_get_symbols",
                     "/mymaps/symbols",
                     request_method="GET")
    config.add_route("mymaps_delete",
                     "/mymaps/delete/{map_id}",
                     request_method="DELETE")
    config.add_route("mymaps_delete_all_features",
                     "/mymaps/delete_all_features/{map_id}",
                     request_method="DELETE")
    config.add_route("mymaps_delete_feature",
                     "/mymaps/delete_feature/{feature_id}",
                     request_method="DELETE")
    config.add_route("mymaps_save_feature",
                     "/mymaps/save_feature/{map_id}",
                     request_method="POST")
    config.add_route("mymaps_save_features",
                     "/mymaps/save_features/{map_id}",
                     request_method="POST")
    config.add_route("mymaps_save_order",
                     "/mymaps/save_order/{map_id}",
                     request_method="POST")
    config.add_route("mymaps_save_offline",
                     "/mymaps/save_offline",
                     request_method="POST")
    config.add_route("mymaps_copy",
                     "/mymaps/copy/{map_id}",
                     request_method="POST")
    config.add_route("exportgpxkml",
                     "/mymaps/exportgpxkml",
                     request_method="POST")
    config.add_route("get_arrow_color", "/mymaps/getarrow")
    config.add_route("getroute", "/mymaps/getroute")
    config.add_route("getremoteroute", "/router/getroute")
    # geocoder routes
    config.add_route("reverse_geocode", "/geocode/reverse")
    config.add_route("geocode", "/geocode/search")
    config.add_route("feedback", "/feedback")
    config.add_route("feedbackanf", "/feedbackanf")
    config.add_route("feedbackcrues", "/feedbackcrues")
    config.add_route("feedbackage", "/feedbackage")
    # user config routes
    config.add_route("get_userconfig", "/get_userconfig", request_method="GET")
    config.add_route("save_userconfig",
                     "/save_userconfig",
                     request_method="POST")
    config.add_route("delete_userconfig",
                     "/delete_userconfig",
                     request_method="DELETE")
    config.add_route("apply_mvt_config",
                     "/apply_mvt_config",
                     request_method="GET")
    # pag routes
    config.add_route("pag_url", "/pag")
    # pag routes
    config.add_route("pag_report", "/pag/report/{oid}.pdf")
    # pag routes
    config.add_route("casipo_url", "/casipo")
    # pag routes
    config.add_route("casipo_report", "/casipo/report/{oid}.pdf")
    # pds routes
    config.add_route("pds_url", "/pds")
    # pag routes
    config.add_route("pds_report", "/pds/report/{oid}.pdf")
    config.add_route("pag_files", "/pag/files/{_file}")
    config.add_route("get_png", "/legends/get")
    config.add_route("get_html", "/legends/get_html")
    config.add_route("get_metadata", "/getMetadata")
    # full text search routes
    config.add_route("fulltextsearch", "/fulltextsearch")

    # layer search routes
    config.add_route("layersearch", "/layersearch")

    # cms search routes
    config.add_route("cmssearch", "/cmssearch")

    # cms search routes
    config.add_route("featuresearch", "/featuresearch")

    # jsapi routes
    config.add_route('jsapiloader', '/apiv3loader.js')
    config.add_route('jsapiexample', '/api-example')
    config.add_route('jsapilayers', '/jsapilayers')
    config.add_route('jsapilayersfull', '/jsapilayersfull')
    config.add_route('jsapithemesfull', '/jsapithemesfull')

    config.add_route("echocsv", "/profile/echocsv", request_method="POST")
    config.add_route('getuserinfo', '/getuserinfo')
    config.add_route('wms', '/ogcproxywms')
    config.add_route('wmspoi', '/wmspoi')
    config.add_route('https_proxy', '/httpsproxy')
    config.add_route('download_sketch', '/downloadsketch')
    config.add_route('download', '/download')
    config.add_route('download_pdf', '/downloadpdf')
    config.add_route('download_measurement', '/downloadmeasurement')
    config.add_route('preview_measurement', '/previewmeasurement')
    config.add_route('qr', '/qr')
    config.add_route('getfeatureinfo', '/getfeatureinfo')
    config.add_route('getbuswidget', '/getbuswidget')
    config.add_route('getpoitemplate', '/getpoitemplate')
    config.add_route('getremotetemplate', '/getremotetemplate')
    config.add_route('isthemeprivate', '/isthemeprivate')
    config.add_route('download_resource', '/downloadresource')
    config.add_route('upload_vt_style', '/uploadvtstyle')
    config.add_route('delete_vt_style', '/deletevtstyle')
    config.add_route('get_vt_style', '/getvtstyle')

    # Service worker
    config.add_route('sw', '/sw.js')

    config.add_static_view('proj/{version}',
                           path='geoportailv3_geoportal:jsapi/')

    # Appcache manifest
    config.add_route('appcache', '/geoportailv3.appcache')
    # ldap
    from geoportailv3_geoportal.views.authentication import ldap_user_validator, \
        get_user_from_request
    ldap_settings = config.get_settings()['ldap']
    if ldap_settings:
        config.include('pyramid_ldap3')
        """Config the ldap connection.
        """

        config.ldap_setup(
            ldap_settings['url'],
            ldap_settings['bind'],
            ldap_settings['passwd'],
            use_pool=
            False,  # avoid errors like LDAPMaximumRetriesError and LDAPResponseTimeoutError
        )

        ldap_settings['filter_tmpl'] = ldap_settings['filter_tmpl'].replace(
            '%%', '%')
        config.ldap_set_login_query(
            ldap_settings['base_dn'],
            filter_tmpl=ldap_settings['filter_tmpl'],
            scope=ldap.SUBTREE,
        )

        config.set_request_property(get_user_from_request,
                                    name='user',
                                    reify=True)

        set_user_validator(config, ldap_user_validator)

    # json
    json_renderer = JSON()
    json_renderer.add_adapter(datetime.date, datetime_adapter)
    json_renderer.add_adapter(datetime.datetime, datetime_adapter)
    json_renderer.add_adapter(Decimal, decimal_adapter)
    config.add_renderer('json', json_renderer)

    # mailer
    mail_config = config.get_settings()['mailer'].copy()
    maildir = os.environ.get('MAILER_DIRECTORY', None)
    if maildir:
        # To deliver emails to a directory (for local dev)
        mail_config['transport.use'] = 'maildir'
        mail_config['transport.directory'] = maildir
    global mailer
    mailer = Mailer(mail_config)
    mailer.start()

    # Add custom table in admin interace, that means re-add all normal table

    from c2cgeoform.routes import register_models

    from c2cgeoportal_commons.models.main import (Role, LayerWMS, LayerWMTS,
                                                  Theme, LayerGroup, LayerV1,
                                                  Interface, OGCServer,
                                                  Functionality,
                                                  RestrictionArea)
    from c2cgeoportal_commons.models.static import User
    from geoportailv3_geoportal.models import LuxDownloadUrl, \
        LuxMeasurementLoginCommune, LuxMeasurementDirectory, LuxGetfeatureDefinition, \
        LuxPrintServers, LuxPredefinedWms, LuxLayerExternalWMS, LuxLayerInternalWMS

    register_models(
        config,
        (
            ('themes', Theme),
            ('layer_groups', LayerGroup),
            # ('layers_wms', LayerWMS), removed we use LuxLayerExternalWMS and LuxLayerInternalWMS instead
            ('layers_wmts', LayerWMTS),
            ('layers_v1', LayerV1),
            ('ogc_servers', OGCServer),
            ('restriction_areas', RestrictionArea),
            ('users', User),
            ('roles', Role),
            ('functionalities', Functionality),
            ('interfaces', Interface),
            ('lux_download_url', LuxDownloadUrl),
            ('lux_measurement_login_commune', LuxMeasurementLoginCommune),
            ('lux_measurement_directory', LuxMeasurementDirectory),
            ('lux_getfeature_definition', LuxGetfeatureDefinition),
            ('lux_print_servers', LuxPrintServers),
            ('lux_predefined_wms', LuxPredefinedWms),
            ('lux_layer_external_wms', LuxLayerExternalWMS),
            ('lux_layer_internal_wms', LuxLayerInternalWMS),
        ),
        'admin')

    # scan view decorator for adding routes
    config.scan()

    return config.make_wsgi_app()
예제 #28
0
def includeme(config: Optional[pyramid.config.Configurator] = None) -> None:
    """Initialize the Sentry intergation."""
    global _client_setup
    sentry_url = config_utils.env_or_config(config, "SENTRY_URL",
                                            "c2c.sentry.url")
    if sentry_url is not None and not _client_setup:
        client_info: MutableMapping[str, Any] = {
            key[14:].lower(): value
            for key, value in os.environ.items()
            if key.startswith("SENTRY_CLIENT_")
        }
        # Parse bool
        for key in (
                "with_locals",
                "default_integrations",
                "send_default_pii",
                "debug",
                "attach_stacktrace",
                "propagate_traces",
                "auto_enabling_integrations",
                "auto_session_tracking",
        ):
            if key in client_info:
                client_info[key] = client_info[key].lower() in ("1", "t",
                                                                "true")
        # Parse int
        for key in ("max_breadcrumbs", "shutdown_timeout",
                    "transport_queue_size"):
            if key in client_info:
                client_info[key] = int(client_info[key])
        # Parse float
        for key in ("sample_rate", "traces_sample_rate"):
            if key in client_info:
                client_info[key] = float(client_info[key])

        git_hash = config_utils.env_or_config(config, "GIT_HASH",
                                              "c2c.git_hash")
        if git_hash is not None and not ("release" in client_info and
                                         client_info["release"] != "latest"):
            client_info["release"] = git_hash
        client_info["ignore_errors"] = client_info.pop("ignore_exceptions",
                                                       "SystemExit").split(",")
        tags = {
            key[11:].lower(): value
            for key, value in os.environ.items()
            if key.startswith("SENTRY_TAG_")
        }

        sentry_logging = LoggingIntegration(
            level=logging.DEBUG,
            event_level=config_utils.env_or_config(config, "SENTRY_LEVEL",
                                                   "c2c.sentry_level",
                                                   "ERROR").upper(),
        )
        traces_sample_rate = float(
            config_utils.env_or_config(config, "SENTRY_TRACES_SAMPLE_RATE",
                                       "c2c.sentry_traces_sample_rate", "0.0"))
        sentry_sdk.init(
            dsn=sentry_url,
            integrations=[
                sentry_logging,
                PyramidIntegration(),
                SqlalchemyIntegration(),
                RedisIntegration()
            ],
            traces_sample_rate=traces_sample_rate,
            before_send=_create_before_send_filter(tags),
            **client_info,
        )
        _client_setup = True

        excludes = config_utils.env_or_config(config, "SENTRY_EXCLUDES",
                                              "c2c.sentry.excludes",
                                              "sentry_sdk").split(",")
        for exclude in excludes:
            ignore_logger(exclude)

        LOG.info("Configured sentry reporting with client=%s and tags=%s",
                 repr(client_info), repr(tags))
예제 #29
0
    def make_app(self, settings=None):
        settings = dict(self._settings, **settings)

        settings['mako.directories'] = 'nextgisweb:templates/'

        is_debug = self.env.core.debug

        # If debug is on, add mako-filter that checks
        # if the line was translated before output.

        if is_debug:
            settings['mako.default_filters'] = ['tcheck', 'h']
            settings['mako.imports'] = settings.get('mako.imports', []) \
                + ['from nextgisweb.i18n import tcheck', ]

        # If pyramid config doesn't state otherwise, use locale from,
        # core component, while this is not clear why we need that.

        plockey = 'pyramid.default_locale_name'
        if plockey not in settings and self.env.core.locale_default is not None:
            settings[plockey] = self.env.core.locale_default

        sentry_dsn = 'sentry_dsn'
        if sentry_dsn in settings:
            sentry_sdk.init(
                settings[sentry_dsn],
                integrations=[PyramidIntegration()],
            )

        config = Configurator(settings=settings)

        # Substitute localizer from pyramid with our own, original is
        # too tied to translationstring, that works strangely with string
        # interpolation via % operator.

        def localizer(request):
            return request.env.core.localizer(request.locale_name)

        config.add_request_method(localizer, 'localizer', property=True)

        # TODO: Need to get rid of translation dirs!
        # Currently used only to search for jed-files.

        for pkg in pkginfo.packages:
            dirname = resource_filename(pkg, 'locale')
            if os.path.isdir(dirname):
                config.add_translation_dirs(dirname)

        config.add_route_predicate('client', ClientRoutePredicate)

        config.add_view_predicate('method', RequestMethodPredicate)
        config.add_view_predicate('json', JsonPredicate)

        config.add_request_method(
            lambda request: request.path_info.lower().startswith('/api/'),
            'is_api',
            property=True,
            reify=True)

        self.error_handlers = list()

        @self.error_handlers.append
        def api_error_handler(request, err_info, exc, exc_info):
            if request.is_api or request.is_xhr:
                return exception.json_error_response(request,
                                                     err_info,
                                                     exc,
                                                     exc_info,
                                                     debug=is_debug)

        def error_handler(request, err_info, exc, exc_info, **kwargs):
            for handler in self.error_handlers:
                result = handler(request, err_info, exc, exc_info)
                if result is not None:
                    return result

        config.registry.settings['error.err_response'] = error_handler
        config.registry.settings['error.exc_response'] = error_handler
        config.include(exception)

        # Access to Env through request.env
        config.add_request_method(lambda req: self._env, 'env', property=True)

        config.include(pyramid_tm)
        config.include(pyramid_mako)

        # Filter for quick translation. Defines function tr, which we can use
        # instead of request.localizer.translate in templates.
        def tr_subscriber(event):
            event['tr'] = event['request'].localizer.translate

        config.add_subscriber(tr_subscriber, BeforeRender)

        assert 'secret' in settings, 'Secret not set!'
        authn_policy = AuthenticationPolicy(settings=settings)
        config.set_authentication_policy(authn_policy)

        authz_policy = ACLAuthorizationPolicy()
        config.set_authorization_policy(authz_policy)

        # Help
        self.help_page = {}
        for key in settings.keys():
            if key.startswith('help_page'):
                hploc = key.split('.')[-1]
                self.help_page[hploc] = settings[key]

        # To not clear static cache by hand make it so that
        # URLs are different. Use md5 hash from all installed packages
        # which we can get with pip freeze. pip freeze
        # also returns current commit for packages from
        # VCS, this also helps.

        # This could've been done better, but right now simply
        # redirect sys.stdout to StringIO, run pip freeze and
        # return sys.stdout to initial state.

        try:
            from pip._internal import main as pip_main
        except ImportError:
            from pip import main as pip_main

        stdout = sys.stdout
        static_key = ''

        try:
            buf = StringIO()
            sys.stdout = buf
            with warnings.catch_warnings():
                warnings.filterwarnings(
                    'ignore', r'DEPRECATION: Python 2\.7 will reach')
                pip_main([
                    'freeze',
                ])
            h = md5()
            h.update(buf.getvalue())
            static_key = '/' + h.hexdigest()
        finally:
            sys.stdout = stdout

        self.distinfo = []

        # Read installed packages from pip freeze

        buf.seek(0)

        for line in buf:
            line = line.strip().lower()

            dinfo = None
            mpkg = re.match(r'(.+)==(.+)', line)
            if mpkg:
                dinfo = DistInfo(name=mpkg.group(1),
                                 version=mpkg.group(2),
                                 commit=None)

            mgit = re.match(r'-e\sgit\+.+\@(.{8}).{32}\#egg=(\w+).*$', line)
            if mgit:
                dinfo = DistInfo(name=mgit.group(2),
                                 version=get_distribution(
                                     mgit.group(2)).version,
                                 commit=mgit.group(1))

            if dinfo is not None:
                self.distinfo.append(dinfo)
            else:
                self.logger.warn("Could not parse pip freeze line: %s", line)

        config.add_static_view('/static%s/asset' % static_key,
                               'nextgisweb:static',
                               cache_max_age=3600)

        config.add_route('amd_package', '/static%s/amd/*subpath' % static_key) \
            .add_view('nextgisweb.views.amd_package')

        for comp in self._env.chain('setup_pyramid'):
            comp.setup_pyramid(config)

        def html_error_handler(request, err_info, exc, exc_info):
            return exception.html_error_response(request,
                                                 err_info,
                                                 exc,
                                                 exc_info,
                                                 debug=is_debug)

        self.error_handlers.append(html_error_handler)

        def amd_base(request):
            amds = []
            for comp in self._env.chain('amd_base'):
                amds.extend(comp.amd_base)
            return amds

        config.add_request_method(amd_base,
                                  'amd_base',
                                  property=True,
                                  reify=True)

        config.add_renderer('json', json_renderer)

        return config
예제 #30
0
def main(global_config, **settings):
    dsn = settings.get("sentry.dsn", None)
    if dsn:
        LOGGER.info("Init sentry sdk for {}".format(dsn))
        sentry_sdk.init(
            dsn=dsn,
            integrations=[
                LoggingIntegration(level=None, event_level=None),
                PyramidIntegration()
            ],
            send_default_pii=True,
            request_bodies="always",
            environment=settings.get("sentry.environment", None),
            debug=settings.get("sentry.debug", False),
        )

    config = Configurator(
        autocommit=True,
        settings=settings,
        authentication_policy=AuthenticationPolicy(settings["auth.file"],
                                                   __name__),
        authorization_policy=AuthorizationPolicy(),
        route_prefix=ROUTE_PREFIX,
    )
    config.include("pyramid_exclog")
    config.include("cornice")
    config.add_forbidden_view(forbidden)
    config.add_view(precondition, context=HTTPPreconditionFailed)
    config.add_request_method(request_params, "params", reify=True)
    config.add_request_method(authenticated_role, reify=True)
    config.add_request_method(check_accreditations)
    config.add_request_method(get_currency_rates,
                              name="currency_rates",
                              reify=True)
    config.add_renderer("json", JSON(serializer=simplejson.dumps))
    config.add_renderer("prettyjson",
                        JSON(indent=4, serializer=simplejson.dumps))
    config.add_renderer(
        "jsonp", JSONP(param_name="opt_jsonp", serializer=simplejson.dumps))
    config.add_renderer(
        "prettyjsonp",
        JSONP(indent=4, param_name="opt_jsonp", serializer=simplejson.dumps))

    # search for plugins
    plugins = settings.get("plugins") and [
        plugin.strip() for plugin in settings["plugins"].split(",")
    ]
    for entry_point in iter_entry_points("openprocurement.api.plugins"):
        if not plugins or entry_point.name in plugins:
            plugin = entry_point.load()
            plugin(config)

    # CouchDB connection
    aserver, server, db = set_api_security(settings)
    config.registry.couchdb_server = server
    if aserver:
        config.registry.admin_couchdb_server = aserver
    config.registry.db = db

    # CouchDB specific databases connections
    config.registry.databases = Databases(
        admin_connection=aserver or server,
        connection=server,
        migrations=settings.get("couchdb.migrations_db_name"),
        frameworks=settings.get("couchdb.frameworks_db_name"),
        submissions=settings.get("couchdb.submissions_db_name"),
        qualifications=settings.get("couchdb.qualifications_db_name"),
        agreements=settings.get("couchdb.agreements_db_name"),
        transfers=settings.get("couchdb.transfers_db_name"),
        plans=settings.get("couchdb.plans_db_name"),
        contracts=settings.get("couchdb.contracts_db_name"),
    )

    # readjust couchdb json decoder
    couchdb_json_decode()

    # Document Service key
    config.registry.docservice_url = settings.get("docservice_url")
    config.registry.docservice_username = settings.get("docservice_username")
    config.registry.docservice_password = settings.get("docservice_password")
    config.registry.docservice_upload_url = settings.get(
        "docservice_upload_url")

    signing_key = settings.get('dockey', '')
    signer = SigningKey(
        signing_key,
        encoder=HexEncoder) if signing_key else SigningKey.generate()
    config.registry.docservice_key = signer
    verifier = signer.verify_key

    config.registry.keyring = {
        verifier.encode(encoder=HexEncoder)[:8].decode(): verifier
    }
    dockeys = settings.get('dockeys', '')
    for key in dockeys.split('\0'):
        if key:
            config.registry.keyring[key[:8]] = VerifyKey(key,
                                                         encoder=HexEncoder)

    # migrate data
    if not os.environ.get("MIGRATION_SKIP"):
        for entry_point in iter_entry_points("openprocurement.api.migrations"):
            plugin = entry_point.load()
            plugin(config.registry)

    config.registry.server_id = settings.get("id", "")

    # search subscribers
    subscribers_keys = [k for k in settings if k.startswith("subscribers.")]
    for k in subscribers_keys:
        subscribers = settings[k].split(",")
        for subscriber in subscribers:
            for entry_point in iter_entry_points(
                    "openprocurement.{}".format(k), subscriber):
                if entry_point:
                    plugin = entry_point.load()
                    plugin(config)

    config.registry.health_threshold = float(
        settings.get("health_threshold", 512))
    config.registry.health_threshold_func = settings.get(
        "health_threshold_func", "all")
    config.registry.update_after = asbool(settings.get("update_after", True))
    return config.make_wsgi_app()