示例#1
0
def make_aiohttp_application():
    middlewares = [resolve_dotted_name(m) for m in app_settings.get('middlewares', [])]
    router_klass = app_settings.get('router', TraversalRouter)
    router = resolve_dotted_name(router_klass)()
    return GuillotinaAIOHTTPApplication(
        router=router,
        middlewares=middlewares,
        **app_settings.get('aiohttp_settings', {}))
示例#2
0
文件: app.py 项目: jordic/guillotina
def make_aiohttp_application():
    middlewares = [resolve_dotted_name(m) for m in app_settings.get('middlewares', [])]
    router_klass = app_settings.get('router', TraversalRouter)
    router = resolve_dotted_name(router_klass)()
    return GuillotinaAIOHTTPApplication(
        router=router,
        middlewares=middlewares,
        **app_settings.get('aiohttp_settings', {}))
示例#3
0
def load_service(_context, service):
    # prevent circular import
    from guillotina.security.utils import protect_view

    service_conf = service["config"]
    factory = resolve_dotted_name(service["klass"])

    permission = service_conf.get("permission",
                                  app_settings.get("default_permission", None))

    protect_view(factory, permission)

    method = service_conf.get("method", "GET")
    default_layer = resolve_dotted_name(
        app_settings.get("default_layer", IDefaultLayer))
    layer = service_conf.get("layer", default_layer)
    name = service_conf.get("name", "")
    content = service_conf.get("context", Interface)
    logger.debug("Defining adapter for "  # noqa
                 "{0:s} {1:s} {2:s} to {3:s} name {4:s}".format(
                     content.__identifier__,
                     app_settings["http_methods"][method].__identifier__,
                     layer.__identifier__,
                     str(factory),
                     name,
                 ))

    if not getattr(factory, "__route__", None):
        factory.__route__ = routes.Route(name)
    else:
        factory.__route__.service_configuration = service_conf
    service_conf["route"] = [str(rp) for rp in factory.__route__.route_parts]

    component.adapter(
        _context,
        factory=(factory, ),
        provides=app_settings["http_methods"][method],
        for_=(content, layer),
        name=factory.__route__.view_name,
    )

    api = app_settings["api_definition"]
    ct_name = content.__identifier__
    if ct_name not in api:
        api[ct_name] = OrderedDict()
    ct_api = api[ct_name]
    if name:
        if "endpoints" not in ct_api:
            ct_api["endpoints"] = OrderedDict()
        if name not in ct_api["endpoints"]:
            ct_api["endpoints"][name] = OrderedDict()
        ct_api["endpoints"][name][method] = OrderedDict(service_conf)
    else:
        ct_api[method] = OrderedDict(service_conf)
示例#4
0
def load_service(_context, service):
    # prevent circular import
    from guillotina.security.utils import protect_view

    service_conf = service['config']
    factory = resolve_dotted_name(service['klass'])

    permission = service_conf.get(
        'permission', app_settings.get('default_permission', None))

    protect_view(factory, permission)

    method = service_conf.get('method', 'GET')
    default_layer = resolve_dotted_name(
        app_settings.get('default_layer', IDefaultLayer))
    layer = service_conf.get('layer', default_layer)
    name = service_conf.get('name', '')
    content = service_conf.get('context', Interface)
    logger.debug('Defining adapter for '  # noqa
                 '{0:s} {1:s} {2:s} to {3:s} name {4:s}'.format(
        content.__identifier__,
        app_settings['http_methods'][method].__identifier__,
        layer.__identifier__,
        str(factory),
        name))

    if not getattr(factory, '__route__', None):
        factory.__route__ = routes.Route(name)
    else:
        factory.__route__.service_configuration = service_conf

    component.adapter(
        _context,
        factory=(factory,),
        provides=app_settings['http_methods'][method],
        for_=(content, layer),
        name=factory.__route__.view_name
    )

    api = app_settings['api_definition']
    ct_name = content.__identifier__
    if ct_name not in api:
        api[ct_name] = OrderedDict()
    ct_api = api[ct_name]
    if name:
        if 'endpoints' not in ct_api:
            ct_api['endpoints'] = OrderedDict()
        if name not in ct_api['endpoints']:
            ct_api['endpoints'][name] = OrderedDict()
        ct_api['endpoints'][name][method] = OrderedDict(service_conf)
    else:
        ct_api[method] = OrderedDict(service_conf)
示例#5
0
def load_service(_context, service):
    # prevent circular import
    from guillotina.security.utils import protect_view

    service_conf = service['config']
    factory = resolve_dotted_name(service['klass'])

    permission = service_conf.get(
        'permission', app_settings.get('default_permission', None))

    protect_view(factory, permission)

    method = service_conf.get('method', 'GET')
    default_layer = resolve_dotted_name(
        app_settings.get('default_layer', IDefaultLayer))
    layer = service_conf.get('layer', default_layer)
    name = service_conf.get('name', '')
    content = service_conf.get('context', Interface)
    logger.debug('Defining adapter for '  # noqa
                 '{0:s} {1:s} {2:s} to {3:s} name {4:s}'.format(
        content.__identifier__,
        app_settings['http_methods'][method].__identifier__,
        layer.__identifier__,
        str(factory),
        name))

    if not getattr(factory, '__route__', None):
        factory.__route__ = routes.Route(name)
    else:
        factory.__route__.service_configuration = service_conf

    component.adapter(
        _context,
        factory=(factory,),
        provides=app_settings['http_methods'][method],
        for_=(content, layer),
        name=factory.__route__.view_name
    )

    api = app_settings['api_definition']
    ct_name = content.__identifier__
    if ct_name not in api:
        api[ct_name] = OrderedDict()
    ct_api = api[ct_name]
    if name:
        if 'endpoints' not in ct_api:
            ct_api['endpoints'] = OrderedDict()
        if name not in ct_api['endpoints']:
            ct_api['endpoints'][name] = OrderedDict()
        ct_api['endpoints'][name][method] = OrderedDict(service_conf)
    else:
        ct_api[method] = OrderedDict(service_conf)
示例#6
0
def update_app_settings(settings):
    for key, value in settings.items():
        if (isinstance(app_settings.get(key), dict) and
                isinstance(value, dict)):
            app_settings[key].update(value)
        else:
            app_settings[key] = value
示例#7
0
 async def __aenter__(self):
     self.requester = await self.get_requester()
     resp, status = await self.requester(
         "POST",
         "/db",
         data=json.dumps({
             "@type":
             "Container",
             # to be able to register for tests
             "@addons":
             app_settings.get("__test_addons__") or [],
             "title":
             "Guillotina Container",
             "id":
             "guillotina",
             "description":
             "Description Guillotina Container",
         }),
     )
     assert status == 200
     for addon in self.install:
         await self.requester("POST",
                              "/db/guillotina/@addons",
                              data=json.dumps({"id": addon}))
     return self.requester
示例#8
0
def update_app_settings(settings):
    for key, value in settings.items():
        if (isinstance(app_settings.get(key), dict)
                and isinstance(value, dict)):
            app_settings[key].update(value)
        else:
            app_settings[key] = value
示例#9
0
文件: app.py 项目: sunbit/guillotina
def make_app(config_file=None, settings=None, loop=None):
    from guillotina.asgi import AsgiApp

    router_klass = app_settings.get("router", traversal.TraversalRouter)
    app = AsgiApp(config_file, settings, loop,
                  resolve_dotted_name(router_klass)())

    return app
示例#10
0
 def get_conflict_summary(self, oid, txn, old_serial, writer):
     from guillotina.utils import get_current_request
     try:
         req = get_current_request()
     except RequestNotFound:
         req = None
     max_attempts = app_settings.get('conflict_retry_attempts', 3)
     attempts = getattr(req, '_retry_attempt', 0)
     return f'''Object ID: {oid}
示例#11
0
async def addable_types(context, request):
    constrains = IConstrainTypes(context, None)
    types = constrains and constrains.get_allowed_types()
    if types is None:
        types = [
            type_name for type_name in FACTORY_CACHE
            if constrains.is_globally_allowed(type_name)
        ]
    container_types = app_settings.get("container_types", [])
    types = [item for item in types if item not in container_types]
    return types
示例#12
0
 async def __aenter__(self):
     self.requester = await self.get_requester()
     resp, status = await self.requester('POST', '/db', data=json.dumps({
         "@type": "Container",
         # to be able to register for tests
         "@addons": app_settings.get('__test_addons__') or [],
         "title": "Guillotina Container",
         "id": "guillotina",
         "description": "Description Guillotina Container"
     }))
     assert status == 200
     return self.requester
示例#13
0
 async def __aenter__(self):
     self.requester = await self.get_requester()
     resp, status = await self.requester('POST', '/db', data=json.dumps({
         "@type": "Container",
         # to be able to register for tests
         "@addons": app_settings.get('__test_addons__') or [],
         "title": "Guillotina Container",
         "id": "guillotina",
         "description": "Description Guillotina Container"
     }))
     assert status == 200
     return self.requester
示例#14
0
    def __init__(self, context, request, field):
        self.context = context
        self.request = request
        self.field = field

        iface = resolve_dotted_name(app_settings["cloud_storage"])
        alsoProvides(field, iface)

        self.file_storage_manager = get_multi_adapter((context, request, field), IFileStorageManager)
        self.dm = get_adapter(
            self.file_storage_manager, IUploadDataManager, name=app_settings.get("cloud_datamanager") or "db"
        )
示例#15
0
    def __init__(self, context, request, field):
        self.context = context
        self.request = request
        self.field = field

        iface = import_class(app_settings['cloud_storage'])
        alsoProvides(field, iface)

        self.file_storage_manager = get_multi_adapter(
            (context, request, field), IFileStorageManager)
        self.dm = get_adapter(self.file_storage_manager,
                              IUploadDataManager,
                              name=app_settings.get('cloud_datamanager')
                              or 'db')
示例#16
0
 def generate_error_response(self, e, request, error, status=500):
     # We may need to check the roles of the users to show the real error
     eid = uuid.uuid4().hex
     if isinstance(e, asyncio.CancelledError):  # pragma: no cover
         message = _("Cancelled execution of view") + " " + eid
         logger.warning(message, exc_info=e, eid=eid, request=request)
     else:
         message = _("Error on execution of view") + " " + eid
         logger.error(message, exc_info=e, eid=eid, request=request)
     data = {
         "message": message,
         "reason": error_reasons.UNKNOWN.name,
         "details": error_reasons.UNKNOWN.details,
         "eid": eid,
     }
     if app_settings.get("debug"):
         data["traceback"] = traceback.format_exc()
     return response.HTTPInternalServerError(content=data)
示例#17
0
文件: app.py 项目: jordic/guillotina
 async def _handle(self, request, retries=0):
     aiotask_context.set('request', request)
     try:
         return await super()._handle(request)
     except (ConflictError, TIDConflictError) as e:
         if app_settings.get('conflict_retry_attempts', 3) > retries:
             label = 'DB Conflict detected'
             if isinstance(e, TIDConflictError):
                 label = 'TID Conflict Error detected'
             tid = getattr(getattr(request, '_txn', None), '_tid', 'not issued')
             logger.debug(
                 f'{label}, retrying request, tid: {tid}, retries: {retries + 1})',
                 exc_info=True)
             request._retry_attempt = retries + 1
             request.clear_futures()
             return await self._handle(request, retries + 1)
         logger.error(
             'Exhausted retry attempts for conflict error on tid: {}'.format(
                 getattr(getattr(request, '_txn', None), '_tid', 'not issued')
             ))
         return HTTPConflict()
示例#18
0
 async def _handle(self, request, retries=0):
     aiotask_context.set('request', request)
     try:
         return await super()._handle(request)
     except (ConflictError, TIDConflictError) as e:
         if app_settings.get('conflict_retry_attempts', 3) > retries:
             label = 'DB Conflict detected'
             if isinstance(e, TIDConflictError):
                 label = 'TID Conflict Error detected'
             tid = getattr(getattr(request, '_txn', None), '_tid', 'not issued')
             logger.debug(
                 f'{label}, retrying request, tid: {tid}, retries: {retries + 1})',
                 exc_info=True)
             request._retry_attempt = retries + 1
             request.clear_futures()
             return await self._handle(request, retries + 1)
         logger.error(
             'Exhausted retry attempts for conflict error on tid: {}'.format(
                 getattr(getattr(request, '_txn', None), '_tid', 'not issued')
             ))
         return HTTPConflict()
示例#19
0
def generate_error_response(e, request, error, status=500):
    # We may need to check the roles of the users to show the real error
    eid = uuid.uuid4().hex
    http_response = query_adapter(e,
                                  IErrorResponseException,
                                  kwargs={
                                      'error': error,
                                      'eid': eid
                                  })
    if http_response is not None:
        return http_response
    message = _('Error on execution of view') + ' ' + eid
    logger.error(message, exc_info=e, eid=eid, request=request)
    data = {
        'message': message,
        'reason': error_reasons.UNKNOWN.name,
        'details': error_reasons.UNKNOWN.details,
        'eid': eid
    }
    if app_settings.get('debug'):
        data['traceback'] = traceback.format_exc()
    return response.HTTPInternalServerError(content=data)
示例#20
0
def generate_error_response(e, request, error, status=500):
    # We may need to check the roles of the users to show the real error
    eid = uuid.uuid4().hex
    http_response = query_adapter(e,
                                  IErrorResponseException,
                                  kwargs={
                                      "error": error,
                                      "eid": eid
                                  })
    if http_response is not None:
        return http_response
    message = _("Error on execution of view") + " " + eid
    logger.error(message, exc_info=e, eid=eid, request=request)
    data = {
        "message": message,
        "reason": error_reasons.UNKNOWN.name,
        "details": error_reasons.UNKNOWN.details,
        "eid": eid,
    }
    if app_settings.get("debug"):
        data["traceback"] = traceback.format_exc()
    return response.HTTPInternalServerError(content=data)
示例#21
0
文件: app.py 项目: Inqbus/guillotina
 async def _handle(self, request, retries=0):
     task_vars.request.set(request)
     for var in (
             "txn",
             "tm",
             "futures",
             "authenticated_user",
             "security_policies",
             "container",
             "registry",
             "db",
     ):
         # and make sure to reset various task vars...
         getattr(task_vars, var).set(None)
     try:
         return await super()._handle(request)
     except (ConflictError, TIDConflictError) as e:
         if app_settings.get("conflict_retry_attempts", 3) > retries:
             label = "DB Conflict detected"
             if isinstance(e, TIDConflictError):
                 label = "TID Conflict Error detected"
             tid = getattr(getattr(request, "_txn", None), "_tid",
                           "not issued")
             logger.debug(
                 f"{label}, retrying request, tid: {tid}, retries: {retries + 1})",
                 exc_info=True)
             request._retry_attempt = retries + 1
             request.clear_futures()
             return await self._handle(request, retries + 1)
         logger.error(
             "Exhausted retry attempts for conflict error on tid: {}".
             format(
                 getattr(getattr(request, "_txn", None), "_tid",
                         "not issued")))
         return HTTPConflict(body=json.dumps({"summary": str(e)}),
                             content_type="application/json")
示例#22
0
    async def real_resolve(self, request: IRequest) -> Optional[MatchInfo]:
        """Main function to resolve a request."""
        if request.method not in app_settings['http_methods']:
            raise HTTPMethodNotAllowed(
                method=request.method,
                allowed_methods=[
                    k for k in app_settings['http_methods'].keys()
                ])
        method = app_settings['http_methods'][request.method]

        try:
            resource, tail = await self.traverse(request)
        except ConflictError:
            # can also happen from connection errors so we bubble this...
            raise
        except Exception as _exc:
            logger.error('Unhandled exception occurred', exc_info=True)
            request.resource = request.tail = None
            request.exc = _exc
            data = {
                'success': False,
                'exception_message': str(_exc),
                'exception_type': getattr(type(_exc), '__name__',
                                          str(type(_exc))),  # noqa
            }
            if app_settings.get('debug'):
                data['traceback'] = traceback.format_exc()
            raise HTTPBadRequest(content={'reason': data})

        request.record('traversed')

        await notify(ObjectLoadedEvent(resource))
        request.resource = resource
        request.tail = tail

        if request.resource is None:
            await notify(TraversalResourceMissEvent(request, tail))
            raise HTTPNotFound(content={"reason": 'Resource not found'})

        if tail and len(tail) > 0:
            # convert match lookups
            view_name = routes.path_to_view_name(tail)
        elif not tail:
            view_name = ''

        request.record('beforeauthentication')
        authenticated = await authenticate_request(request)
        # Add anonymous participation
        if authenticated is None:
            authenticated = AnonymousUser()
            set_authenticated_user(authenticated)
        request.record('authentication')

        policy = get_security_policy(authenticated)

        for language in get_acceptable_languages(request):
            translator = query_adapter((resource, request),
                                       ILanguage,
                                       name=language)
            if translator is not None:
                resource = translator.translate()
                break

        # container registry lookup
        try:
            view = query_multi_adapter((resource, request),
                                       method,
                                       name=view_name)
        except AttributeError:
            view = None

        if view is None and method == IOPTIONS:
            view = DefaultOPTIONS(resource, request)

        # Check security on context to AccessContent unless
        # is view allows explicit or its OPTIONS
        permission = get_utility(IPermission, name='guillotina.AccessContent')
        if not policy.check_permission(permission.id, resource):
            # Check if its a CORS call:
            if IOPTIONS != method:
                # Check if the view has permissions explicit
                if view is None or not view.__allow_access__:
                    logger.info(
                        "No access content {content} with {auth}".format(
                            content=resource, auth=authenticated.id),
                        request=request)
                    raise HTTPUnauthorized(
                        content={
                            "reason":
                            "You are not authorized to access content",
                            "content": str(resource),
                            "auth": authenticated.id
                        })

        if not view and len(tail) > 0:
            # we should have a view in this case because we are matching routes
            await notify(TraversalViewMissEvent(request, tail))
            return None

        request.found_view = view
        request.view_name = view_name
        request.record('viewfound')

        ViewClass = view.__class__
        view_permission = get_view_permission(ViewClass)
        if view_permission is None:
            # use default view permission
            view_permission = app_settings['default_permission']
        if not policy.check_permission(view_permission, view):
            if IOPTIONS != method:
                raise HTTPUnauthorized(
                    content={
                        "reason": "You are not authorized to view",
                        "content": str(resource),
                        "auth": authenticated.id
                    })

        try:
            view.__route__.matches(request, tail or [])
        except (KeyError, IndexError):
            await notify(TraversalRouteMissEvent(request, tail))
            return None
        except AttributeError:
            pass

        if hasattr(view, 'prepare'):
            view = (await view.prepare()) or view

        request.record('authorization')

        return MatchInfo(resource, request, view)
示例#23
0
async def make_app(config_file=None, settings=None, loop=None, server_app=None):
    '''
    Make application from configuration

    :param config_file: path to configuration file to load
    :param settings: dictionary of settings
    :param loop: if not using with default event loop
    :param settings: provide your own aiohttp application
    '''
    # reset app_settings
    startup_vars = {}
    for key in app_settings.keys():
        if key[0] == '_':
            startup_vars[key] = app_settings[key]

    app_settings.clear()
    app_settings.update(startup_vars)
    app_settings.update(deepcopy(default_settings))

    if loop is None:
        loop = asyncio.get_event_loop()

    # chainmap task factory is actually very important
    # default task factory uses inheritance in a way
    # that bubbles back down. So it's possible for a sub-task
    # to clear out the request of the parent task
    loop.set_task_factory(aiotask_context.chainmap_task_factory)

    if config_file is not None:
        with open(config_file, 'r') as config:
            settings = json.load(config)
    elif settings is None:
        raise Exception('Neither configuration or settings')

    # Create root Application
    root = ApplicationRoot(config_file, loop)
    provide_utility(root, IApplication, 'root')

    # Initialize global (threadlocal) ZCA configuration
    config = root.config = ConfigurationMachine()

    app_configurator = ApplicationConfigurator(
        settings.get('applications') or [],
        config, root, settings
    )

    configure.scan('guillotina.renderers')
    configure.scan('guillotina.api')
    configure.scan('guillotina.content')
    configure.scan('guillotina.registry')
    configure.scan('guillotina.auth')
    configure.scan('guillotina.json')
    configure.scan('guillotina.behaviors')
    configure.scan('guillotina.languages')
    configure.scan('guillotina.permissions')
    configure.scan('guillotina.security.security_local')
    configure.scan('guillotina.security.policy')
    configure.scan('guillotina.auth.participation')
    configure.scan('guillotina.catalog.index')
    configure.scan('guillotina.catalog.catalog')
    configure.scan('guillotina.files')
    configure.scan('guillotina.annotations')
    configure.scan('guillotina.constraintypes')
    configure.scan('guillotina.subscribers')
    configure.scan('guillotina.db.strategies')
    configure.scan('guillotina.db.cache')
    configure.scan('guillotina.db.writer')
    configure.scan('guillotina.db.factory')
    configure.scan('guillotina.exc_resp')
    configure.scan('guillotina.fields')
    configure.scan('guillotina.migrations')

    # always load guillotina
    app_configurator.configure_application('guillotina')
    app_configurator.configure_all_applications()

    apply_concrete_behaviors()

    # update *after* plugins loaded
    update_app_settings(settings)

    if 'logging' in app_settings:
        try:
            logging.config.dictConfig(app_settings['logging'])
        except Exception:
            logger.error('Could not setup logging configuration', exc_info=True)

    # Make and initialize aiohttp app
    if server_app is None:
        server_app = make_aiohttp_application()
    root.app = server_app
    server_app.root = root
    server_app.config = config

    optimize_settings(app_settings)

    await notify(ApplicationConfiguredEvent(server_app, loop))

    for key, dbconfig in list_or_dict_items(app_settings['databases']):
        factory = get_utility(
            IDatabaseConfigurationFactory, name=dbconfig['storage'])
        root[key] = await factory(key, dbconfig, loop)
        await notify(DatabaseInitializedEvent(root[key]))

    for key, file_path in list_or_dict_items(app_settings['static']):
        path = resolve_path(file_path).resolve()
        if not path.exists():
            raise Exception('Invalid static directory {}'.format(file_path))
        if path.is_dir():
            root[key] = StaticDirectory(path)
        else:
            root[key] = StaticFile(path)

    for key, file_path in list_or_dict_items(app_settings['jsapps']):
        path = resolve_path(file_path).resolve()
        if not path.exists() or not path.is_dir():
            raise Exception('Invalid jsapps directory {}'.format(file_path))
        root[key] = JavaScriptApplication(path)

    root.set_root_user(app_settings['root_user'])

    if app_settings.get('jwk') and\
            app_settings.get('jwk').get('k') and\
            app_settings.get('jwk').get('kty'):
        key = jwk.JWK.from_json(json.dumps(app_settings.get('jwk')))
        app_settings['jwk'] = key
        # {"k":"QqzzWH1tYqQO48IDvW7VH7gvJz89Ita7G6APhV-uLMo","kty":"oct"}

    if not app_settings.get('debug') and app_settings['jwt'].get('secret'):
        # validate secret
        secret = app_settings['jwt']['secret']
        if secret == 'secret':
            logger.warning(
                'You are using a very insecure secret key in production mode. '
                'It is strongly advised that you provide a better value for '
                '`jwt.secret` in your config.')
        elif not secure_passphrase(app_settings['jwt']['secret']):
            logger.warning(
                'You are using a insecure secret key in production mode. '
                'It is recommended that you provide a more complex value for '
                '`jwt.secret` in your config.')

    # Set router root
    server_app.router.set_root(root)
    server_app.on_cleanup.append(cleanup_app)

    for util in app_settings.get('utilities') or []:
        logger.warn('Adding : ' + util['provides'])
        root.add_async_utility(util['provides'], util, loop=loop)

    for key, util in app_settings['load_utilities'].items():
        logger.info('Adding ' + key + ' : ' + util['provides'])
        root.add_async_utility(key, util, loop=loop)

    # Load cached Schemas
    load_cached_schema()

    await notify(ApplicationInitializedEvent(server_app, loop))

    return server_app
示例#24
0
 def executor(self):
     if self._executor is None:
         self._executor = ThreadPoolExecutor(
             max_workers=app_settings.get("thread_pool_workers", 32))
     return self._executor
示例#25
0
async def make_app(config_file=None,
                   settings=None,
                   loop=None,
                   server_app=None):
    '''
    Make application from configuration

    :param config_file: path to configuration file to load
    :param settings: dictionary of settings
    :param loop: if not using with default event loop
    :param settings: provide your own aiohttp application
    '''
    # reset app_settings
    startup_vars = {}
    for key in app_settings.keys():
        if key[0] == '_':
            startup_vars[key] = app_settings[key]

    app_settings.clear()
    app_settings.update(startup_vars)
    app_settings.update(default_settings)

    if loop is None:
        loop = asyncio.get_event_loop()

    # chainmap task factory is actually very important
    # default task factory uses inheritance in a way
    # that bubbles back down. So it's possible for a sub-task
    # to clear out the request of the parent task
    loop.set_task_factory(aiotask_context.chainmap_task_factory)

    if config_file is not None:
        with open(config_file, 'r') as config:
            settings = json.load(config)
    elif settings is None:
        raise Exception('Neither configuration or settings')

    # Create root Application
    root = ApplicationRoot(config_file, loop)
    provide_utility(root, IApplication, 'root')

    # Initialize global (threadlocal) ZCA configuration
    config = root.config = ConfigurationMachine()

    import guillotina
    import guillotina.db.factory
    import guillotina.db.writer
    import guillotina.db.db
    configure.scan('guillotina.renderers')
    configure.scan('guillotina.api')
    configure.scan('guillotina.content')
    configure.scan('guillotina.registry')
    configure.scan('guillotina.auth')
    configure.scan('guillotina.json')
    configure.scan('guillotina.behaviors')
    configure.scan('guillotina.languages')
    configure.scan('guillotina.permissions')
    configure.scan('guillotina.security.security_local')
    configure.scan('guillotina.security.policy')
    configure.scan('guillotina.auth.participation')
    configure.scan('guillotina.catalog.index')
    configure.scan('guillotina.catalog.catalog')
    configure.scan('guillotina.files')
    configure.scan('guillotina.annotations')
    configure.scan('guillotina.constraintypes')
    configure.scan('guillotina.subscribers')
    configure.scan('guillotina.db.strategies')
    configure.scan('guillotina.db.cache')
    configure.scan('guillotina.exc_resp')
    configure.scan('guillotina.fields')
    configure.scan('guillotina.migrations')
    load_application(guillotina, root, settings)
    config.execute_actions()
    config.commit()

    configured = ['guillotina']
    for module_name in settings.get('applications') or []:
        configure_application(module_name, config, root, settings, configured)

    apply_concrete_behaviors()

    # update *after* plugins loaded
    update_app_settings(settings)

    if 'logging' in app_settings:
        logging.config.dictConfig(app_settings['logging'])

    # Make and initialize aiohttp app
    if server_app is None:
        server_app = make_aiohttp_application()
    root.app = server_app
    server_app.root = root
    server_app.config = config

    optimize_settings(app_settings)

    await notify(ApplicationConfiguredEvent(server_app, loop))

    for key, dbconfig in list_or_dict_items(app_settings['databases']):
        factory = get_utility(IDatabaseConfigurationFactory,
                              name=dbconfig['storage'])
        root[key] = await factory(key, dbconfig, loop)
        await notify(DatabaseInitializedEvent(root[key]))

    for key, file_path in list_or_dict_items(app_settings['static']):
        path = resolve_path(file_path).resolve()
        if not path.exists():
            raise Exception('Invalid static directory {}'.format(file_path))
        if path.is_dir():
            root[key] = StaticDirectory(path)
        else:
            root[key] = StaticFile(path)

    for key, file_path in list_or_dict_items(app_settings['jsapps']):
        path = resolve_path(file_path).resolve()
        if not path.exists() or not path.is_dir():
            raise Exception('Invalid jsapps directory {}'.format(file_path))
        root[key] = JavaScriptApplication(path)

    root.set_root_user(app_settings['root_user'])

    if app_settings.get('jwk') and\
            app_settings.get('jwk').get('k') and\
            app_settings.get('jwk').get('kty'):
        key = jwk.JWK.from_json(json.dumps(app_settings.get('jwk')))
        app_settings['jwk'] = key
        # {"k":"QqzzWH1tYqQO48IDvW7VH7gvJz89Ita7G6APhV-uLMo","kty":"oct"}

    if not app_settings.get('debug') and app_settings['jwt'].get('secret'):
        # validate secret
        secret = app_settings['jwt']['secret']
        if secret == 'secret':
            logger.warning(
                'You are using a very insecure secret key in production mode. '
                'It is strongly advised that you provide a better value for '
                '`jwt.secret` in your config.')
        elif not secure_passphrase(app_settings['jwt']['secret']):
            logger.warning(
                'You are using a insecure secret key in production mode. '
                'It is recommended that you provide a more complex value for '
                '`jwt.secret` in your config.')

    # Set router root
    server_app.router.set_root(root)
    server_app.on_cleanup.append(cleanup_app)

    for util in app_settings.get('utilities') or []:
        logger.warn('Adding : ' + util['provides'])
        root.add_async_utility(util['provides'], util, loop=loop)

    for key, util in app_settings['load_utilities'].items():
        logger.info('Adding ' + key + ' : ' + util['provides'])
        root.add_async_utility(key, util, loop=loop)

    # Load cached Schemas
    load_cached_schema()

    await notify(ApplicationInitializedEvent(server_app, loop))

    return server_app
示例#26
0
def make_app(config_file=None, settings=None, loop=None, server_app=None):
    app_settings.update(_delayed_default_settings)

    if loop is None:
        loop = asyncio.get_event_loop()

    loop.set_task_factory(aiotask_context.task_factory)

    if config_file is not None:
        with open(config_file, 'r') as config:
            settings = json.load(config)
    elif settings is None:
        raise Exception('Neither configuration or settings')

    # Create root Application
    root = ApplicationRoot(config_file)
    provide_utility(root, IApplication, 'root')

    # Initialize global (threadlocal) ZCA configuration
    config = root.config = ConfigurationMachine()

    import guillotina
    import guillotina.db.factory
    import guillotina.db.writer
    import guillotina.db.db
    configure.scan('guillotina.translation')
    configure.scan('guillotina.renderers')
    configure.scan('guillotina.api')
    configure.scan('guillotina.content')
    configure.scan('guillotina.registry')
    configure.scan('guillotina.auth')
    configure.scan('guillotina.json')
    configure.scan('guillotina.behaviors')
    configure.scan('guillotina.languages')
    configure.scan('guillotina.permissions')
    configure.scan('guillotina.security.security_local')
    configure.scan('guillotina.security.policy')
    configure.scan('guillotina.auth.participation')
    configure.scan('guillotina.catalog.index')
    configure.scan('guillotina.catalog.catalog')
    configure.scan('guillotina.framing')
    configure.scan('guillotina.files')
    configure.scan('guillotina.annotations')
    configure.scan('guillotina.constraintypes')
    configure.scan('guillotina.subscribers')
    configure.scan('guillotina.db.strategies')
    configure.scan('guillotina.db.cache')
    load_application(guillotina, root, settings)
    config.execute_actions()
    config.commit()

    for module_name in settings.get('applications', []):
        config.begin(module_name)
        load_application(resolve_dotted_name(module_name), root, settings)
        config.execute_actions()
        config.commit()

    # XXX we clear now to save some memory
    # it's unclear to me if this is necesary or not but it seems to me that
    # we don't need things registered in both components AND here.
    configure.clear()

    # update *after* plugins loaded
    update_app_settings(settings)

    if 'logging' in app_settings:
        logging.config.dictConfig(app_settings['logging'])

    # Make and initialize aiohttp app
    if server_app is None:
        server_app = make_aiohttp_application()
    root.app = server_app
    server_app.root = root
    server_app.config = config

    content_type = ContentNegotiatorUtility('content_type',
                                            app_settings['renderers'].keys())
    language = ContentNegotiatorUtility('language',
                                        app_settings['languages'].keys())

    provide_utility(content_type, IContentNegotiation, 'content_type')
    provide_utility(language, IContentNegotiation, 'language')

    for database in app_settings['databases']:
        for key, dbconfig in database.items():
            factory = get_utility(IDatabaseConfigurationFactory,
                                  name=dbconfig['storage'])
            if asyncio.iscoroutinefunction(factory):
                future = asyncio.ensure_future(factory(key, dbconfig,
                                                       server_app),
                                               loop=loop)

                loop.run_until_complete(future)
                root[key] = future.result()
            else:
                root[key] = factory(key, dbconfig)

    for key, file_path in list_or_dict_items(app_settings['static']):
        path = resolve_path(file_path).resolve()
        if not path.exists():
            raise Exception('Invalid static directory {}'.format(file_path))
        if path.is_dir():
            root[key] = StaticDirectory(path)
        else:
            root[key] = StaticFile(path)
    for key, file_path in list_or_dict_items(app_settings['jsapps']):
        path = resolve_path(file_path).resolve()
        if not path.exists() or not path.is_dir():
            raise Exception('Invalid jsapps directory {}'.format(file_path))
        root[key] = JavaScriptApplication(path)

    root.set_root_user(app_settings['root_user'])

    if RSA is not None and not app_settings.get('rsa'):
        key = RSA.generate(2048)
        pub_jwk = {'k': key.publickey().exportKey('PEM')}
        priv_jwk = {'k': key.exportKey('PEM')}
        app_settings['rsa'] = {'pub': pub_jwk, 'priv': priv_jwk}

    # Set router root
    server_app.router.set_root(root)

    for utility in get_all_utilities_registered_for(IAsyncUtility):
        # In case there is Utilties that are registered
        if hasattr(utility, 'initialize'):
            task = asyncio.ensure_future(lazy_apply(utility.initialize,
                                                    app=server_app),
                                         loop=loop)
            root.add_async_task(utility, task, {})
        else:
            logger.warn(f'No initialize method found on {utility} object')

    server_app.on_cleanup.append(close_utilities)

    for util in app_settings['utilities']:
        root.add_async_utility(util, loop=loop)

    # Load cached Schemas
    load_cached_schema()

    optimize_settings(app_settings)

    return server_app
示例#27
0
    async def real_resolve(self, request: IRequest) -> MatchInfo:
        """Main function to resolve a request."""
        security = get_adapter(request, IInteraction)

        if request.method not in app_settings['http_methods']:
            raise HTTPMethodNotAllowed()
        method = app_settings['http_methods'][request.method]

        language = language_negotiation(request)
        language_object = language(request)

        try:
            resource, tail = await self.traverse(request)
        except ConflictError:
            # can also happen from connection errors so we bubble this...
            raise
        except Exception as _exc:
            logger.error('Unhandled exception occurred', exc_info=True)
            request.resource = request.tail = None
            request.exc = _exc
            data = {
                'success': False,
                'exception_message': str(_exc),
                'exception_type': getattr(type(_exc), '__name__',
                                          str(type(_exc))),  # noqa
            }
            if app_settings.get('debug'):
                data['traceback'] = traceback.format_exc()
            raise HTTPBadRequest(text=ujson.dumps(data))

        request.record('traversed')

        await notify(ObjectLoadedEvent(resource))
        request.resource = resource
        request.tail = tail

        if request.resource is None:
            raise HTTPBadRequest(text='Resource not found')

        traverse_to = None
        if tail and len(tail) == 1:
            view_name = tail[0]
        elif tail is None or len(tail) == 0:
            view_name = ''
        else:
            view_name = tail[0]
            traverse_to = tail[1:]

        request.record('beforeauthentication')
        await self.apply_authorization(request)
        request.record('authentication')

        translator = query_adapter(language_object,
                                   ITranslated,
                                   args=[resource, request])
        if translator is not None:
            resource = translator.translate()

        # Add anonymous participation
        if len(security.participations) == 0:
            security.add(AnonymousParticipation(request))

        # container registry lookup
        try:
            view = query_multi_adapter((resource, request),
                                       method,
                                       name=view_name)
        except AttributeError:
            view = None

        request.found_view = view
        request.view_name = view_name

        # Traverse view if its needed
        if traverse_to is not None and view is not None:
            if not ITraversableView.providedBy(view):
                return None
            else:
                try:
                    view = await view.publish_traverse(traverse_to)
                except KeyError:
                    return None  # not found, it's okay.
                except Exception as e:
                    logger.error("Exception on view execution",
                                 exc_info=e,
                                 request=request)
                    return None

        request.record('viewfound')
        permission = get_utility(IPermission, name='guillotina.AccessContent')

        if not security.check_permission(permission.id, resource):
            # Check if its a CORS call:
            if IOPTIONS != method:
                # Check if the view has permissions explicit
                if view is None or not view.__allow_access__:
                    logger.info(
                        "No access content {content} with {auths}".format(
                            content=resource,
                            auths=str([
                                x.principal.id for x in security.participations
                            ])),
                        request=request)
                    raise HTTPUnauthorized()

        if view is None and method == IOPTIONS:
            view = DefaultOPTIONS(resource, request)

        if view:
            ViewClass = view.__class__
            view_permission = get_view_permission(ViewClass)
            if not security.check_permission(view_permission, view):
                logger.info("No access for view {content} with {auths}".format(
                    content=resource,
                    auths=str(
                        [x.principal.id for x in security.participations])),
                            request=request)
                raise HTTPUnauthorized()

        request.record('authorization')

        renderer = content_type_negotiation(request, resource, view)
        renderer_object = renderer(request)

        rendered = query_multi_adapter((renderer_object, view, request),
                                       IRendered)

        request.record('renderer')

        if rendered is not None:
            return MatchInfo(resource, request, view, rendered)
        else:
            return None
示例#28
0
 async def get_json(self):
     if not app_settings.get('store_json', True):
         return {}
     adapter = query_adapter(self._obj, ICatalogDataAdapter)
     if adapter is not None:
         return await adapter()
示例#29
0
 def serialize(self):
     protocol = app_settings.get("pickle_protocol", pickle.HIGHEST_PROTOCOL)
     return pickle.dumps(self._obj, protocol=protocol)
示例#30
0
 async def get_json(self):
     if not app_settings.get('store_json', False):
         return {}
     adapter = query_adapter(self._obj, IJSONDBSerializer)
     if adapter is not None:
         return await adapter()
示例#31
0
 def get_conflict_summary(self, oid, txn, old_serial, writer):
     from guillotina.utils import get_current_request
     req = get_current_request()
     max_attempts = app_settings.get('conflict_retry_attempts', 3)
     attempts = getattr(req, '_retry_attempt', 0)
     return f'''Object ID: {oid}
示例#32
0
文件: app.py 项目: worasit/guillotina
async def make_app(config_file=None,
                   settings=None,
                   loop=None,
                   server_app=None):

    # reset app_settings
    app_settings.clear()
    app_settings.update(default_settings)

    if loop is None:
        loop = asyncio.get_event_loop()

    # chainmap task factory is actually very important
    # default task factory uses inheritance in a way
    # that bubbles back down. So it's possible for a sub-task
    # to clear out the request of the parent task
    loop.set_task_factory(aiotask_context.chainmap_task_factory)

    if config_file is not None:
        with open(config_file, 'r') as config:
            settings = json.load(config)
    elif settings is None:
        raise Exception('Neither configuration or settings')

    # Create root Application
    root = ApplicationRoot(config_file, loop)
    provide_utility(root, IApplication, 'root')

    # Initialize global (threadlocal) ZCA configuration
    config = root.config = ConfigurationMachine()

    import guillotina
    import guillotina.db.factory
    import guillotina.db.writer
    import guillotina.db.db
    configure.scan('guillotina.renderers')
    configure.scan('guillotina.api')
    configure.scan('guillotina.content')
    configure.scan('guillotina.registry')
    configure.scan('guillotina.auth')
    configure.scan('guillotina.json')
    configure.scan('guillotina.behaviors')
    configure.scan('guillotina.languages')
    configure.scan('guillotina.permissions')
    configure.scan('guillotina.security.security_local')
    configure.scan('guillotina.security.policy')
    configure.scan('guillotina.auth.participation')
    configure.scan('guillotina.catalog.index')
    configure.scan('guillotina.catalog.catalog')
    configure.scan('guillotina.files')
    configure.scan('guillotina.annotations')
    configure.scan('guillotina.constraintypes')
    configure.scan('guillotina.subscribers')
    configure.scan('guillotina.db.strategies')
    configure.scan('guillotina.db.cache')
    configure.scan('guillotina.exc_resp')
    configure.scan('guillotina.fields')
    load_application(guillotina, root, settings)
    config.execute_actions()
    config.commit()

    configured = ['guillotina']
    for module_name in settings.get('applications') or []:
        configure_application(module_name, config, root, settings, configured)

    apply_concrete_behaviors()

    # update *after* plugins loaded
    update_app_settings(settings)

    if 'logging' in app_settings:
        logging.config.dictConfig(app_settings['logging'])

    # Make and initialize aiohttp app
    if server_app is None:
        server_app = make_aiohttp_application()
    root.app = server_app
    server_app.root = root
    server_app.config = config

    optimize_settings(app_settings)

    await notify(ApplicationConfiguredEvent(server_app, loop))

    for key, dbconfig in list_or_dict_items(app_settings['databases']):
        factory = get_utility(IDatabaseConfigurationFactory,
                              name=dbconfig['storage'])
        root[key] = await factory(key, dbconfig, loop)
        await notify(DatabaseInitializedEvent(root[key]))

    for key, file_path in list_or_dict_items(app_settings['static']):
        path = resolve_path(file_path).resolve()
        if not path.exists():
            raise Exception('Invalid static directory {}'.format(file_path))
        if path.is_dir():
            root[key] = StaticDirectory(path)
        else:
            root[key] = StaticFile(path)

    for key, file_path in list_or_dict_items(app_settings['jsapps']):
        path = resolve_path(file_path).resolve()
        if not path.exists() or not path.is_dir():
            raise Exception('Invalid jsapps directory {}'.format(file_path))
        root[key] = JavaScriptApplication(path)

    root.set_root_user(app_settings['root_user'])

    if RSA is not None and not app_settings.get('rsa'):
        key = RSA.generate(2048)
        pub_jwk = {'k': key.publickey().exportKey('PEM')}
        priv_jwk = {'k': key.exportKey('PEM')}
        app_settings['rsa'] = {'pub': pub_jwk, 'priv': priv_jwk}

    # Set router root
    server_app.router.set_root(root)
    server_app.on_cleanup.append(cleanup_app)

    for util in app_settings.get('utilities') or []:
        logger.warn('Adding : ' + util['provides'])
        root.add_async_utility(util['provides'], util, loop=loop)

    for key, util in app_settings['load_utilities'].items():
        logger.info('Adding ' + key + ' : ' + util['provides'])
        root.add_async_utility(key, util, loop=loop)

    # Load cached Schemas
    load_cached_schema()

    await notify(ApplicationInitializedEvent(server_app, loop))

    return server_app
示例#33
0
 async def get_json(self):
     if not app_settings.get('store_json', False):
         return {}
     adapter = query_adapter(self._obj, IJSONDBSerializer)
     if adapter is not None:
         return await adapter()
示例#34
0
文件: app.py 项目: Inqbus/guillotina
async def make_app(config_file=None,
                   settings=None,
                   loop=None,
                   server_app=None):
    """
    Make application from configuration

    :param config_file: path to configuration file to load
    :param settings: dictionary of settings
    :param loop: if not using with default event loop
    :param settings: provide your own aiohttp application
    """
    # reset app_settings
    startup_vars = {}
    for key in app_settings.keys():
        if key[0] == "_":
            startup_vars[key] = app_settings[key]

    app_settings.clear()
    app_settings.update(startup_vars)
    app_settings.update(deepcopy(default_settings))

    if loop is None:
        loop = asyncio.get_event_loop()

    if config_file is not None:
        with open(config_file, "r") as config:
            settings = json.load(config)
    elif settings is None:
        raise Exception("Neither configuration or settings")

    # Create root Application
    root = ApplicationRoot(config_file, loop)
    provide_utility(root, IApplication, "root")

    # Initialize global (threadlocal) ZCA configuration
    config = root.config = ConfigurationMachine()

    app_configurator = ApplicationConfigurator(
        settings.get("applications") or [], config, root, settings)

    configure.scan("guillotina.renderers")
    configure.scan("guillotina.api")
    configure.scan("guillotina.content")
    configure.scan("guillotina.registry")
    configure.scan("guillotina.auth")
    configure.scan("guillotina.json")
    configure.scan("guillotina.behaviors")
    configure.scan("guillotina.languages")
    configure.scan("guillotina.permissions")
    configure.scan("guillotina.security.security_local")
    configure.scan("guillotina.security.policy")
    configure.scan("guillotina.catalog.index")
    configure.scan("guillotina.catalog.catalog")
    configure.scan("guillotina.files")
    configure.scan("guillotina.annotations")
    configure.scan("guillotina.constraintypes")
    configure.scan("guillotina.subscribers")
    configure.scan("guillotina.db.strategies")
    configure.scan("guillotina.db.storages.vacuum")
    configure.scan("guillotina.db.cache")
    configure.scan("guillotina.db.writer")
    configure.scan("guillotina.db.factory")
    configure.scan("guillotina.exc_resp")
    configure.scan("guillotina.fields")
    configure.scan("guillotina.migrations")

    # always load guillotina
    app_configurator.configure_application("guillotina")
    app_configurator.configure_all_applications()

    apply_concrete_behaviors()

    # update *after* plugins loaded
    update_app_settings(settings)

    if "logging" in app_settings:
        try:
            logging.config.dictConfig(app_settings["logging"])
        except Exception:
            app_logger.error("Could not setup logging configuration",
                             exc_info=True)

    # Make and initialize aiohttp app
    if server_app is None:
        server_app = make_aiohttp_application()
    root.app = server_app
    server_app.root = root
    server_app.config = config

    for k, v in _moved.items():
        # for b/w compatibility, convert these
        if k in app_settings:
            app_settings[v] = app_settings[k]
            del app_settings[k]

    optimize_settings(app_settings)

    await notify(ApplicationConfiguredEvent(server_app, loop))

    for key, dbconfig in list_or_dict_items(app_settings["databases"]):
        factory = get_utility(IDatabaseConfigurationFactory,
                              name=dbconfig["storage"])
        root[key] = await factory(key, dbconfig, loop)
        await notify(DatabaseInitializedEvent(root[key]))

    for key, file_path in list_or_dict_items(app_settings["static"]):
        path = resolve_path(file_path).resolve()
        if not path.exists():
            raise Exception("Invalid static directory {}".format(file_path))
        if path.is_dir():
            root[key] = StaticDirectory(path)
        else:
            root[key] = StaticFile(path)

    for key, file_path in list_or_dict_items(app_settings["jsapps"]):
        path = resolve_path(file_path).resolve()
        if not path.exists() or not path.is_dir():
            raise Exception("Invalid jsapps directory {}".format(file_path))
        root[key] = JavaScriptApplication(path)

    root.set_root_user(app_settings["root_user"])

    if app_settings.get("jwk") and app_settings.get("jwk").get(
            "k") and app_settings.get("jwk").get("kty"):
        key = jwk.JWK.from_json(json.dumps(app_settings.get("jwk")))
        app_settings["jwk"] = key
        # {"k":"QqzzWH1tYqQO48IDvW7VH7gvJz89Ita7G6APhV-uLMo","kty":"oct"}

    if not app_settings.get("debug") and app_settings["jwt"].get("secret"):
        # validate secret
        secret = app_settings["jwt"]["secret"]
        if secret == "secret":
            app_logger.warning(
                "You are using a very insecure secret key in production mode. "
                "It is strongly advised that you provide a better value for "
                "`jwt.secret` in your config.")
        elif not secure_passphrase(app_settings["jwt"]["secret"]):
            app_logger.warning(
                "You are using a insecure secret key in production mode. "
                "It is recommended that you provide a more complex value for "
                "`jwt.secret` in your config.")

    # Set router root
    server_app.router.set_root(root)
    server_app.on_cleanup.append(cleanup_app)

    for key, util in app_settings["load_utilities"].items():
        app_logger.info("Adding " + key + " : " + util["provides"])
        await notify(BeforeAsyncUtilityLoadedEvent(key, util))
        result = root.add_async_utility(key, util, loop=loop)
        if result is not None:
            await notify(AfterAsyncUtilityLoadedEvent(key, util, *result))

    # Load cached Schemas
    load_cached_schema()

    await notify(ApplicationInitializedEvent(server_app, loop))

    return server_app
示例#35
0
    async def real_resolve(self, request: IRequest) -> Optional[MatchInfo]:
        """Main function to resolve a request."""
        security = get_adapter(request, IInteraction)

        if request.method not in app_settings['http_methods']:
            raise HTTPMethodNotAllowed(
                method=request.method,
                allowed_methods=[k for k in app_settings['http_methods'].keys()])
        method = app_settings['http_methods'][request.method]

        try:
            resource, tail = await self.traverse(request)
        except ConflictError:
            # can also happen from connection errors so we bubble this...
            raise
        except Exception as _exc:
            logger.error('Unhandled exception occurred', exc_info=True)
            request.resource = request.tail = None
            request.exc = _exc
            data = {
                'success': False,
                'exception_message': str(_exc),
                'exception_type': getattr(type(_exc), '__name__', str(type(_exc))),  # noqa
            }
            if app_settings.get('debug'):
                data['traceback'] = traceback.format_exc()
            raise HTTPBadRequest(content={
                'reason': data
            })

        request.record('traversed')

        await notify(ObjectLoadedEvent(resource))
        request.resource = resource
        request.tail = tail

        if request.resource is None:
            await notify(TraversalResourceMissEvent(request, tail))
            raise HTTPNotFound(content={
                "reason": 'Resource not found'
            })

        if tail and len(tail) > 0:
            # convert match lookups
            view_name = routes.path_to_view_name(tail)
        elif not tail:
            view_name = ''

        request.record('beforeauthentication')
        await self.apply_authorization(request)
        request.record('authentication')

        for language in get_acceptable_languages(request):
            translator = query_adapter((resource, request), ILanguage,
                                       name=language)
            if translator is not None:
                resource = translator.translate()
                break

        # Add anonymous participation
        if len(security.participations) == 0:
            security.add(AnonymousParticipation(request))

        # container registry lookup
        try:
            view = query_multi_adapter(
                (resource, request), method, name=view_name)
        except AttributeError:
            view = None

        if view is None and method == IOPTIONS:
            view = DefaultOPTIONS(resource, request)

        # Check security on context to AccessContent unless
        # is view allows explicit or its OPTIONS
        permission = get_utility(IPermission, name='guillotina.AccessContent')
        if not security.check_permission(permission.id, resource):
            # Check if its a CORS call:
            if IOPTIONS != method:
                # Check if the view has permissions explicit
                if view is None or not view.__allow_access__:
                    logger.info(
                        "No access content {content} with {auths}".format(
                            content=resource,
                            auths=str([x.principal.id
                                       for x in security.participations])),
                        request=request)
                    raise HTTPUnauthorized(
                        content={
                            "reason": "You are not authorized to access content",
                            "content": str(resource),
                            "auths": [x.principal.id
                                      for x in security.participations]
                        }
                    )

        if not view and len(tail) > 0:
            # we should have a view in this case because we are matching routes
            await notify(TraversalViewMissEvent(request, tail))
            return None

        request.found_view = view
        request.view_name = view_name
        request.record('viewfound')

        ViewClass = view.__class__
        view_permission = get_view_permission(ViewClass)
        if not security.check_permission(view_permission, view):
            if IOPTIONS != method:
                raise HTTPUnauthorized(
                    content={
                        "reason": "You are not authorized to view",
                        "content": str(resource),
                        "auths": [x.principal.id
                                  for x in security.participations]
                    }
                )

        try:
            view.__route__.matches(request, tail or [])
        except (KeyError, IndexError):
            await notify(TraversalRouteMissEvent(request, tail))
            return None
        except AttributeError:
            pass

        if hasattr(view, 'prepare'):
            view = (await view.prepare()) or view

        request.record('authorization')

        return MatchInfo(resource, request, view)