Пример #1
0
async def create_app():
    app = web.Application()
    app.on_startup.append(on_startup)
    aiohttp_jinja2.setup(app, loader=jinja2.FileSystemLoader('templates'))
    aiojobs_setup(app)
    app.add_routes([web.static('/static', 'static')])
    app.router.add_get('/hello', hello_handler)
    # app.router.add_post('/cow', job_handler)
    app.add_routes([web.get('/ws', ws_handler)])
    app.add_routes(routes)

    return app
Пример #2
0
async def create_app():
    """
    Create web application and manage connection to redis
    :return: instance of application
    """
    app = web.Application()
    jinja_env = aiohttp_jinja2.setup(
        app, loader=jinja2.FileSystemLoader('templates'))

    for route in routes:
        app.router.add_route(**route)
    startup_tasks = [startup]
    app.on_startup.extend(startup_tasks)
    app.on_cleanup.append(cleanup)
    aiojobs_setup(app)
    return app
Пример #3
0
async def test_atomic(test_client):
    @atomic
    async def handler(request):
        await asyncio.sleep(0)
        return web.Response()

    app = web.Application()
    app.router.add_get('/', handler)
    aiojobs_setup(app)

    client = await test_client(app)
    resp = await client.get('/')
    assert resp.status == 200

    scheduler = get_scheduler_from_app(app)

    assert scheduler.active_count == 0
    assert scheduler.pending_count == 0
Пример #4
0
async def test_nested_application(test_client):
    app = web.Application()
    aiojobs_setup(app)

    app2 = web.Application()

    class MyView(web.View):
        async def get(self):
            assert get_scheduler_from_request(self.request) ==\
                get_scheduler_from_app(app)
            return web.Response()

    app2.router.add_route("*", "/", MyView)
    app.add_subapp("/sub/", app2)

    client = await test_client(app)
    resp = await client.get("/sub/")
    assert resp.status == 200
Пример #5
0
async def test_atomic_from_view(test_client):
    app = web.Application()

    class MyView(web.View):
        @atomic
        async def get(self):
            return web.Response()

    app.router.add_route("*", "/", MyView)
    aiojobs_setup(app)

    client = await test_client(app)
    resp = await client.get('/')
    assert resp.status == 200

    scheduler = get_scheduler_from_app(app)

    assert scheduler.active_count == 0
    assert scheduler.pending_count == 0
Пример #6
0
async def test_plugin(test_client):
    job = None

    async def coro():
        await asyncio.sleep(10)

    async def handler(request):
        nonlocal job

        job = await spawn(request, coro())
        assert not job.closed
        return web.Response()

    app = web.Application()
    app.router.add_get('/', handler)
    aiojobs_setup(app)

    client = await test_client(app)
    resp = await client.get('/')
    assert resp.status == 200

    assert job.active
    await client.close()
    assert job.closed
Пример #7
0
def setup_postschema(app, appname: str, *,
                     plugin_config={},
                     extra_config={},
                     after_create=[],
                     **app_config):

    roles = app_config.get('roles', [])
    ROLES = frozenset(role.title() for role in DEFAULT_ROLES | set(roles))
    os.environ['ROLES'] = dumps(ROLES)

    app_config = AppConfig(**app_config)
    app_config.initial_logging_context['version'] = app_config.version
    app_config.initial_logging_context['app_mode'] = app_config.app_mode = os.environ.get('APP_MODE')

    plugin_config = PluginConfig(**plugin_config)

    url_prefix = app_config.url_prefix

    if url_prefix and not url_prefix.startswith('/'):
        url_prefix = '/' + url_prefix
    if url_prefix.endswith('/'):
        url_prefix = url_prefix[:-1]

    app.app_name = appname
    app.url_prefix = url_prefix
    app.app_mode = app_config.app_mode
    app.app_description = app_config.description
    app.version = app_config.version
    app.queries = {
        os.path.split(filename)[1].rsplit('.', 1)[0]: open(filename).read().strip()
        for filename in glob(str(Q_PATTERN))
    }

    # create loggers
    info_logger, error_logger, access_logger = setup_logging(
        app_config.info_logger_processors,
        app_config.error_logger_processors,
        app_config.default_logging_level)

    from . import middlewares
    from .actor import PrincipalActor
    from .core import Base
    from .provision_db import setup_db
    from .scope import ScopeBase
    from .workspace import Workspace  # noqa

    ScopeBase._validate_roles(ROLES)

    # setup middlewares
    app.middlewares.append(middlewares.postschema_middleware)

    app.info_logger = info_logger.new(**app_config.initial_logging_context)
    app.error_logger = error_logger.new(**app_config.initial_logging_context)
    app.access_logger = access_logger.new(**app_config.initial_logging_context)

    aiojobs_setup(app, exception_handler=exception_handler(app.error_logger))

    aiohttp_jinja2.setup(app, loader=jinja2.FileSystemLoader(
        [AUTH_TEMPLATES_DIR, *app_config.template_dirs]
    ))

    if not app_config.redirect_reset_password_to:
        app_config.redirect_reset_password_to = redirect_reset_password_to = '/passform/{checkcode}/'
        app.add_routes(
            [aiohttp.web.get(redirect_reset_password_to, pass_reset_checkcode_template)]
        )
    else:
        app.add_routes(
            [aiohttp.web.get(app_config.redirect_reset_password_to, pass_reset_checkcode_raw)]
        )

    if not app_config.password_reset_form_link:
        app_config.password_reset_form_link = '{scheme}passform/{checkcode}/'

    app.on_startup.extend([startup, init_resources])
    app.on_cleanup.append(cleanup)

    if app_config.alembic_dest is None:
        stack = inspect.stack()
        stack_frame = stack[1]
        calling_module_path = Path(inspect.getmodule(stack_frame[0]).__file__).parent
        os.environ.setdefault('POSTCHEMA_INSTANCE_PATH', str(calling_module_path))
    else:
        alembic_destination = str(app_config.alembic_dest)
        assert os.path.exists(alembic_destination),\
            "`alembic_dest` argument doesn't point to an existing directory"
        os.environ.setdefault('POSTCHEMA_INSTANCE_PATH', alembic_destination)

    app_config.activation_email_html = jinja2.Template(app_config.activation_email_html)
    app_config.invitation_email_html = jinja2.Template(app_config.invitation_email_html)
    app_config.reset_pass_email_html = jinja2.Template(app_config.reset_pass_email_html)
    app_config.verification_email_html = jinja2.Template(app_config.verification_email_html)

    config = ConfigBearer(**extra_config, **plugin_config.__dict__)

    # extend with immutable config opts
    app_config._update(ImmutableConfig(scopes=ScopeBase._scopes))
    config.update(app_config.__dict__)
    app.config = config
    app.scopes = frozenset(ScopeBase._scopes)
    app.allowed_roles = frozenset([role for role in ROLES if role not in ['Admin', '*', 'Owner']])

    app.principal_actor_schema = PrincipalActor
    app.schemas = registered_schemas
    app.config.roles = ROLES
    app.send_sms = app_config.send_sms or default_send_sms
    app.invitation_link = app_config.invitation_link
    app.created_email_confirmation_link = app_config.created_email_confirmation_link.format(
        url_prefix=url_prefix)
    app.invited_email_confirmation_link = app_config.invited_email_confirmation_link.format(
        url_prefix=url_prefix)

    # build the views
    router, openapi_spec = build_app(app, registered_schemas)

    # hash the spec
    app.spec_hash = md5(dumps(openapi_spec).encode()).hexdigest()

    # map paths to roles
    app.paths_by_roles = PathReturner(openapi_spec, router)

    # parse plugins
    installed_plugins = {}
    for plugin in app_config.plugins:
        print(f"* Installing plugin {plugin}...")
        assert plugin in ['shield', 'sentry'], f'Plugin `{plugin}` is not recognized'
        installed_plugins[plugin] = plugin_module = import_module(f'.{plugin}', 'postschema')
        with suppress(AttributeError, TypeError):
            plugin_module.install(app)

    app.installed_plugins = installed_plugins.keys()

    @auth(roles=['Admin'])
    @aiohttp_jinja2.template('redoc.html')
    async def apidoc(request):
        return {'appname': request.app.app_name}

    @auth(roles=['Admin'])
    async def apispec_context(request):
        return json_response(openapi_spec)

    @auth(roles=['*'], email_verified=False)
    async def actor_apispec(request):
        '''OpenAPI JSON spec filtered to include only the public
        and requester-specific routes.
        '''
        request.app.paths_by_roles.roles = set(request.session.roles)
        return json_response(request.app.paths_by_roles.paths_by_roles)

    try:
        app.info_logger.debug("Provisioning DB...")
        setup_db(Base, after_create)
        app.info_logger.debug("DB provisioning done")
    except Exception:
        app.error_logger.exception("Provisioning failed", exc_info=True)
        raise

    router.add_get(f'{url_prefix}/doc/', apidoc)
    router.add_get(f'{url_prefix}/doc/openapi.yaml', apispec_context)
    router.add_get(f'{url_prefix}/doc/spec.json', actor_apispec)
    router.add_get(f'{url_prefix}/doc/meta/', apispec_metainfo)